blob: 8cce3c487ca92129f231c899c5cdac614fa5c56a [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>
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -08009#include <string.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +010010#include <json.h>
Thu Nguyene42fb482024-10-15 14:43:11 +000011#include <libcper/base64.h>
12#include <libcper/Cper.h>
13#include <libcper/cper-utils.h>
14#include <libcper/sections/cper-section-arm.h>
Ed Tanous50b966f2025-03-11 09:06:19 -070015#include <libcper/log.h>
Lawrence Tang2800cd82022-07-05 16:08:20 +010016
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010017//Private pre-definitions.
Lawrence Tange407b4c2022-07-21 13:54:01 +010018json_object *
19cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
20json_object *
21cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
Ed Tanous5e2164a2025-03-09 09:20:44 -070022 const UINT8 **cur_pos, UINT32 *remaining_size);
Lawrence Tange407b4c2022-07-21 13:54:01 +010023json_object *
24cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
25 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
26json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error);
27json_object *cper_arm_misc_register_array_to_ir(
28 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register);
29void ir_arm_error_info_to_cper(json_object *error_info, FILE *out);
30void ir_arm_context_info_to_cper(json_object *context_info, FILE *out);
31void ir_arm_error_cache_tlb_info_to_cper(
32 json_object *error_information,
33 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper);
34void ir_arm_error_bus_info_to_cper(json_object *error_information,
35 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper);
36void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out);
37void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out);
38void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out);
39void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out);
40void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out);
41void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out);
42void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out);
43void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out);
44void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out);
John Chungf8fc7052024-05-03 20:05:29 +080045void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010046
Lawrence Tang2800cd82022-07-05 16:08:20 +010047//Converts the given processor-generic CPER section into JSON IR.
Ed Tanous12dbd4f2025-03-08 19:05:01 -080048json_object *cper_section_arm_to_ir(const UINT8 *section, UINT32 size)
Lawrence Tang2800cd82022-07-05 16:08:20 +010049{
Ed Tanous5e2164a2025-03-09 09:20:44 -070050 const UINT8 *cur_pos = section;
51 UINT32 remaining_size = size;
52
53 if (remaining_size < sizeof(EFI_ARM_ERROR_RECORD)) {
Ed Tanous12dbd4f2025-03-08 19:05:01 -080054 return NULL;
55 }
Ed Tanous5e2164a2025-03-09 09:20:44 -070056 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)cur_pos;
57 cur_pos += sizeof(EFI_ARM_ERROR_RECORD);
58 remaining_size -= sizeof(EFI_ARM_ERROR_RECORD);
Lawrence Tange407b4c2022-07-21 13:54:01 +010059 json_object *section_ir = json_object_new_object();
Lawrence Tang2800cd82022-07-05 16:08:20 +010060
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080061 //Length of ValidationBits from spec
62 ValidationTypes ui64Type = { UINT_64T,
63 .value.ui64 = record->ValidFields };
Lawrence Tang2800cd82022-07-05 16:08:20 +010064
Lawrence Tange407b4c2022-07-21 13:54:01 +010065 //Number of error info and context info structures, and length.
66 json_object_object_add(section_ir, "errorInfoNum",
67 json_object_new_int(record->ErrInfoNum));
68 json_object_object_add(section_ir, "contextInfoNum",
69 json_object_new_int(record->ContextInfoNum));
70 json_object_object_add(section_ir, "sectionLength",
71 json_object_new_uint64(record->SectionLength));
Lawrence Tang2800cd82022-07-05 16:08:20 +010072
Lawrence Tange407b4c2022-07-21 13:54:01 +010073 //Error affinity.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080074 if (isvalid_prop_to_ir(&ui64Type, 1)) {
75 json_object *error_affinity = json_object_new_object();
76 json_object_object_add(
77 error_affinity, "value",
78 json_object_new_int(record->ErrorAffinityLevel));
79 json_object_object_add(
80 error_affinity, "type",
81 json_object_new_string(record->ErrorAffinityLevel < 4 ?
82 "Vendor Defined" :
83 "Reserved"));
84 json_object_object_add(section_ir, "errorAffinity",
85 error_affinity);
86 }
Lawrence Tang2800cd82022-07-05 16:08:20 +010087
Lawrence Tange407b4c2022-07-21 13:54:01 +010088 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080089 if (isvalid_prop_to_ir(&ui64Type, 0)) {
90 uint64_t mpidr_eli1 = record->MPIDR_EL1;
91 uint64_t sock;
92 json_object_object_add(section_ir, "mpidrEl1",
93 json_object_new_uint64(mpidr_eli1));
94
95 //Arm Processor socket info dependes on mpidr_eli1
96 sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32;
97 json_object_object_add(section_ir, "affinity3",
98 json_object_new_uint64(sock));
99 }
Aushim Nagarkatti17bc66a2024-11-25 13:47:35 -0800100
Lawrence Tange407b4c2022-07-21 13:54:01 +0100101 json_object_object_add(section_ir, "midrEl1",
102 json_object_new_uint64(record->MIDR_EL1));
Lawrence Tang2800cd82022-07-05 16:08:20 +0100103
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800104 if (isvalid_prop_to_ir(&ui64Type, 2)) {
105 //Whether the processor is running, and the state of it if so.
106 json_object_object_add(
107 section_ir, "running",
108 json_object_new_boolean(record->RunningState & 0x1));
109 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100110 if (!(record->RunningState >> 31)) {
111 //Bit 32 of running state is on, so PSCI state information is included.
112 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
113 //or the newer Extended StateID format.
114 json_object_object_add(
115 section_ir, "psciState",
116 json_object_new_uint64(record->PsciState));
117 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100118
Lawrence Tange407b4c2022-07-21 13:54:01 +0100119 //Processor error structures.
120 json_object *error_info_array = json_object_new_array();
121 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
122 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
Ed Tanous5e2164a2025-03-09 09:20:44 -0700123 if (remaining_size <
124 (record->ErrInfoNum * sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY))) {
125 json_object_put(error_info_array);
126 json_object_put(section_ir);
Ed Tanous50b966f2025-03-11 09:06:19 -0700127 cper_print_log(
128 "Invalid CPER file: Invalid processor error info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700129 return NULL;
130 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100131 for (int i = 0; i < record->ErrInfoNum; i++) {
132 json_object_array_add(error_info_array,
133 cper_arm_error_info_to_ir(cur_error));
134 cur_error++;
135 }
Ed Tanous5e2164a2025-03-09 09:20:44 -0700136
137 cur_pos += (UINT32)(record->ErrInfoNum *
138 sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY));
139 remaining_size -= (UINT32)(record->ErrInfoNum *
140 sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY));
141
Lawrence Tange407b4c2022-07-21 13:54:01 +0100142 json_object_object_add(section_ir, "errorInfo", error_info_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100143
Lawrence Tange407b4c2022-07-21 13:54:01 +0100144 //Processor context structures.
145 //The current position is moved within the processing, as it is a dynamic size structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100146 json_object *context_info_array = json_object_new_array();
147 for (int i = 0; i < record->ContextInfoNum; i++) {
Ed Tanous5e2164a2025-03-09 09:20:44 -0700148 if (remaining_size <
149 sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER)) {
150 json_object_put(context_info_array);
151 json_object_put(section_ir);
Ed Tanous50b966f2025-03-11 09:06:19 -0700152 cper_print_log(
153 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700154 return NULL;
155 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100156 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
157 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700158
159 cur_pos += sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER);
160 remaining_size -= sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100161 json_object *processor_context =
Ed Tanous5e2164a2025-03-09 09:20:44 -0700162 cper_arm_processor_context_to_ir(header, &cur_pos,
163 &remaining_size);
164 if (processor_context == NULL) {
165 json_object_put(context_info_array);
166 json_object_put(section_ir);
Ed Tanous50b966f2025-03-11 09:06:19 -0700167 cper_print_log(
168 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700169 return NULL;
170 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100171 json_object_array_add(context_info_array, processor_context);
172 }
173 json_object_object_add(section_ir, "contextInfo", context_info_array);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100174
Lawrence Tange407b4c2022-07-21 13:54:01 +0100175 //Is there any vendor-specific information following?
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800176 if (isvalid_prop_to_ir(&ui64Type, 3)) {
177 if (cur_pos < (uint8_t *)section + record->SectionLength) {
178 json_object *vendor_specific = json_object_new_object();
179 size_t input_size = (uint8_t *)section +
180 record->SectionLength - cur_pos;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700181 if (remaining_size < input_size) {
182 json_object_put(vendor_specific);
183 json_object_put(section_ir);
Ed Tanous50b966f2025-03-11 09:06:19 -0700184 cper_print_log(
185 "Invalid CPER file: Invalid vendor-specific info length.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700186 return NULL;
187 }
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800188 int32_t encoded_len = 0;
189 char *encoded = base64_encode(cur_pos, input_size,
190 &encoded_len);
191 if (encoded == NULL) {
Ed Tanous5e2164a2025-03-09 09:20:44 -0700192 json_object_put(vendor_specific);
193 json_object_put(section_ir);
Ed Tanous50b966f2025-03-11 09:06:19 -0700194 cper_print_log(
195 "base64 encode of vendorSpecificInfo failed\n");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800196 return NULL;
197 }
198 json_object_object_add(vendor_specific, "data",
199 json_object_new_string_len(
200 encoded, encoded_len));
201 free(encoded);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700202
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800203 json_object_object_add(section_ir, "vendorSpecificInfo",
204 vendor_specific);
205 } else {
Ed Tanous50b966f2025-03-11 09:06:19 -0700206 cper_print_log(
207 "vendorSpecificInfo is marked valid but not present in binary\n");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800208 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100209 }
210
211 return section_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100212}
213
214//Converts a single ARM Process Error Information structure into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100215json_object *
216cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100217{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100218 json_object *error_info_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100219
Lawrence Tange407b4c2022-07-21 13:54:01 +0100220 //Version, length.
221 json_object_object_add(error_info_ir, "version",
222 json_object_new_int(error_info->Version));
223 json_object_object_add(error_info_ir, "length",
224 json_object_new_int(error_info->Length));
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100225
Lawrence Tange407b4c2022-07-21 13:54:01 +0100226 //Validation bitfield.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800227 ValidationTypes ui16Type = { UINT_16T,
228 .value.ui16 = error_info->ValidationBits };
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100229
Lawrence Tange407b4c2022-07-21 13:54:01 +0100230 //The type of error information in this log.
231 json_object *error_type = integer_to_readable_pair(
232 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
233 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
234 json_object_object_add(error_info_ir, "errorType", error_type);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100235
Lawrence Tange407b4c2022-07-21 13:54:01 +0100236 //Multiple error count.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800237 if (isvalid_prop_to_ir(&ui16Type, 0)) {
238 json_object *multiple_error = json_object_new_object();
239 json_object_object_add(
240 multiple_error, "value",
241 json_object_new_int(error_info->MultipleError));
242 json_object_object_add(
243 multiple_error, "type",
244 json_object_new_string(error_info->MultipleError < 1 ?
245 "Single Error" :
246 "Multiple Errors"));
247 json_object_object_add(error_info_ir, "multipleError",
248 multiple_error);
249 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100250
Lawrence Tange407b4c2022-07-21 13:54:01 +0100251 //Flags.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800252 if (isvalid_prop_to_ir(&ui16Type, 1)) {
253 json_object *flags = bitfield_to_ir(
254 error_info->Flags, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
255 json_object_object_add(error_info_ir, "flags", flags);
256 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100257
Lawrence Tange407b4c2022-07-21 13:54:01 +0100258 //Error information, split by type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800259 if (isvalid_prop_to_ir(&ui16Type, 2)) {
260 json_object *error_subinfo = NULL;
261 switch (error_info->Type) {
262 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
263 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
264 error_subinfo = cper_arm_cache_tlb_error_to_ir(
265 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
266 ->ErrorInformation,
267 error_info);
268 break;
269 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
270 error_subinfo = cper_arm_bus_error_to_ir(
271 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
272 ->ErrorInformation);
273 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100274
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800275 default:
276 //Unknown/microarch, will not support.
277 break;
278 }
Ed Tanousd6b62632025-03-14 15:30:07 -0700279 if (error_subinfo != NULL) {
280 json_object_object_add(error_info_ir,
281 "errorInformation",
282 error_subinfo);
283 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100284 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100285
Lawrence Tange407b4c2022-07-21 13:54:01 +0100286 //Virtual fault address, physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800287 if (isvalid_prop_to_ir(&ui16Type, 3)) {
288 json_object_object_add(
289 error_info_ir, "virtualFaultAddress",
290 json_object_new_uint64(
291 error_info->VirtualFaultAddress));
292 }
293 if (isvalid_prop_to_ir(&ui16Type, 4)) {
294 json_object_object_add(
295 error_info_ir, "physicalFaultAddress",
296 json_object_new_uint64(
297 error_info->PhysicalFaultAddress));
298 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100299
300 return error_info_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100301}
302
Lawrence Tang7f21db62022-07-06 11:09:39 +0100303//Converts a single ARM cache/TLB error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100304json_object *
305cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
306 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100307{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100308 json_object *cache_tlb_error_ir = json_object_new_object();
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700309 json_object *cache_tlb_prop = json_object_new_object();
310 char *cache_tlb_propname;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100311
Lawrence Tange407b4c2022-07-21 13:54:01 +0100312 //Validation bitfield.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800313 ValidationTypes ui64Type = {
314 UINT_64T, .value.ui64 = cache_tlb_error->ValidationBits
315 };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100316
Lawrence Tange407b4c2022-07-21 13:54:01 +0100317 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800318 if (isvalid_prop_to_ir(&ui64Type, 0)) {
319 json_object *transaction_type = integer_to_readable_pair(
320 cache_tlb_error->TransactionType, 3,
321 ARM_ERROR_TRANSACTION_TYPES_KEYS,
322 ARM_ERROR_TRANSACTION_TYPES_VALUES,
323 "Unknown (Reserved)");
324 json_object_object_add(cache_tlb_error_ir, "transactionType",
325 transaction_type);
326 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100327
Lawrence Tange407b4c2022-07-21 13:54:01 +0100328 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800329 bool cacheErrorFlag = 1;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100330 if (error_info->Type == 0) {
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700331 cache_tlb_propname = "cacheError";
Lawrence Tange407b4c2022-07-21 13:54:01 +0100332 } else {
333 //TLB operation.
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700334 cache_tlb_propname = "tlbError";
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800335 cacheErrorFlag = 0;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100336 }
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800337
338 if (isvalid_prop_to_ir(&ui64Type, 1)) {
339 json_object *operation;
340
341 if (cacheErrorFlag) {
342 //Cache operation.
343 operation = integer_to_readable_pair(
344 cache_tlb_error->Operation, 11,
345 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
346 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
347 "Unknown (Reserved)");
348 } else {
349 operation = integer_to_readable_pair(
350 cache_tlb_error->Operation, 9,
351 ARM_TLB_OPERATION_TYPES_KEYS,
352 ARM_TLB_OPERATION_TYPES_VALUES,
353 "Unknown (Reserved)");
354 }
355 json_object_object_add(cache_tlb_error_ir, "operation",
356 operation);
357 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100358
Lawrence Tange407b4c2022-07-21 13:54:01 +0100359 //Miscellaneous remaining fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800360 if (isvalid_prop_to_ir(&ui64Type, 2)) {
361 json_object_object_add(
362 cache_tlb_error_ir, "level",
363 json_object_new_int(cache_tlb_error->Level));
364 }
365 if (isvalid_prop_to_ir(&ui64Type, 3)) {
366 json_object_object_add(
367 cache_tlb_error_ir, "processorContextCorrupt",
368 json_object_new_boolean(
369 cache_tlb_error->ProcessorContextCorrupt));
370 }
371 if (isvalid_prop_to_ir(&ui64Type, 4)) {
372 json_object_object_add(
373 cache_tlb_error_ir, "corrected",
374 json_object_new_boolean(cache_tlb_error->Corrected));
375 }
376 if (isvalid_prop_to_ir(&ui64Type, 5)) {
377 json_object_object_add(
378 cache_tlb_error_ir, "precisePC",
379 json_object_new_boolean(cache_tlb_error->PrecisePC));
380 }
381 if (isvalid_prop_to_ir(&ui64Type, 6)) {
382 json_object_object_add(cache_tlb_error_ir, "restartablePC",
383 json_object_new_boolean(
384 cache_tlb_error->RestartablePC));
385 }
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700386
387 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
388 cache_tlb_error_ir);
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800389
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700390 return cache_tlb_prop;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100391}
392
393//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100394json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100395{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100396 json_object *bus_error_ir = json_object_new_object();
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800397 json_object *bus_prop = json_object_new_object();
398 char *bus_propname = "busError";
Lawrence Tang7f21db62022-07-06 11:09:39 +0100399
Lawrence Tange407b4c2022-07-21 13:54:01 +0100400 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800401 ValidationTypes ui64Type = { UINT_64T,
402 .value.ui64 = bus_error->ValidationBits };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100403
Lawrence Tange407b4c2022-07-21 13:54:01 +0100404 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800405 if (isvalid_prop_to_ir(&ui64Type, 0)) {
406 json_object *transaction_type = integer_to_readable_pair(
407 bus_error->TransactionType, 3,
408 ARM_ERROR_TRANSACTION_TYPES_KEYS,
409 ARM_ERROR_TRANSACTION_TYPES_VALUES,
410 "Unknown (Reserved)");
411 json_object_object_add(bus_error_ir, "transactionType",
412 transaction_type);
413 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100414
Lawrence Tange407b4c2022-07-21 13:54:01 +0100415 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800416 if (isvalid_prop_to_ir(&ui64Type, 1)) {
417 json_object *operation = integer_to_readable_pair(
418 bus_error->Operation, 7,
419 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
420 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
421 "Unknown (Reserved)");
422 json_object_object_add(bus_error_ir, "operation", operation);
423 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100424
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800425 if (isvalid_prop_to_ir(&ui64Type, 2)) {
426 //Affinity level of bus error, + miscellaneous fields.
427 json_object_object_add(bus_error_ir, "level",
428 json_object_new_int(bus_error->Level));
429 }
430 if (isvalid_prop_to_ir(&ui64Type, 3)) {
431 json_object_object_add(
432 bus_error_ir, "processorContextCorrupt",
433 json_object_new_boolean(
434 bus_error->ProcessorContextCorrupt));
435 }
436 if (isvalid_prop_to_ir(&ui64Type, 4)) {
437 json_object_object_add(
438 bus_error_ir, "corrected",
439 json_object_new_boolean(bus_error->Corrected));
440 }
441 if (isvalid_prop_to_ir(&ui64Type, 5)) {
442 json_object_object_add(
443 bus_error_ir, "precisePC",
444 json_object_new_boolean(bus_error->PrecisePC));
445 }
446 if (isvalid_prop_to_ir(&ui64Type, 6)) {
447 json_object_object_add(
448 bus_error_ir, "restartablePC",
449 json_object_new_boolean(bus_error->RestartablePC));
450 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100451
Lawrence Tange407b4c2022-07-21 13:54:01 +0100452 //Participation type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800453 if (isvalid_prop_to_ir(&ui64Type, 7)) {
454 json_object *participation_type = integer_to_readable_pair(
455 bus_error->ParticipationType, 4,
456 ARM_BUS_PARTICIPATION_TYPES_KEYS,
457 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
458 json_object_object_add(bus_error_ir, "participationType",
459 participation_type);
460 }
461 if (isvalid_prop_to_ir(&ui64Type, 8)) {
462 json_object_object_add(
463 bus_error_ir, "timedOut",
464 json_object_new_boolean(bus_error->TimeOut));
465 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100466
Lawrence Tange407b4c2022-07-21 13:54:01 +0100467 //Address space.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800468 if (isvalid_prop_to_ir(&ui64Type, 9)) {
469 json_object *address_space = integer_to_readable_pair(
470 bus_error->AddressSpace, 3,
471 ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
472 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
473 json_object_object_add(bus_error_ir, "addressSpace",
474 address_space);
475 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100476
Lawrence Tange407b4c2022-07-21 13:54:01 +0100477 //Memory access attributes.
478 //todo: find the specification of these in the ARM ARM
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800479 if (isvalid_prop_to_ir(&ui64Type, 10)) {
480 json_object_object_add(
481 bus_error_ir, "memoryAttributes",
482 json_object_new_int(
483 bus_error->MemoryAddressAttributes));
484 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100485
Lawrence Tange407b4c2022-07-21 13:54:01 +0100486 //Access Mode
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800487 if (isvalid_prop_to_ir(&ui64Type, 8)) {
488 json_object *access_mode = json_object_new_object();
489 json_object_object_add(
490 access_mode, "value",
491 json_object_new_int(bus_error->AccessMode));
492 json_object_object_add(
493 access_mode, "name",
494 json_object_new_string(bus_error->AccessMode == 0 ?
495 "Secure" :
496 "Normal"));
497 json_object_object_add(bus_error_ir, "accessMode", access_mode);
498 }
499 json_object_object_add(bus_prop, bus_propname, bus_error_ir);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100500
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800501 return bus_prop;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100502}
503
504//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100505json_object *
506cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
Ed Tanous5e2164a2025-03-09 09:20:44 -0700507 const UINT8 **cur_pos, UINT32 *remaining_size)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100508{
Ed Tanous5e2164a2025-03-09 09:20:44 -0700509 if (header->RegisterArraySize > *remaining_size) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700510 cper_print_log(
511 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700512 return NULL;
513 }
514
Lawrence Tange407b4c2022-07-21 13:54:01 +0100515 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100516
Lawrence Tange407b4c2022-07-21 13:54:01 +0100517 //Version.
518 json_object_object_add(context_ir, "version",
519 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100520
Lawrence Tange407b4c2022-07-21 13:54:01 +0100521 //Add the context type.
522 json_object *context_type = integer_to_readable_pair(
Ed Tanous5e2164a2025-03-09 09:20:44 -0700523 header->RegisterContextType,
524 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_COUNT,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100525 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
526 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
527 "Unknown (Reserved)");
528 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100529
Lawrence Tange407b4c2022-07-21 13:54:01 +0100530 //Register array size (bytes).
531 json_object_object_add(
532 context_ir, "registerArraySize",
533 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100534
Lawrence Tange407b4c2022-07-21 13:54:01 +0100535 //The register array itself.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100536 json_object *register_array = NULL;
537 switch (header->RegisterContextType) {
538 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700539 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH32_GPR)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700540 cper_print_log(
541 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700542 goto fail;
543 }
544 if (header->RegisterArraySize <
545 sizeof(EFI_ARM_V8_AARCH32_GPR)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700546 cper_print_log(
547 "Invalid CPER file: Not enough bytes for aarch32 gpr\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700548 goto fail;
549 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100550 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800551 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100552 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
553 ARM_AARCH32_GPR_NAMES);
554 break;
555 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700556 if (*remaining_size <
557 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700558 cper_print_log(
559 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700560 goto fail;
561 }
562 if (header->RegisterArraySize <
563 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700564 cper_print_log(
565 "Invalid CPER file: Not enough bytes for aarch32 el1\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700566 goto fail;
567 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100568 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800569 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100570 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
571 sizeof(UINT32),
572 ARM_AARCH32_EL1_REGISTER_NAMES);
573 break;
574 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700575 if (*remaining_size <
576 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700577 cper_print_log(
578 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700579 goto fail;
580 }
581 if (header->RegisterArraySize <
582 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700583 cper_print_log(
584 "Invalid CPER file: Not enough bytes for aarch32 el2\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700585 goto fail;
586 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100587 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800588 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100589 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
590 sizeof(UINT32),
591 ARM_AARCH32_EL2_REGISTER_NAMES);
Ed Tanous5e2164a2025-03-09 09:20:44 -0700592
Lawrence Tange407b4c2022-07-21 13:54:01 +0100593 break;
594 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700595 if (*remaining_size <
596 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) {
597 json_object_put(context_ir);
Ed Tanous50b966f2025-03-11 09:06:19 -0700598 cper_print_log(
599 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700600 return NULL;
601 }
602 if (header->RegisterArraySize <
603 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700604 cper_print_log(
605 "Invalid CPER file: Not enough bytes for aarch32 secure\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700606 goto fail;
607 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100608 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800609 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100610 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
611 sizeof(UINT32),
612 ARM_AARCH32_SECURE_REGISTER_NAMES);
613 break;
614 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700615 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH64_GPR)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700616 cper_print_log(
617 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700618 goto fail;
619 }
620 if (header->RegisterArraySize <
621 sizeof(EFI_ARM_V8_AARCH64_GPR)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700622 cper_print_log(
623 "Invalid CPER file: Not enough bytes for aarch64 gpr\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700624 goto fail;
625 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100626 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800627 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100628 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
629 ARM_AARCH64_GPR_NAMES);
630 break;
631 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700632 if (*remaining_size <
633 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700634 cper_print_log(
635 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700636 goto fail;
637 }
638 if (header->RegisterArraySize <
639 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700640 cper_print_log(
641 "Invalid CPER file: Not enough bytes for aarch64 el1\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700642 goto fail;
643 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100644 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800645 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100646 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
647 sizeof(UINT64),
648 ARM_AARCH64_EL1_REGISTER_NAMES);
649 break;
650 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700651 if (*remaining_size <
652 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700653 cper_print_log(
654 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700655 goto fail;
656 }
657 if (header->RegisterArraySize <
658 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700659 cper_print_log(
660 "Invalid CPER file: Not enough bytes for aarch64 el2\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700661 goto fail;
662 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100663 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800664 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100665 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
666 sizeof(UINT64),
667 ARM_AARCH64_EL2_REGISTER_NAMES);
668 break;
669 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700670 if (*remaining_size <
671 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700672 cper_print_log(
673 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700674 goto fail;
675 }
676 if (header->RegisterArraySize <
677 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700678 cper_print_log(
679 "Invalid CPER file: Not enough bytes for aarch64 el3\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700680 goto fail;
681 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100682 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800683 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100684 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
685 sizeof(UINT64),
686 ARM_AARCH64_EL3_REGISTER_NAMES);
687 break;
688 case EFI_ARM_CONTEXT_TYPE_MISC:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700689 if (*remaining_size < sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700690 cper_print_log(
691 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700692 goto fail;
693 }
694 if (header->RegisterArraySize <
695 sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700696 cper_print_log(
697 "Invalid CPER file: Not enough bytes for misc\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700698 goto fail;
699 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100700 register_array = cper_arm_misc_register_array_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800701 (EFI_ARM_MISC_CONTEXT_REGISTER *)*cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100702 break;
703 default:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700704 if (*remaining_size < header->RegisterArraySize) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700705 cper_print_log(
706 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700707 goto fail;
708 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100709 //Unknown register array type, add as base64 data instead.
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700710 int32_t encoded_len = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800711 char *encoded = base64_encode((UINT8 *)*cur_pos,
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700712 header->RegisterArraySize,
713 &encoded_len);
714 if (encoded == NULL) {
Ed Tanous5e2164a2025-03-09 09:20:44 -0700715 goto fail;
John Chungf8fc7052024-05-03 20:05:29 +0800716 }
Ed Tanous5e2164a2025-03-09 09:20:44 -0700717 register_array = json_object_new_object();
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700718 json_object_object_add(register_array, "data",
719 json_object_new_string_len(encoded,
720 encoded_len));
721 free(encoded);
722
Lawrence Tange407b4c2022-07-21 13:54:01 +0100723 break;
724 }
725 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100726
Lawrence Tange407b4c2022-07-21 13:54:01 +0100727 //Set the current position to after the processor context structure.
728 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700729 *remaining_size -= header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100730
Lawrence Tange407b4c2022-07-21 13:54:01 +0100731 return context_ir;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700732
733fail:
734 json_object_put(context_ir);
735 return NULL;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100736}
737
738//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100739json_object *
740cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100741{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100742 json_object *register_array = json_object_new_object();
743 json_object *mrs_encoding = json_object_new_object();
744 json_object_object_add(mrs_encoding, "op2",
745 json_object_new_uint64(misc_register->MrsOp2));
746 json_object_object_add(mrs_encoding, "crm",
747 json_object_new_uint64(misc_register->MrsCrm));
748 json_object_object_add(mrs_encoding, "crn",
749 json_object_new_uint64(misc_register->MrsCrn));
750 json_object_object_add(mrs_encoding, "op1",
751 json_object_new_uint64(misc_register->MrsOp1));
752 json_object_object_add(mrs_encoding, "o0",
753 json_object_new_uint64(misc_register->MrsO0));
754 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
755 json_object_object_add(register_array, "value",
756 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100757
Lawrence Tange407b4c2022-07-21 13:54:01 +0100758 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100759}
760
761//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100762void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100763{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800764 EFI_ARM_ERROR_RECORD section_cper;
765 memset(&section_cper, 0, sizeof(section_cper));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100766
Lawrence Tange407b4c2022-07-21 13:54:01 +0100767 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800768 struct json_object *obj = NULL;
769 ValidationTypes u32Type = { UINT_32T, .value.ui32 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100770
Lawrence Tange407b4c2022-07-21 13:54:01 +0100771 //Count of error/context info structures.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800772 section_cper.ErrInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100773 json_object_object_get(section, "errorInfoNum"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800774 section_cper.ContextInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100775 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100776
Lawrence Tange407b4c2022-07-21 13:54:01 +0100777 //Miscellaneous raw value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800778 section_cper.SectionLength = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100779 json_object_object_get(section, "sectionLength"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800780 if (json_object_object_get_ex(section, "mpidrEl1", &obj)) {
781 section_cper.MPIDR_EL1 = json_object_get_uint64(obj);
782 add_to_valid_bitfield(&u32Type, 0);
783 }
784 if (json_object_object_get_ex(section, "errorAffinity", &obj)) {
785 section_cper.ErrorAffinityLevel = readable_pair_to_integer(obj);
786 add_to_valid_bitfield(&u32Type, 1);
787 }
788 section_cper.MIDR_EL1 = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100789 json_object_object_get(section, "midrEl1"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800790 if (json_object_object_get_ex(section, "running", &obj)) {
791 section_cper.RunningState = json_object_get_boolean(obj);
792 add_to_valid_bitfield(&u32Type, 2);
793 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100794
Lawrence Tange407b4c2022-07-21 13:54:01 +0100795 //Optional PSCI state.
796 json_object *psci_state = json_object_object_get(section, "psciState");
John Chungf8fc7052024-05-03 20:05:29 +0800797 if (psci_state != NULL) {
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800798 section_cper.PsciState = json_object_get_uint64(psci_state);
John Chungf8fc7052024-05-03 20:05:29 +0800799 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100800
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800801 //Validationbits for EFI_ARM_ERROR_RECORD should also consider vendorSpecificInfo
802 bool vendorSpecificPresent =
803 json_object_object_get_ex(section, "vendorSpecificInfo", &obj);
804 json_object *vendor_specific_info = obj;
805 if (vendorSpecificPresent) {
806 add_to_valid_bitfield(&u32Type, 3);
807 }
808
809 section_cper.ValidFields = u32Type.value.ui32;
810
Lawrence Tange407b4c2022-07-21 13:54:01 +0100811 //Flush header to stream.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800812 fwrite(&section_cper, sizeof(section_cper), 1, out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100813
Lawrence Tange407b4c2022-07-21 13:54:01 +0100814 //Error info structure array.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800815
Lawrence Tange407b4c2022-07-21 13:54:01 +0100816 json_object *error_info = json_object_object_get(section, "errorInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800817 for (int i = 0; i < section_cper.ErrInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100818 ir_arm_error_info_to_cper(
819 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800820 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100821
Lawrence Tange407b4c2022-07-21 13:54:01 +0100822 //Context info structure array.
823 json_object *context_info =
824 json_object_object_get(section, "contextInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800825 for (int i = 0; i < section_cper.ContextInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100826 ir_arm_context_info_to_cper(
827 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800828 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100829
Lawrence Tange407b4c2022-07-21 13:54:01 +0100830 //Vendor specific error info.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800831 if (vendorSpecificPresent) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100832 json_object *vendor_info_string =
833 json_object_object_get(vendor_specific_info, "data");
834 int vendor_specific_len =
835 json_object_get_string_len(vendor_info_string);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100836
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700837 int32_t decoded_len = 0;
838
839 UINT8 *decoded = base64_decode(
840 json_object_get_string(vendor_info_string),
841 vendor_specific_len, &decoded_len);
842
843 //Write out to file.
844 fwrite(decoded, decoded_len, 1, out);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700845 free(decoded);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100846 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100847
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800848 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100849}
850
851//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100852void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100853{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100854 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800855 memset(&error_info_cper, 0, sizeof(error_info_cper));
856 struct json_object *obj = NULL;
857 ValidationTypes ui16Type = { UINT_16T, .value.ui16 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100858
Lawrence Tange407b4c2022-07-21 13:54:01 +0100859 //Version, length.
860 error_info_cper.Version = json_object_get_int(
861 json_object_object_get(error_info, "version"));
862 error_info_cper.Length = json_object_get_int(
863 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100864
Lawrence Tange407b4c2022-07-21 13:54:01 +0100865 //Type, multiple error.
866 error_info_cper.Type = (UINT8)readable_pair_to_integer(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800867 json_object_object_get(error_info, "errorType"));
868
869 if (json_object_object_get_ex(error_info, "multipleError", &obj)) {
870 error_info_cper.MultipleError =
871 (UINT16)readable_pair_to_integer(obj);
872 add_to_valid_bitfield(&ui16Type, 0);
873 } else {
874 error_info_cper.MultipleError = 0;
875 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100876
Lawrence Tange407b4c2022-07-21 13:54:01 +0100877 //Flags object.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800878 if (json_object_object_get_ex(error_info, "flags", &obj)) {
879 error_info_cper.Flags = (UINT8)ir_to_bitfield(
880 obj, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
881 add_to_valid_bitfield(&ui16Type, 1);
882 } else {
883 error_info_cper.Flags = 0;
884 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100885
Lawrence Tange407b4c2022-07-21 13:54:01 +0100886 //Error information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800887 if (json_object_object_get_ex(error_info, "errorInformation", &obj)) {
888 json_object *error_info_information = obj;
889 json_object *error_info_prop = NULL;
890 switch (error_info_cper.Type) {
891 case ARM_ERROR_INFORMATION_TYPE_CACHE:
892 error_info_cper.ErrorInformation.Value = 0;
893 error_info_prop = json_object_object_get(
894 error_info_information, "cacheError");
895 ir_arm_error_cache_tlb_info_to_cper(
896 error_info_prop,
897 &error_info_cper.ErrorInformation.CacheError);
898 break;
899 case ARM_ERROR_INFORMATION_TYPE_TLB:
900 error_info_cper.ErrorInformation.Value = 0;
901 error_info_prop = json_object_object_get(
902 error_info_information, "tlbError");
903 ir_arm_error_cache_tlb_info_to_cper(
904 error_info_prop,
905 &error_info_cper.ErrorInformation.CacheError);
906 break;
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700907
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800908 case ARM_ERROR_INFORMATION_TYPE_BUS:
909 error_info_cper.ErrorInformation.Value = 0;
910 error_info_prop = json_object_object_get(
911 error_info_information, "busError");
912 ir_arm_error_bus_info_to_cper(
913 error_info_prop,
914 &error_info_cper.ErrorInformation.BusError);
915 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100916
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800917 default:
918 //Unknown error information type.
919 break;
920 }
921 add_to_valid_bitfield(&ui16Type, 2);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100922 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100923
Lawrence Tange407b4c2022-07-21 13:54:01 +0100924 //Virtual/physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800925 if (json_object_object_get_ex(error_info, "virtualFaultAddress",
926 &obj)) {
927 error_info_cper.VirtualFaultAddress =
928 json_object_get_uint64(obj);
929 add_to_valid_bitfield(&ui16Type, 3);
930 } else {
931 error_info_cper.VirtualFaultAddress = 0;
932 }
933
934 if (json_object_object_get_ex(error_info, "physicalFaultAddress",
935 &obj)) {
936 error_info_cper.PhysicalFaultAddress =
937 json_object_get_uint64(obj);
938 add_to_valid_bitfield(&ui16Type, 4);
939 } else {
940 error_info_cper.PhysicalFaultAddress = 0;
941 }
942 error_info_cper.ValidationBits = ui16Type.value.ui16;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100943
Lawrence Tange407b4c2022-07-21 13:54:01 +0100944 //Write out to stream.
945 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
946 out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100947}
948
Lawrence Tang71570a22022-07-14 11:45:28 +0100949//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100950void ir_arm_error_cache_tlb_info_to_cper(
951 json_object *error_information,
952 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100953{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800954 // //Validation bits.
955 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
956 struct json_object *obj = NULL;
Lawrence Tang71570a22022-07-14 11:45:28 +0100957
Lawrence Tange407b4c2022-07-21 13:54:01 +0100958 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800959 if (json_object_object_get_ex(error_information, "transactionType",
960 &obj)) {
961 error_info_cper->TransactionType =
962 readable_pair_to_integer(obj);
963 add_to_valid_bitfield(&ui64Type, 0);
964 }
965 if (json_object_object_get_ex(error_information, "operation", &obj)) {
966 error_info_cper->Operation = readable_pair_to_integer(obj);
967 add_to_valid_bitfield(&ui64Type, 1);
968 }
969 if (json_object_object_get_ex(error_information, "level", &obj)) {
970 error_info_cper->Level = json_object_get_uint64(obj);
971 add_to_valid_bitfield(&ui64Type, 2);
972 }
973 if (json_object_object_get_ex(error_information,
974 "processorContextCorrupt", &obj)) {
975 error_info_cper->ProcessorContextCorrupt =
976 json_object_get_boolean(obj);
977 add_to_valid_bitfield(&ui64Type, 3);
978 }
979 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
980 error_info_cper->Corrected = json_object_get_boolean(obj);
981 add_to_valid_bitfield(&ui64Type, 4);
982 }
983 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
984 error_info_cper->PrecisePC = json_object_get_boolean(obj);
985 add_to_valid_bitfield(&ui64Type, 5);
986 }
987 if (json_object_object_get_ex(error_information, "restartablePC",
988 &obj)) {
989 error_info_cper->RestartablePC = json_object_get_boolean(obj);
990 add_to_valid_bitfield(&ui64Type, 6);
991 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100992 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800993 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +0100994}
995
996//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100997void ir_arm_error_bus_info_to_cper(json_object *error_information,
998 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100999{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001000 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -08001001 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
1002 struct json_object *obj = NULL;
1003
1004 memset(error_info_cper, 0, sizeof(EFI_ARM_BUS_ERROR_STRUCTURE));
Lawrence Tang71570a22022-07-14 11:45:28 +01001005
Lawrence Tange407b4c2022-07-21 13:54:01 +01001006 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -08001007 if (json_object_object_get_ex(error_information, "transactionType",
1008 &obj)) {
1009 error_info_cper->TransactionType =
1010 readable_pair_to_integer(obj);
1011 add_to_valid_bitfield(&ui64Type, 0);
1012 } else {
1013 error_info_cper->TransactionType = 0;
1014 }
1015 if (json_object_object_get_ex(error_information, "operation", &obj)) {
1016 error_info_cper->Operation = readable_pair_to_integer(obj);
1017 add_to_valid_bitfield(&ui64Type, 1);
1018 } else {
1019 error_info_cper->Operation = 0;
1020 }
1021 if (json_object_object_get_ex(error_information, "level", &obj)) {
1022 error_info_cper->Level = json_object_get_uint64(obj);
1023 add_to_valid_bitfield(&ui64Type, 2);
1024 } else {
1025 error_info_cper->Level = 0;
1026 }
1027 if (json_object_object_get_ex(error_information,
1028 "processorContextCorrupt", &obj)) {
1029 error_info_cper->ProcessorContextCorrupt =
1030 json_object_get_boolean(obj);
1031 add_to_valid_bitfield(&ui64Type, 3);
1032 } else {
1033 error_info_cper->ProcessorContextCorrupt = 0;
1034 }
1035 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
1036 error_info_cper->Corrected = json_object_get_boolean(obj);
1037 add_to_valid_bitfield(&ui64Type, 4);
1038 } else {
1039 error_info_cper->Corrected = 0;
1040 }
1041 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
1042 error_info_cper->PrecisePC = json_object_get_boolean(obj);
1043 add_to_valid_bitfield(&ui64Type, 5);
1044 } else {
1045 error_info_cper->PrecisePC = 0;
1046 }
1047 if (json_object_object_get_ex(error_information, "restartablePC",
1048 &obj)) {
1049 error_info_cper->RestartablePC = json_object_get_boolean(obj);
1050 add_to_valid_bitfield(&ui64Type, 6);
1051 } else {
1052 error_info_cper->RestartablePC = 0;
1053 }
1054 if (json_object_object_get_ex(error_information, "participationType",
1055 &obj)) {
1056 error_info_cper->ParticipationType =
1057 readable_pair_to_integer(obj);
1058 add_to_valid_bitfield(&ui64Type, 7);
1059 } else {
1060 error_info_cper->ParticipationType = 0;
1061 }
1062 if (json_object_object_get_ex(error_information, "timedOut", &obj)) {
1063 error_info_cper->TimeOut = json_object_get_boolean(obj);
1064 add_to_valid_bitfield(&ui64Type, 8);
1065 } else {
1066 error_info_cper->TimeOut = 0;
1067 }
1068 if (json_object_object_get_ex(error_information, "addressSpace",
1069 &obj)) {
1070 error_info_cper->AddressSpace = readable_pair_to_integer(obj);
1071 add_to_valid_bitfield(&ui64Type, 9);
1072 } else {
1073 error_info_cper->AddressSpace = 0;
1074 }
1075 if (json_object_object_get_ex(error_information, "accessMode", &obj)) {
1076 error_info_cper->AccessMode = readable_pair_to_integer(obj);
1077 add_to_valid_bitfield(&ui64Type, 11);
1078 } else {
1079 error_info_cper->AccessMode = 0;
1080 }
1081 if (json_object_object_get_ex(error_information, "memoryAttributes",
1082 &obj)) {
1083 error_info_cper->MemoryAddressAttributes =
1084 json_object_get_uint64(obj);
1085 add_to_valid_bitfield(&ui64Type, 10);
1086 } else {
1087 error_info_cper->MemoryAddressAttributes = 0;
1088 }
Lawrence Tange407b4c2022-07-21 13:54:01 +01001089 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -08001090 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +01001091}
1092
Lawrence Tang7cd13902022-07-13 16:59:25 +01001093//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001094void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +01001095{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001096 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +01001097
Lawrence Tange407b4c2022-07-21 13:54:01 +01001098 //Version, array size, context type.
1099 info_header.Version = json_object_get_int(
1100 json_object_object_get(context_info, "version"));
1101 info_header.RegisterArraySize = json_object_get_int(
1102 json_object_object_get(context_info, "registerArraySize"));
1103 info_header.RegisterContextType = readable_pair_to_integer(
1104 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001105
Lawrence Tange407b4c2022-07-21 13:54:01 +01001106 //Flush to stream, write the register array itself.
1107 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
1108 out);
1109 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001110
Lawrence Tange407b4c2022-07-21 13:54:01 +01001111 json_object *register_array =
1112 json_object_object_get(context_info, "registerArray");
1113 switch (info_header.RegisterContextType) {
1114 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
1115 ir_arm_aarch32_gpr_to_cper(register_array, out);
1116 break;
1117 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
1118 ir_arm_aarch32_el1_to_cper(register_array, out);
1119 break;
1120 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
1121 ir_arm_aarch32_el2_to_cper(register_array, out);
1122 break;
1123 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
1124 ir_arm_aarch32_secure_to_cper(register_array, out);
1125 break;
1126 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
1127 ir_arm_aarch64_gpr_to_cper(register_array, out);
1128 break;
1129 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
1130 ir_arm_aarch64_el1_to_cper(register_array, out);
1131 break;
1132 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
1133 ir_arm_aarch64_el2_to_cper(register_array, out);
1134 break;
1135 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
1136 ir_arm_aarch64_el3_to_cper(register_array, out);
1137 break;
1138 case EFI_ARM_CONTEXT_TYPE_MISC:
1139 ir_arm_misc_registers_to_cper(register_array, out);
1140 break;
1141 default:
1142 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +08001143 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +01001144 break;
1145 }
Lawrence Tang71570a22022-07-14 11:45:28 +01001146}
1147
1148//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001149void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001150{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001151 //Get uniform register array.
1152 EFI_ARM_V8_AARCH32_GPR reg_array;
1153 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1154 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
1155 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001156
Lawrence Tange407b4c2022-07-21 13:54:01 +01001157 //Flush to stream.
1158 fwrite(&reg_array, sizeof(reg_array), 1, out);
1159 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001160}
1161
1162//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 +01001163void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001164{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001165 //Get uniform register array.
1166 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
1167 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1168 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
1169 sizeof(UINT32),
1170 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001171
Lawrence Tange407b4c2022-07-21 13:54:01 +01001172 //Flush to stream.
1173 fwrite(&reg_array, sizeof(reg_array), 1, out);
1174 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001175}
1176
1177//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 +01001178void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001179{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001180 //Get uniform register array.
1181 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
1182 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1183 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
1184 sizeof(UINT32),
1185 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001186
Lawrence Tange407b4c2022-07-21 13:54:01 +01001187 //Flush to stream.
1188 fwrite(&reg_array, sizeof(reg_array), 1, out);
1189 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001190}
1191
1192//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 +01001193void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001194{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001195 //Get uniform register array.
1196 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
1197 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1198 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
1199 sizeof(UINT32),
1200 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001201
Lawrence Tange407b4c2022-07-21 13:54:01 +01001202 //Flush to stream.
1203 fwrite(&reg_array, sizeof(reg_array), 1, out);
1204 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001205}
1206
1207//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001208void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001209{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001210 //Get uniform register array.
1211 EFI_ARM_V8_AARCH64_GPR reg_array;
1212 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1213 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
1214 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001215
Lawrence Tange407b4c2022-07-21 13:54:01 +01001216 //Flush to stream.
1217 fwrite(&reg_array, sizeof(reg_array), 1, out);
1218 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001219}
1220
1221//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 +01001222void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001223{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001224 //Get uniform register array.
1225 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
1226 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1227 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
1228 sizeof(UINT64),
1229 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001230
Lawrence Tange407b4c2022-07-21 13:54:01 +01001231 //Flush to stream.
1232 fwrite(&reg_array, sizeof(reg_array), 1, out);
1233 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001234}
1235
1236//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 +01001237void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001238{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001239 //Get uniform register array.
1240 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
1241 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1242 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
1243 sizeof(UINT64),
1244 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001245
Lawrence Tange407b4c2022-07-21 13:54:01 +01001246 //Flush to stream.
1247 fwrite(&reg_array, sizeof(reg_array), 1, out);
1248 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001249}
1250
1251//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 +01001252void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001253{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001254 //Get uniform register array.
1255 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
1256 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1257 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
1258 sizeof(UINT64),
1259 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001260
Lawrence Tange407b4c2022-07-21 13:54:01 +01001261 //Flush to stream.
1262 fwrite(&reg_array, sizeof(reg_array), 1, out);
1263 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001264}
1265
1266//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 +01001267void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001268{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001269 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +01001270
Lawrence Tange407b4c2022-07-21 13:54:01 +01001271 //MRS encoding information.
1272 json_object *mrs_encoding =
1273 json_object_object_get(registers, "mrsEncoding");
1274 reg_array.MrsOp2 = json_object_get_uint64(
1275 json_object_object_get(mrs_encoding, "op2"));
1276 reg_array.MrsCrm = json_object_get_uint64(
1277 json_object_object_get(mrs_encoding, "crm"));
1278 reg_array.MrsCrn = json_object_get_uint64(
1279 json_object_object_get(mrs_encoding, "crn"));
1280 reg_array.MrsOp1 = json_object_get_uint64(
1281 json_object_object_get(mrs_encoding, "op1"));
1282 reg_array.MrsO0 = json_object_get_uint64(
1283 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001284
Lawrence Tange407b4c2022-07-21 13:54:01 +01001285 //Actual register value.
1286 reg_array.Value = json_object_get_uint64(
1287 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001288
Lawrence Tange407b4c2022-07-21 13:54:01 +01001289 //Flush to stream.
1290 fwrite(&reg_array, sizeof(reg_array), 1, out);
1291 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001292}
1293
1294//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +08001295void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001296{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001297 //Get base64 represented data.
1298 json_object *encoded = json_object_object_get(registers, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -07001299
1300 int32_t decoded_len = 0;
1301
1302 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
1303 json_object_get_string_len(encoded),
1304 &decoded_len);
1305
1306 if (decoded == NULL) {
Ed Tanous50b966f2025-03-11 09:06:19 -07001307 cper_print_log("Failed to allocate decode output buffer. \n");
John Chungf8fc7052024-05-03 20:05:29 +08001308 } else {
John Chungf8fc7052024-05-03 20:05:29 +08001309 //Flush out to stream.
1310 fwrite(&decoded, decoded_len, 1, out);
1311 fflush(out);
1312 free(decoded);
1313 }
1314}