blob: 6961d165c48c6d574bb8cb99a09e5c328e42fec9 [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 }
279 json_object_object_add(error_info_ir, "errorInformation",
280 error_subinfo);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100281 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100282
Lawrence Tange407b4c2022-07-21 13:54:01 +0100283 //Virtual fault address, physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800284 if (isvalid_prop_to_ir(&ui16Type, 3)) {
285 json_object_object_add(
286 error_info_ir, "virtualFaultAddress",
287 json_object_new_uint64(
288 error_info->VirtualFaultAddress));
289 }
290 if (isvalid_prop_to_ir(&ui16Type, 4)) {
291 json_object_object_add(
292 error_info_ir, "physicalFaultAddress",
293 json_object_new_uint64(
294 error_info->PhysicalFaultAddress));
295 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100296
297 return error_info_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100298}
299
Lawrence Tang7f21db62022-07-06 11:09:39 +0100300//Converts a single ARM cache/TLB error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100301json_object *
302cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
303 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100304{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100305 json_object *cache_tlb_error_ir = json_object_new_object();
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700306 json_object *cache_tlb_prop = json_object_new_object();
307 char *cache_tlb_propname;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100308
Lawrence Tange407b4c2022-07-21 13:54:01 +0100309 //Validation bitfield.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800310 ValidationTypes ui64Type = {
311 UINT_64T, .value.ui64 = cache_tlb_error->ValidationBits
312 };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100313
Lawrence Tange407b4c2022-07-21 13:54:01 +0100314 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800315 if (isvalid_prop_to_ir(&ui64Type, 0)) {
316 json_object *transaction_type = integer_to_readable_pair(
317 cache_tlb_error->TransactionType, 3,
318 ARM_ERROR_TRANSACTION_TYPES_KEYS,
319 ARM_ERROR_TRANSACTION_TYPES_VALUES,
320 "Unknown (Reserved)");
321 json_object_object_add(cache_tlb_error_ir, "transactionType",
322 transaction_type);
323 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100324
Lawrence Tange407b4c2022-07-21 13:54:01 +0100325 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800326 bool cacheErrorFlag = 1;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100327 if (error_info->Type == 0) {
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700328 cache_tlb_propname = "cacheError";
Lawrence Tange407b4c2022-07-21 13:54:01 +0100329 } else {
330 //TLB operation.
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700331 cache_tlb_propname = "tlbError";
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800332 cacheErrorFlag = 0;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100333 }
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800334
335 if (isvalid_prop_to_ir(&ui64Type, 1)) {
336 json_object *operation;
337
338 if (cacheErrorFlag) {
339 //Cache operation.
340 operation = integer_to_readable_pair(
341 cache_tlb_error->Operation, 11,
342 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
343 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
344 "Unknown (Reserved)");
345 } else {
346 operation = integer_to_readable_pair(
347 cache_tlb_error->Operation, 9,
348 ARM_TLB_OPERATION_TYPES_KEYS,
349 ARM_TLB_OPERATION_TYPES_VALUES,
350 "Unknown (Reserved)");
351 }
352 json_object_object_add(cache_tlb_error_ir, "operation",
353 operation);
354 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100355
Lawrence Tange407b4c2022-07-21 13:54:01 +0100356 //Miscellaneous remaining fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800357 if (isvalid_prop_to_ir(&ui64Type, 2)) {
358 json_object_object_add(
359 cache_tlb_error_ir, "level",
360 json_object_new_int(cache_tlb_error->Level));
361 }
362 if (isvalid_prop_to_ir(&ui64Type, 3)) {
363 json_object_object_add(
364 cache_tlb_error_ir, "processorContextCorrupt",
365 json_object_new_boolean(
366 cache_tlb_error->ProcessorContextCorrupt));
367 }
368 if (isvalid_prop_to_ir(&ui64Type, 4)) {
369 json_object_object_add(
370 cache_tlb_error_ir, "corrected",
371 json_object_new_boolean(cache_tlb_error->Corrected));
372 }
373 if (isvalid_prop_to_ir(&ui64Type, 5)) {
374 json_object_object_add(
375 cache_tlb_error_ir, "precisePC",
376 json_object_new_boolean(cache_tlb_error->PrecisePC));
377 }
378 if (isvalid_prop_to_ir(&ui64Type, 6)) {
379 json_object_object_add(cache_tlb_error_ir, "restartablePC",
380 json_object_new_boolean(
381 cache_tlb_error->RestartablePC));
382 }
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700383
384 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
385 cache_tlb_error_ir);
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800386
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700387 return cache_tlb_prop;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100388}
389
390//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100391json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100392{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100393 json_object *bus_error_ir = json_object_new_object();
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800394 json_object *bus_prop = json_object_new_object();
395 char *bus_propname = "busError";
Lawrence Tang7f21db62022-07-06 11:09:39 +0100396
Lawrence Tange407b4c2022-07-21 13:54:01 +0100397 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800398 ValidationTypes ui64Type = { UINT_64T,
399 .value.ui64 = bus_error->ValidationBits };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100400
Lawrence Tange407b4c2022-07-21 13:54:01 +0100401 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800402 if (isvalid_prop_to_ir(&ui64Type, 0)) {
403 json_object *transaction_type = integer_to_readable_pair(
404 bus_error->TransactionType, 3,
405 ARM_ERROR_TRANSACTION_TYPES_KEYS,
406 ARM_ERROR_TRANSACTION_TYPES_VALUES,
407 "Unknown (Reserved)");
408 json_object_object_add(bus_error_ir, "transactionType",
409 transaction_type);
410 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100411
Lawrence Tange407b4c2022-07-21 13:54:01 +0100412 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800413 if (isvalid_prop_to_ir(&ui64Type, 1)) {
414 json_object *operation = integer_to_readable_pair(
415 bus_error->Operation, 7,
416 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
417 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
418 "Unknown (Reserved)");
419 json_object_object_add(bus_error_ir, "operation", operation);
420 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100421
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800422 if (isvalid_prop_to_ir(&ui64Type, 2)) {
423 //Affinity level of bus error, + miscellaneous fields.
424 json_object_object_add(bus_error_ir, "level",
425 json_object_new_int(bus_error->Level));
426 }
427 if (isvalid_prop_to_ir(&ui64Type, 3)) {
428 json_object_object_add(
429 bus_error_ir, "processorContextCorrupt",
430 json_object_new_boolean(
431 bus_error->ProcessorContextCorrupt));
432 }
433 if (isvalid_prop_to_ir(&ui64Type, 4)) {
434 json_object_object_add(
435 bus_error_ir, "corrected",
436 json_object_new_boolean(bus_error->Corrected));
437 }
438 if (isvalid_prop_to_ir(&ui64Type, 5)) {
439 json_object_object_add(
440 bus_error_ir, "precisePC",
441 json_object_new_boolean(bus_error->PrecisePC));
442 }
443 if (isvalid_prop_to_ir(&ui64Type, 6)) {
444 json_object_object_add(
445 bus_error_ir, "restartablePC",
446 json_object_new_boolean(bus_error->RestartablePC));
447 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100448
Lawrence Tange407b4c2022-07-21 13:54:01 +0100449 //Participation type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800450 if (isvalid_prop_to_ir(&ui64Type, 7)) {
451 json_object *participation_type = integer_to_readable_pair(
452 bus_error->ParticipationType, 4,
453 ARM_BUS_PARTICIPATION_TYPES_KEYS,
454 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
455 json_object_object_add(bus_error_ir, "participationType",
456 participation_type);
457 }
458 if (isvalid_prop_to_ir(&ui64Type, 8)) {
459 json_object_object_add(
460 bus_error_ir, "timedOut",
461 json_object_new_boolean(bus_error->TimeOut));
462 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100463
Lawrence Tange407b4c2022-07-21 13:54:01 +0100464 //Address space.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800465 if (isvalid_prop_to_ir(&ui64Type, 9)) {
466 json_object *address_space = integer_to_readable_pair(
467 bus_error->AddressSpace, 3,
468 ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
469 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
470 json_object_object_add(bus_error_ir, "addressSpace",
471 address_space);
472 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100473
Lawrence Tange407b4c2022-07-21 13:54:01 +0100474 //Memory access attributes.
475 //todo: find the specification of these in the ARM ARM
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800476 if (isvalid_prop_to_ir(&ui64Type, 10)) {
477 json_object_object_add(
478 bus_error_ir, "memoryAttributes",
479 json_object_new_int(
480 bus_error->MemoryAddressAttributes));
481 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100482
Lawrence Tange407b4c2022-07-21 13:54:01 +0100483 //Access Mode
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800484 if (isvalid_prop_to_ir(&ui64Type, 8)) {
485 json_object *access_mode = json_object_new_object();
486 json_object_object_add(
487 access_mode, "value",
488 json_object_new_int(bus_error->AccessMode));
489 json_object_object_add(
490 access_mode, "name",
491 json_object_new_string(bus_error->AccessMode == 0 ?
492 "Secure" :
493 "Normal"));
494 json_object_object_add(bus_error_ir, "accessMode", access_mode);
495 }
496 json_object_object_add(bus_prop, bus_propname, bus_error_ir);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100497
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800498 return bus_prop;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100499}
500
501//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100502json_object *
503cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
Ed Tanous5e2164a2025-03-09 09:20:44 -0700504 const UINT8 **cur_pos, UINT32 *remaining_size)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100505{
Ed Tanous5e2164a2025-03-09 09:20:44 -0700506 if (header->RegisterArraySize > *remaining_size) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700507 cper_print_log(
508 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700509 return NULL;
510 }
511
Lawrence Tange407b4c2022-07-21 13:54:01 +0100512 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100513
Lawrence Tange407b4c2022-07-21 13:54:01 +0100514 //Version.
515 json_object_object_add(context_ir, "version",
516 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100517
Lawrence Tange407b4c2022-07-21 13:54:01 +0100518 //Add the context type.
519 json_object *context_type = integer_to_readable_pair(
Ed Tanous5e2164a2025-03-09 09:20:44 -0700520 header->RegisterContextType,
521 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_COUNT,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100522 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
523 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
524 "Unknown (Reserved)");
525 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100526
Lawrence Tange407b4c2022-07-21 13:54:01 +0100527 //Register array size (bytes).
528 json_object_object_add(
529 context_ir, "registerArraySize",
530 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100531
Lawrence Tange407b4c2022-07-21 13:54:01 +0100532 //The register array itself.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100533 json_object *register_array = NULL;
534 switch (header->RegisterContextType) {
535 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700536 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH32_GPR)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700537 cper_print_log(
538 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700539 goto fail;
540 }
541 if (header->RegisterArraySize <
542 sizeof(EFI_ARM_V8_AARCH32_GPR)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700543 cper_print_log(
544 "Invalid CPER file: Not enough bytes for aarch32 gpr\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700545 goto fail;
546 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100547 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800548 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100549 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
550 ARM_AARCH32_GPR_NAMES);
551 break;
552 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700553 if (*remaining_size <
554 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700555 cper_print_log(
556 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700557 goto fail;
558 }
559 if (header->RegisterArraySize <
560 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700561 cper_print_log(
562 "Invalid CPER file: Not enough bytes for aarch32 el1\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700563 goto fail;
564 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100565 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800566 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100567 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
568 sizeof(UINT32),
569 ARM_AARCH32_EL1_REGISTER_NAMES);
570 break;
571 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700572 if (*remaining_size <
573 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700574 cper_print_log(
575 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700576 goto fail;
577 }
578 if (header->RegisterArraySize <
579 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700580 cper_print_log(
581 "Invalid CPER file: Not enough bytes for aarch32 el2\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700582 goto fail;
583 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100584 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800585 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100586 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
587 sizeof(UINT32),
588 ARM_AARCH32_EL2_REGISTER_NAMES);
Ed Tanous5e2164a2025-03-09 09:20:44 -0700589
Lawrence Tange407b4c2022-07-21 13:54:01 +0100590 break;
591 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700592 if (*remaining_size <
593 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) {
594 json_object_put(context_ir);
Ed Tanous50b966f2025-03-11 09:06:19 -0700595 cper_print_log(
596 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700597 return NULL;
598 }
599 if (header->RegisterArraySize <
600 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700601 cper_print_log(
602 "Invalid CPER file: Not enough bytes for aarch32 secure\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700603 goto fail;
604 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100605 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800606 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100607 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
608 sizeof(UINT32),
609 ARM_AARCH32_SECURE_REGISTER_NAMES);
610 break;
611 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700612 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH64_GPR)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700613 cper_print_log(
614 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700615 goto fail;
616 }
617 if (header->RegisterArraySize <
618 sizeof(EFI_ARM_V8_AARCH64_GPR)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700619 cper_print_log(
620 "Invalid CPER file: Not enough bytes for aarch64 gpr\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700621 goto fail;
622 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100623 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800624 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100625 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
626 ARM_AARCH64_GPR_NAMES);
627 break;
628 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700629 if (*remaining_size <
630 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700631 cper_print_log(
632 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700633 goto fail;
634 }
635 if (header->RegisterArraySize <
636 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700637 cper_print_log(
638 "Invalid CPER file: Not enough bytes for aarch64 el1\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700639 goto fail;
640 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100641 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800642 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100643 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
644 sizeof(UINT64),
645 ARM_AARCH64_EL1_REGISTER_NAMES);
646 break;
647 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700648 if (*remaining_size <
649 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700650 cper_print_log(
651 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700652 goto fail;
653 }
654 if (header->RegisterArraySize <
655 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700656 cper_print_log(
657 "Invalid CPER file: Not enough bytes for aarch64 el2\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700658 goto fail;
659 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100660 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800661 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100662 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
663 sizeof(UINT64),
664 ARM_AARCH64_EL2_REGISTER_NAMES);
665 break;
666 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700667 if (*remaining_size <
668 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700669 cper_print_log(
670 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700671 goto fail;
672 }
673 if (header->RegisterArraySize <
674 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700675 cper_print_log(
676 "Invalid CPER file: Not enough bytes for aarch64 el3\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700677 goto fail;
678 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100679 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800680 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100681 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
682 sizeof(UINT64),
683 ARM_AARCH64_EL3_REGISTER_NAMES);
684 break;
685 case EFI_ARM_CONTEXT_TYPE_MISC:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700686 if (*remaining_size < sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700687 cper_print_log(
688 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700689 goto fail;
690 }
691 if (header->RegisterArraySize <
692 sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700693 cper_print_log(
694 "Invalid CPER file: Not enough bytes for misc\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700695 goto fail;
696 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100697 register_array = cper_arm_misc_register_array_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800698 (EFI_ARM_MISC_CONTEXT_REGISTER *)*cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100699 break;
700 default:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700701 if (*remaining_size < header->RegisterArraySize) {
Ed Tanous50b966f2025-03-11 09:06:19 -0700702 cper_print_log(
703 "Invalid CPER file: Invalid processor context info num.\n");
Ed Tanous5e2164a2025-03-09 09:20:44 -0700704 goto fail;
705 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100706 //Unknown register array type, add as base64 data instead.
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700707 int32_t encoded_len = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800708 char *encoded = base64_encode((UINT8 *)*cur_pos,
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700709 header->RegisterArraySize,
710 &encoded_len);
711 if (encoded == NULL) {
Ed Tanous5e2164a2025-03-09 09:20:44 -0700712 goto fail;
John Chungf8fc7052024-05-03 20:05:29 +0800713 }
Ed Tanous5e2164a2025-03-09 09:20:44 -0700714 register_array = json_object_new_object();
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700715 json_object_object_add(register_array, "data",
716 json_object_new_string_len(encoded,
717 encoded_len));
718 free(encoded);
719
Lawrence Tange407b4c2022-07-21 13:54:01 +0100720 break;
721 }
722 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100723
Lawrence Tange407b4c2022-07-21 13:54:01 +0100724 //Set the current position to after the processor context structure.
725 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700726 *remaining_size -= header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100727
Lawrence Tange407b4c2022-07-21 13:54:01 +0100728 return context_ir;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700729
730fail:
731 json_object_put(context_ir);
732 return NULL;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100733}
734
735//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100736json_object *
737cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100738{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100739 json_object *register_array = json_object_new_object();
740 json_object *mrs_encoding = json_object_new_object();
741 json_object_object_add(mrs_encoding, "op2",
742 json_object_new_uint64(misc_register->MrsOp2));
743 json_object_object_add(mrs_encoding, "crm",
744 json_object_new_uint64(misc_register->MrsCrm));
745 json_object_object_add(mrs_encoding, "crn",
746 json_object_new_uint64(misc_register->MrsCrn));
747 json_object_object_add(mrs_encoding, "op1",
748 json_object_new_uint64(misc_register->MrsOp1));
749 json_object_object_add(mrs_encoding, "o0",
750 json_object_new_uint64(misc_register->MrsO0));
751 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
752 json_object_object_add(register_array, "value",
753 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100754
Lawrence Tange407b4c2022-07-21 13:54:01 +0100755 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100756}
757
758//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100759void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100760{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800761 EFI_ARM_ERROR_RECORD section_cper;
762 memset(&section_cper, 0, sizeof(section_cper));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100763
Lawrence Tange407b4c2022-07-21 13:54:01 +0100764 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800765 struct json_object *obj = NULL;
766 ValidationTypes u32Type = { UINT_32T, .value.ui32 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100767
Lawrence Tange407b4c2022-07-21 13:54:01 +0100768 //Count of error/context info structures.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800769 section_cper.ErrInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100770 json_object_object_get(section, "errorInfoNum"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800771 section_cper.ContextInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100772 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100773
Lawrence Tange407b4c2022-07-21 13:54:01 +0100774 //Miscellaneous raw value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800775 section_cper.SectionLength = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100776 json_object_object_get(section, "sectionLength"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800777 if (json_object_object_get_ex(section, "mpidrEl1", &obj)) {
778 section_cper.MPIDR_EL1 = json_object_get_uint64(obj);
779 add_to_valid_bitfield(&u32Type, 0);
780 }
781 if (json_object_object_get_ex(section, "errorAffinity", &obj)) {
782 section_cper.ErrorAffinityLevel = readable_pair_to_integer(obj);
783 add_to_valid_bitfield(&u32Type, 1);
784 }
785 section_cper.MIDR_EL1 = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100786 json_object_object_get(section, "midrEl1"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800787 if (json_object_object_get_ex(section, "running", &obj)) {
788 section_cper.RunningState = json_object_get_boolean(obj);
789 add_to_valid_bitfield(&u32Type, 2);
790 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100791
Lawrence Tange407b4c2022-07-21 13:54:01 +0100792 //Optional PSCI state.
793 json_object *psci_state = json_object_object_get(section, "psciState");
John Chungf8fc7052024-05-03 20:05:29 +0800794 if (psci_state != NULL) {
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800795 section_cper.PsciState = json_object_get_uint64(psci_state);
John Chungf8fc7052024-05-03 20:05:29 +0800796 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100797
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800798 //Validationbits for EFI_ARM_ERROR_RECORD should also consider vendorSpecificInfo
799 bool vendorSpecificPresent =
800 json_object_object_get_ex(section, "vendorSpecificInfo", &obj);
801 json_object *vendor_specific_info = obj;
802 if (vendorSpecificPresent) {
803 add_to_valid_bitfield(&u32Type, 3);
804 }
805
806 section_cper.ValidFields = u32Type.value.ui32;
807
Lawrence Tange407b4c2022-07-21 13:54:01 +0100808 //Flush header to stream.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800809 fwrite(&section_cper, sizeof(section_cper), 1, out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100810
Lawrence Tange407b4c2022-07-21 13:54:01 +0100811 //Error info structure array.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800812
Lawrence Tange407b4c2022-07-21 13:54:01 +0100813 json_object *error_info = json_object_object_get(section, "errorInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800814 for (int i = 0; i < section_cper.ErrInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100815 ir_arm_error_info_to_cper(
816 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800817 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100818
Lawrence Tange407b4c2022-07-21 13:54:01 +0100819 //Context info structure array.
820 json_object *context_info =
821 json_object_object_get(section, "contextInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800822 for (int i = 0; i < section_cper.ContextInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100823 ir_arm_context_info_to_cper(
824 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800825 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100826
Lawrence Tange407b4c2022-07-21 13:54:01 +0100827 //Vendor specific error info.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800828 if (vendorSpecificPresent) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100829 json_object *vendor_info_string =
830 json_object_object_get(vendor_specific_info, "data");
831 int vendor_specific_len =
832 json_object_get_string_len(vendor_info_string);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100833
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700834 int32_t decoded_len = 0;
835
836 UINT8 *decoded = base64_decode(
837 json_object_get_string(vendor_info_string),
838 vendor_specific_len, &decoded_len);
839
840 //Write out to file.
841 fwrite(decoded, decoded_len, 1, out);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700842 free(decoded);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100843 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100844
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800845 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100846}
847
848//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100849void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100850{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100851 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800852 memset(&error_info_cper, 0, sizeof(error_info_cper));
853 struct json_object *obj = NULL;
854 ValidationTypes ui16Type = { UINT_16T, .value.ui16 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100855
Lawrence Tange407b4c2022-07-21 13:54:01 +0100856 //Version, length.
857 error_info_cper.Version = json_object_get_int(
858 json_object_object_get(error_info, "version"));
859 error_info_cper.Length = json_object_get_int(
860 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100861
Lawrence Tange407b4c2022-07-21 13:54:01 +0100862 //Type, multiple error.
863 error_info_cper.Type = (UINT8)readable_pair_to_integer(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800864 json_object_object_get(error_info, "errorType"));
865
866 if (json_object_object_get_ex(error_info, "multipleError", &obj)) {
867 error_info_cper.MultipleError =
868 (UINT16)readable_pair_to_integer(obj);
869 add_to_valid_bitfield(&ui16Type, 0);
870 } else {
871 error_info_cper.MultipleError = 0;
872 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100873
Lawrence Tange407b4c2022-07-21 13:54:01 +0100874 //Flags object.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800875 if (json_object_object_get_ex(error_info, "flags", &obj)) {
876 error_info_cper.Flags = (UINT8)ir_to_bitfield(
877 obj, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
878 add_to_valid_bitfield(&ui16Type, 1);
879 } else {
880 error_info_cper.Flags = 0;
881 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100882
Lawrence Tange407b4c2022-07-21 13:54:01 +0100883 //Error information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800884 if (json_object_object_get_ex(error_info, "errorInformation", &obj)) {
885 json_object *error_info_information = obj;
886 json_object *error_info_prop = NULL;
887 switch (error_info_cper.Type) {
888 case ARM_ERROR_INFORMATION_TYPE_CACHE:
889 error_info_cper.ErrorInformation.Value = 0;
890 error_info_prop = json_object_object_get(
891 error_info_information, "cacheError");
892 ir_arm_error_cache_tlb_info_to_cper(
893 error_info_prop,
894 &error_info_cper.ErrorInformation.CacheError);
895 break;
896 case ARM_ERROR_INFORMATION_TYPE_TLB:
897 error_info_cper.ErrorInformation.Value = 0;
898 error_info_prop = json_object_object_get(
899 error_info_information, "tlbError");
900 ir_arm_error_cache_tlb_info_to_cper(
901 error_info_prop,
902 &error_info_cper.ErrorInformation.CacheError);
903 break;
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700904
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800905 case ARM_ERROR_INFORMATION_TYPE_BUS:
906 error_info_cper.ErrorInformation.Value = 0;
907 error_info_prop = json_object_object_get(
908 error_info_information, "busError");
909 ir_arm_error_bus_info_to_cper(
910 error_info_prop,
911 &error_info_cper.ErrorInformation.BusError);
912 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100913
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800914 default:
915 //Unknown error information type.
916 break;
917 }
918 add_to_valid_bitfield(&ui16Type, 2);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100919 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100920
Lawrence Tange407b4c2022-07-21 13:54:01 +0100921 //Virtual/physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800922 if (json_object_object_get_ex(error_info, "virtualFaultAddress",
923 &obj)) {
924 error_info_cper.VirtualFaultAddress =
925 json_object_get_uint64(obj);
926 add_to_valid_bitfield(&ui16Type, 3);
927 } else {
928 error_info_cper.VirtualFaultAddress = 0;
929 }
930
931 if (json_object_object_get_ex(error_info, "physicalFaultAddress",
932 &obj)) {
933 error_info_cper.PhysicalFaultAddress =
934 json_object_get_uint64(obj);
935 add_to_valid_bitfield(&ui16Type, 4);
936 } else {
937 error_info_cper.PhysicalFaultAddress = 0;
938 }
939 error_info_cper.ValidationBits = ui16Type.value.ui16;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100940
Lawrence Tange407b4c2022-07-21 13:54:01 +0100941 //Write out to stream.
942 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
943 out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100944}
945
Lawrence Tang71570a22022-07-14 11:45:28 +0100946//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100947void ir_arm_error_cache_tlb_info_to_cper(
948 json_object *error_information,
949 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100950{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800951 // //Validation bits.
952 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
953 struct json_object *obj = NULL;
Lawrence Tang71570a22022-07-14 11:45:28 +0100954
Lawrence Tange407b4c2022-07-21 13:54:01 +0100955 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800956 if (json_object_object_get_ex(error_information, "transactionType",
957 &obj)) {
958 error_info_cper->TransactionType =
959 readable_pair_to_integer(obj);
960 add_to_valid_bitfield(&ui64Type, 0);
961 }
962 if (json_object_object_get_ex(error_information, "operation", &obj)) {
963 error_info_cper->Operation = readable_pair_to_integer(obj);
964 add_to_valid_bitfield(&ui64Type, 1);
965 }
966 if (json_object_object_get_ex(error_information, "level", &obj)) {
967 error_info_cper->Level = json_object_get_uint64(obj);
968 add_to_valid_bitfield(&ui64Type, 2);
969 }
970 if (json_object_object_get_ex(error_information,
971 "processorContextCorrupt", &obj)) {
972 error_info_cper->ProcessorContextCorrupt =
973 json_object_get_boolean(obj);
974 add_to_valid_bitfield(&ui64Type, 3);
975 }
976 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
977 error_info_cper->Corrected = json_object_get_boolean(obj);
978 add_to_valid_bitfield(&ui64Type, 4);
979 }
980 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
981 error_info_cper->PrecisePC = json_object_get_boolean(obj);
982 add_to_valid_bitfield(&ui64Type, 5);
983 }
984 if (json_object_object_get_ex(error_information, "restartablePC",
985 &obj)) {
986 error_info_cper->RestartablePC = json_object_get_boolean(obj);
987 add_to_valid_bitfield(&ui64Type, 6);
988 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100989 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800990 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +0100991}
992
993//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100994void ir_arm_error_bus_info_to_cper(json_object *error_information,
995 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100996{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100997 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800998 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
999 struct json_object *obj = NULL;
1000
1001 memset(error_info_cper, 0, sizeof(EFI_ARM_BUS_ERROR_STRUCTURE));
Lawrence Tang71570a22022-07-14 11:45:28 +01001002
Lawrence Tange407b4c2022-07-21 13:54:01 +01001003 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -08001004 if (json_object_object_get_ex(error_information, "transactionType",
1005 &obj)) {
1006 error_info_cper->TransactionType =
1007 readable_pair_to_integer(obj);
1008 add_to_valid_bitfield(&ui64Type, 0);
1009 } else {
1010 error_info_cper->TransactionType = 0;
1011 }
1012 if (json_object_object_get_ex(error_information, "operation", &obj)) {
1013 error_info_cper->Operation = readable_pair_to_integer(obj);
1014 add_to_valid_bitfield(&ui64Type, 1);
1015 } else {
1016 error_info_cper->Operation = 0;
1017 }
1018 if (json_object_object_get_ex(error_information, "level", &obj)) {
1019 error_info_cper->Level = json_object_get_uint64(obj);
1020 add_to_valid_bitfield(&ui64Type, 2);
1021 } else {
1022 error_info_cper->Level = 0;
1023 }
1024 if (json_object_object_get_ex(error_information,
1025 "processorContextCorrupt", &obj)) {
1026 error_info_cper->ProcessorContextCorrupt =
1027 json_object_get_boolean(obj);
1028 add_to_valid_bitfield(&ui64Type, 3);
1029 } else {
1030 error_info_cper->ProcessorContextCorrupt = 0;
1031 }
1032 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
1033 error_info_cper->Corrected = json_object_get_boolean(obj);
1034 add_to_valid_bitfield(&ui64Type, 4);
1035 } else {
1036 error_info_cper->Corrected = 0;
1037 }
1038 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
1039 error_info_cper->PrecisePC = json_object_get_boolean(obj);
1040 add_to_valid_bitfield(&ui64Type, 5);
1041 } else {
1042 error_info_cper->PrecisePC = 0;
1043 }
1044 if (json_object_object_get_ex(error_information, "restartablePC",
1045 &obj)) {
1046 error_info_cper->RestartablePC = json_object_get_boolean(obj);
1047 add_to_valid_bitfield(&ui64Type, 6);
1048 } else {
1049 error_info_cper->RestartablePC = 0;
1050 }
1051 if (json_object_object_get_ex(error_information, "participationType",
1052 &obj)) {
1053 error_info_cper->ParticipationType =
1054 readable_pair_to_integer(obj);
1055 add_to_valid_bitfield(&ui64Type, 7);
1056 } else {
1057 error_info_cper->ParticipationType = 0;
1058 }
1059 if (json_object_object_get_ex(error_information, "timedOut", &obj)) {
1060 error_info_cper->TimeOut = json_object_get_boolean(obj);
1061 add_to_valid_bitfield(&ui64Type, 8);
1062 } else {
1063 error_info_cper->TimeOut = 0;
1064 }
1065 if (json_object_object_get_ex(error_information, "addressSpace",
1066 &obj)) {
1067 error_info_cper->AddressSpace = readable_pair_to_integer(obj);
1068 add_to_valid_bitfield(&ui64Type, 9);
1069 } else {
1070 error_info_cper->AddressSpace = 0;
1071 }
1072 if (json_object_object_get_ex(error_information, "accessMode", &obj)) {
1073 error_info_cper->AccessMode = readable_pair_to_integer(obj);
1074 add_to_valid_bitfield(&ui64Type, 11);
1075 } else {
1076 error_info_cper->AccessMode = 0;
1077 }
1078 if (json_object_object_get_ex(error_information, "memoryAttributes",
1079 &obj)) {
1080 error_info_cper->MemoryAddressAttributes =
1081 json_object_get_uint64(obj);
1082 add_to_valid_bitfield(&ui64Type, 10);
1083 } else {
1084 error_info_cper->MemoryAddressAttributes = 0;
1085 }
Lawrence Tange407b4c2022-07-21 13:54:01 +01001086 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -08001087 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +01001088}
1089
Lawrence Tang7cd13902022-07-13 16:59:25 +01001090//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001091void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +01001092{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001093 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +01001094
Lawrence Tange407b4c2022-07-21 13:54:01 +01001095 //Version, array size, context type.
1096 info_header.Version = json_object_get_int(
1097 json_object_object_get(context_info, "version"));
1098 info_header.RegisterArraySize = json_object_get_int(
1099 json_object_object_get(context_info, "registerArraySize"));
1100 info_header.RegisterContextType = readable_pair_to_integer(
1101 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001102
Lawrence Tange407b4c2022-07-21 13:54:01 +01001103 //Flush to stream, write the register array itself.
1104 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
1105 out);
1106 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001107
Lawrence Tange407b4c2022-07-21 13:54:01 +01001108 json_object *register_array =
1109 json_object_object_get(context_info, "registerArray");
1110 switch (info_header.RegisterContextType) {
1111 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
1112 ir_arm_aarch32_gpr_to_cper(register_array, out);
1113 break;
1114 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
1115 ir_arm_aarch32_el1_to_cper(register_array, out);
1116 break;
1117 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
1118 ir_arm_aarch32_el2_to_cper(register_array, out);
1119 break;
1120 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
1121 ir_arm_aarch32_secure_to_cper(register_array, out);
1122 break;
1123 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
1124 ir_arm_aarch64_gpr_to_cper(register_array, out);
1125 break;
1126 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
1127 ir_arm_aarch64_el1_to_cper(register_array, out);
1128 break;
1129 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
1130 ir_arm_aarch64_el2_to_cper(register_array, out);
1131 break;
1132 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
1133 ir_arm_aarch64_el3_to_cper(register_array, out);
1134 break;
1135 case EFI_ARM_CONTEXT_TYPE_MISC:
1136 ir_arm_misc_registers_to_cper(register_array, out);
1137 break;
1138 default:
1139 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +08001140 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +01001141 break;
1142 }
Lawrence Tang71570a22022-07-14 11:45:28 +01001143}
1144
1145//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001146void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001147{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001148 //Get uniform register array.
1149 EFI_ARM_V8_AARCH32_GPR reg_array;
1150 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1151 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
1152 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001153
Lawrence Tange407b4c2022-07-21 13:54:01 +01001154 //Flush to stream.
1155 fwrite(&reg_array, sizeof(reg_array), 1, out);
1156 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001157}
1158
1159//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 +01001160void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001161{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001162 //Get uniform register array.
1163 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
1164 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1165 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
1166 sizeof(UINT32),
1167 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001168
Lawrence Tange407b4c2022-07-21 13:54:01 +01001169 //Flush to stream.
1170 fwrite(&reg_array, sizeof(reg_array), 1, out);
1171 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001172}
1173
1174//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 +01001175void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001176{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001177 //Get uniform register array.
1178 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
1179 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1180 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
1181 sizeof(UINT32),
1182 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001183
Lawrence Tange407b4c2022-07-21 13:54:01 +01001184 //Flush to stream.
1185 fwrite(&reg_array, sizeof(reg_array), 1, out);
1186 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001187}
1188
1189//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 +01001190void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001191{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001192 //Get uniform register array.
1193 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
1194 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1195 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
1196 sizeof(UINT32),
1197 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001198
Lawrence Tange407b4c2022-07-21 13:54:01 +01001199 //Flush to stream.
1200 fwrite(&reg_array, sizeof(reg_array), 1, out);
1201 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001202}
1203
1204//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001205void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001206{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001207 //Get uniform register array.
1208 EFI_ARM_V8_AARCH64_GPR reg_array;
1209 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1210 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
1211 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001212
Lawrence Tange407b4c2022-07-21 13:54:01 +01001213 //Flush to stream.
1214 fwrite(&reg_array, sizeof(reg_array), 1, out);
1215 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001216}
1217
1218//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 +01001219void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001220{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001221 //Get uniform register array.
1222 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
1223 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1224 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
1225 sizeof(UINT64),
1226 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001227
Lawrence Tange407b4c2022-07-21 13:54:01 +01001228 //Flush to stream.
1229 fwrite(&reg_array, sizeof(reg_array), 1, out);
1230 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001231}
1232
1233//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 +01001234void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001235{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001236 //Get uniform register array.
1237 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
1238 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1239 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
1240 sizeof(UINT64),
1241 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001242
Lawrence Tange407b4c2022-07-21 13:54:01 +01001243 //Flush to stream.
1244 fwrite(&reg_array, sizeof(reg_array), 1, out);
1245 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001246}
1247
1248//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 +01001249void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001250{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001251 //Get uniform register array.
1252 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
1253 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1254 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
1255 sizeof(UINT64),
1256 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001257
Lawrence Tange407b4c2022-07-21 13:54:01 +01001258 //Flush to stream.
1259 fwrite(&reg_array, sizeof(reg_array), 1, out);
1260 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001261}
1262
1263//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 +01001264void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001265{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001266 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +01001267
Lawrence Tange407b4c2022-07-21 13:54:01 +01001268 //MRS encoding information.
1269 json_object *mrs_encoding =
1270 json_object_object_get(registers, "mrsEncoding");
1271 reg_array.MrsOp2 = json_object_get_uint64(
1272 json_object_object_get(mrs_encoding, "op2"));
1273 reg_array.MrsCrm = json_object_get_uint64(
1274 json_object_object_get(mrs_encoding, "crm"));
1275 reg_array.MrsCrn = json_object_get_uint64(
1276 json_object_object_get(mrs_encoding, "crn"));
1277 reg_array.MrsOp1 = json_object_get_uint64(
1278 json_object_object_get(mrs_encoding, "op1"));
1279 reg_array.MrsO0 = json_object_get_uint64(
1280 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001281
Lawrence Tange407b4c2022-07-21 13:54:01 +01001282 //Actual register value.
1283 reg_array.Value = json_object_get_uint64(
1284 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001285
Lawrence Tange407b4c2022-07-21 13:54:01 +01001286 //Flush to stream.
1287 fwrite(&reg_array, sizeof(reg_array), 1, out);
1288 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001289}
1290
1291//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +08001292void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001293{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001294 //Get base64 represented data.
1295 json_object *encoded = json_object_object_get(registers, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -07001296
1297 int32_t decoded_len = 0;
1298
1299 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
1300 json_object_get_string_len(encoded),
1301 &decoded_len);
1302
1303 if (decoded == NULL) {
Ed Tanous50b966f2025-03-11 09:06:19 -07001304 cper_print_log("Failed to allocate decode output buffer. \n");
John Chungf8fc7052024-05-03 20:05:29 +08001305 } else {
John Chungf8fc7052024-05-03 20:05:29 +08001306 //Flush out to stream.
1307 fwrite(&decoded, decoded_len, 1, out);
1308 fflush(out);
1309 free(decoded);
1310 }
1311}