blob: cd06131dbe359220c7a32f0193b20d3a070bbdb0 [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>
Lawrence Tang2800cd82022-07-05 16:08:20 +010015
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010016//Private pre-definitions.
Lawrence Tange407b4c2022-07-21 13:54:01 +010017json_object *
18cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
19json_object *
20cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
Ed Tanous5e2164a2025-03-09 09:20:44 -070021 const UINT8 **cur_pos, UINT32 *remaining_size);
Lawrence Tange407b4c2022-07-21 13:54:01 +010022json_object *
23cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
24 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
25json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error);
26json_object *cper_arm_misc_register_array_to_ir(
27 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register);
28void ir_arm_error_info_to_cper(json_object *error_info, FILE *out);
29void ir_arm_context_info_to_cper(json_object *context_info, FILE *out);
30void ir_arm_error_cache_tlb_info_to_cper(
31 json_object *error_information,
32 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper);
33void ir_arm_error_bus_info_to_cper(json_object *error_information,
34 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper);
35void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out);
36void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out);
37void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out);
38void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out);
39void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out);
40void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out);
41void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out);
42void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out);
43void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out);
John Chungf8fc7052024-05-03 20:05:29 +080044void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010045
Lawrence Tang2800cd82022-07-05 16:08:20 +010046//Converts the given processor-generic CPER section into JSON IR.
Ed Tanous12dbd4f2025-03-08 19:05:01 -080047json_object *cper_section_arm_to_ir(const UINT8 *section, UINT32 size)
Lawrence Tang2800cd82022-07-05 16:08:20 +010048{
Ed Tanous5e2164a2025-03-09 09:20:44 -070049 const UINT8 *cur_pos = section;
50 UINT32 remaining_size = size;
51
52 if (remaining_size < sizeof(EFI_ARM_ERROR_RECORD)) {
Ed Tanous12dbd4f2025-03-08 19:05:01 -080053 return NULL;
54 }
Ed Tanous5e2164a2025-03-09 09:20:44 -070055 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)cur_pos;
56 cur_pos += sizeof(EFI_ARM_ERROR_RECORD);
57 remaining_size -= sizeof(EFI_ARM_ERROR_RECORD);
Lawrence Tange407b4c2022-07-21 13:54:01 +010058 json_object *section_ir = json_object_new_object();
Lawrence Tang2800cd82022-07-05 16:08:20 +010059
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080060 //Length of ValidationBits from spec
61 ValidationTypes ui64Type = { UINT_64T,
62 .value.ui64 = record->ValidFields };
Lawrence Tang2800cd82022-07-05 16:08:20 +010063
Lawrence Tange407b4c2022-07-21 13:54:01 +010064 //Number of error info and context info structures, and length.
65 json_object_object_add(section_ir, "errorInfoNum",
66 json_object_new_int(record->ErrInfoNum));
67 json_object_object_add(section_ir, "contextInfoNum",
68 json_object_new_int(record->ContextInfoNum));
69 json_object_object_add(section_ir, "sectionLength",
70 json_object_new_uint64(record->SectionLength));
Lawrence Tang2800cd82022-07-05 16:08:20 +010071
Lawrence Tange407b4c2022-07-21 13:54:01 +010072 //Error affinity.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080073 if (isvalid_prop_to_ir(&ui64Type, 1)) {
74 json_object *error_affinity = json_object_new_object();
75 json_object_object_add(
76 error_affinity, "value",
77 json_object_new_int(record->ErrorAffinityLevel));
78 json_object_object_add(
79 error_affinity, "type",
80 json_object_new_string(record->ErrorAffinityLevel < 4 ?
81 "Vendor Defined" :
82 "Reserved"));
83 json_object_object_add(section_ir, "errorAffinity",
84 error_affinity);
85 }
Lawrence Tang2800cd82022-07-05 16:08:20 +010086
Lawrence Tange407b4c2022-07-21 13:54:01 +010087 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080088 if (isvalid_prop_to_ir(&ui64Type, 0)) {
89 uint64_t mpidr_eli1 = record->MPIDR_EL1;
90 uint64_t sock;
91 json_object_object_add(section_ir, "mpidrEl1",
92 json_object_new_uint64(mpidr_eli1));
93
94 //Arm Processor socket info dependes on mpidr_eli1
95 sock = (mpidr_eli1 & ARM_SOCK_MASK) >> 32;
96 json_object_object_add(section_ir, "affinity3",
97 json_object_new_uint64(sock));
98 }
Aushim Nagarkatti17bc66a2024-11-25 13:47:35 -080099
Lawrence Tange407b4c2022-07-21 13:54:01 +0100100 json_object_object_add(section_ir, "midrEl1",
101 json_object_new_uint64(record->MIDR_EL1));
Lawrence Tang2800cd82022-07-05 16:08:20 +0100102
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800103 if (isvalid_prop_to_ir(&ui64Type, 2)) {
104 //Whether the processor is running, and the state of it if so.
105 json_object_object_add(
106 section_ir, "running",
107 json_object_new_boolean(record->RunningState & 0x1));
108 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100109 if (!(record->RunningState >> 31)) {
110 //Bit 32 of running state is on, so PSCI state information is included.
111 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
112 //or the newer Extended StateID format.
113 json_object_object_add(
114 section_ir, "psciState",
115 json_object_new_uint64(record->PsciState));
116 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100117
Lawrence Tange407b4c2022-07-21 13:54:01 +0100118 //Processor error structures.
119 json_object *error_info_array = json_object_new_array();
120 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
121 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
Ed Tanous5e2164a2025-03-09 09:20:44 -0700122 if (remaining_size <
123 (record->ErrInfoNum * sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY))) {
124 json_object_put(error_info_array);
125 json_object_put(section_ir);
126 printf("Invalid CPER file: Invalid processor error info num.\n");
127 return NULL;
128 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100129 for (int i = 0; i < record->ErrInfoNum; i++) {
130 json_object_array_add(error_info_array,
131 cper_arm_error_info_to_ir(cur_error));
132 cur_error++;
133 }
Ed Tanous5e2164a2025-03-09 09:20:44 -0700134
135 cur_pos += (UINT32)(record->ErrInfoNum *
136 sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY));
137 remaining_size -= (UINT32)(record->ErrInfoNum *
138 sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY));
139
Lawrence Tange407b4c2022-07-21 13:54:01 +0100140 json_object_object_add(section_ir, "errorInfo", error_info_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100141
Lawrence Tange407b4c2022-07-21 13:54:01 +0100142 //Processor context structures.
143 //The current position is moved within the processing, as it is a dynamic size structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100144 json_object *context_info_array = json_object_new_array();
145 for (int i = 0; i < record->ContextInfoNum; i++) {
Ed Tanous5e2164a2025-03-09 09:20:44 -0700146 if (remaining_size <
147 sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER)) {
148 json_object_put(context_info_array);
149 json_object_put(section_ir);
150 printf("Invalid CPER file: Invalid processor context info num.\n");
151 return NULL;
152 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100153 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
154 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700155
156 cur_pos += sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER);
157 remaining_size -= sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100158 json_object *processor_context =
Ed Tanous5e2164a2025-03-09 09:20:44 -0700159 cper_arm_processor_context_to_ir(header, &cur_pos,
160 &remaining_size);
161 if (processor_context == NULL) {
162 json_object_put(context_info_array);
163 json_object_put(section_ir);
164 printf("Invalid CPER file: Invalid processor context info num.\n");
165 return NULL;
166 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100167 json_object_array_add(context_info_array, processor_context);
168 }
169 json_object_object_add(section_ir, "contextInfo", context_info_array);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100170
Lawrence Tange407b4c2022-07-21 13:54:01 +0100171 //Is there any vendor-specific information following?
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800172 if (isvalid_prop_to_ir(&ui64Type, 3)) {
173 if (cur_pos < (uint8_t *)section + record->SectionLength) {
174 json_object *vendor_specific = json_object_new_object();
175 size_t input_size = (uint8_t *)section +
176 record->SectionLength - cur_pos;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700177 if (remaining_size < input_size) {
178 json_object_put(vendor_specific);
179 json_object_put(section_ir);
180 printf("Invalid CPER file: Invalid vendor-specific info length.\n");
181 return NULL;
182 }
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800183 int32_t encoded_len = 0;
184 char *encoded = base64_encode(cur_pos, input_size,
185 &encoded_len);
186 if (encoded == NULL) {
Ed Tanous5e2164a2025-03-09 09:20:44 -0700187 json_object_put(vendor_specific);
188 json_object_put(section_ir);
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800189 printf("base64 encode of vendorSpecificInfo failed\n");
190 return NULL;
191 }
192 json_object_object_add(vendor_specific, "data",
193 json_object_new_string_len(
194 encoded, encoded_len));
195 free(encoded);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700196
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800197 json_object_object_add(section_ir, "vendorSpecificInfo",
198 vendor_specific);
199 } else {
200 printf("vendorSpecificInfo is marked valid but not present in binary\n");
201 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100202 }
203
204 return section_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100205}
206
207//Converts a single ARM Process Error Information structure into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100208json_object *
209cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100210{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100211 json_object *error_info_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100212
Lawrence Tange407b4c2022-07-21 13:54:01 +0100213 //Version, length.
214 json_object_object_add(error_info_ir, "version",
215 json_object_new_int(error_info->Version));
216 json_object_object_add(error_info_ir, "length",
217 json_object_new_int(error_info->Length));
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100218
Lawrence Tange407b4c2022-07-21 13:54:01 +0100219 //Validation bitfield.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800220 ValidationTypes ui16Type = { UINT_16T,
221 .value.ui16 = error_info->ValidationBits };
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100222
Lawrence Tange407b4c2022-07-21 13:54:01 +0100223 //The type of error information in this log.
224 json_object *error_type = integer_to_readable_pair(
225 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
226 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
227 json_object_object_add(error_info_ir, "errorType", error_type);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100228
Lawrence Tange407b4c2022-07-21 13:54:01 +0100229 //Multiple error count.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800230 if (isvalid_prop_to_ir(&ui16Type, 0)) {
231 json_object *multiple_error = json_object_new_object();
232 json_object_object_add(
233 multiple_error, "value",
234 json_object_new_int(error_info->MultipleError));
235 json_object_object_add(
236 multiple_error, "type",
237 json_object_new_string(error_info->MultipleError < 1 ?
238 "Single Error" :
239 "Multiple Errors"));
240 json_object_object_add(error_info_ir, "multipleError",
241 multiple_error);
242 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100243
Lawrence Tange407b4c2022-07-21 13:54:01 +0100244 //Flags.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800245 if (isvalid_prop_to_ir(&ui16Type, 1)) {
246 json_object *flags = bitfield_to_ir(
247 error_info->Flags, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
248 json_object_object_add(error_info_ir, "flags", flags);
249 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100250
Lawrence Tange407b4c2022-07-21 13:54:01 +0100251 //Error information, split by type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800252 if (isvalid_prop_to_ir(&ui16Type, 2)) {
253 json_object *error_subinfo = NULL;
254 switch (error_info->Type) {
255 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
256 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
257 error_subinfo = cper_arm_cache_tlb_error_to_ir(
258 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
259 ->ErrorInformation,
260 error_info);
261 break;
262 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
263 error_subinfo = cper_arm_bus_error_to_ir(
264 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
265 ->ErrorInformation);
266 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100267
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800268 default:
269 //Unknown/microarch, will not support.
270 break;
271 }
272 json_object_object_add(error_info_ir, "errorInformation",
273 error_subinfo);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100274 }
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100275
Lawrence Tange407b4c2022-07-21 13:54:01 +0100276 //Virtual fault address, physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800277 if (isvalid_prop_to_ir(&ui16Type, 3)) {
278 json_object_object_add(
279 error_info_ir, "virtualFaultAddress",
280 json_object_new_uint64(
281 error_info->VirtualFaultAddress));
282 }
283 if (isvalid_prop_to_ir(&ui16Type, 4)) {
284 json_object_object_add(
285 error_info_ir, "physicalFaultAddress",
286 json_object_new_uint64(
287 error_info->PhysicalFaultAddress));
288 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100289
290 return error_info_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100291}
292
Lawrence Tang7f21db62022-07-06 11:09:39 +0100293//Converts a single ARM cache/TLB error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100294json_object *
295cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
296 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100297{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100298 json_object *cache_tlb_error_ir = json_object_new_object();
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700299 json_object *cache_tlb_prop = json_object_new_object();
300 char *cache_tlb_propname;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100301
Lawrence Tange407b4c2022-07-21 13:54:01 +0100302 //Validation bitfield.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800303 ValidationTypes ui64Type = {
304 UINT_64T, .value.ui64 = cache_tlb_error->ValidationBits
305 };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100306
Lawrence Tange407b4c2022-07-21 13:54:01 +0100307 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800308 if (isvalid_prop_to_ir(&ui64Type, 0)) {
309 json_object *transaction_type = integer_to_readable_pair(
310 cache_tlb_error->TransactionType, 3,
311 ARM_ERROR_TRANSACTION_TYPES_KEYS,
312 ARM_ERROR_TRANSACTION_TYPES_VALUES,
313 "Unknown (Reserved)");
314 json_object_object_add(cache_tlb_error_ir, "transactionType",
315 transaction_type);
316 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100317
Lawrence Tange407b4c2022-07-21 13:54:01 +0100318 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800319 bool cacheErrorFlag = 1;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100320 if (error_info->Type == 0) {
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700321 cache_tlb_propname = "cacheError";
Lawrence Tange407b4c2022-07-21 13:54:01 +0100322 } else {
323 //TLB operation.
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700324 cache_tlb_propname = "tlbError";
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800325 cacheErrorFlag = 0;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100326 }
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800327
328 if (isvalid_prop_to_ir(&ui64Type, 1)) {
329 json_object *operation;
330
331 if (cacheErrorFlag) {
332 //Cache operation.
333 operation = integer_to_readable_pair(
334 cache_tlb_error->Operation, 11,
335 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
336 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
337 "Unknown (Reserved)");
338 } else {
339 operation = integer_to_readable_pair(
340 cache_tlb_error->Operation, 9,
341 ARM_TLB_OPERATION_TYPES_KEYS,
342 ARM_TLB_OPERATION_TYPES_VALUES,
343 "Unknown (Reserved)");
344 }
345 json_object_object_add(cache_tlb_error_ir, "operation",
346 operation);
347 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100348
Lawrence Tange407b4c2022-07-21 13:54:01 +0100349 //Miscellaneous remaining fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800350 if (isvalid_prop_to_ir(&ui64Type, 2)) {
351 json_object_object_add(
352 cache_tlb_error_ir, "level",
353 json_object_new_int(cache_tlb_error->Level));
354 }
355 if (isvalid_prop_to_ir(&ui64Type, 3)) {
356 json_object_object_add(
357 cache_tlb_error_ir, "processorContextCorrupt",
358 json_object_new_boolean(
359 cache_tlb_error->ProcessorContextCorrupt));
360 }
361 if (isvalid_prop_to_ir(&ui64Type, 4)) {
362 json_object_object_add(
363 cache_tlb_error_ir, "corrected",
364 json_object_new_boolean(cache_tlb_error->Corrected));
365 }
366 if (isvalid_prop_to_ir(&ui64Type, 5)) {
367 json_object_object_add(
368 cache_tlb_error_ir, "precisePC",
369 json_object_new_boolean(cache_tlb_error->PrecisePC));
370 }
371 if (isvalid_prop_to_ir(&ui64Type, 6)) {
372 json_object_object_add(cache_tlb_error_ir, "restartablePC",
373 json_object_new_boolean(
374 cache_tlb_error->RestartablePC));
375 }
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700376
377 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
378 cache_tlb_error_ir);
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800379
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700380 return cache_tlb_prop;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100381}
382
383//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100384json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100385{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100386 json_object *bus_error_ir = json_object_new_object();
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800387 json_object *bus_prop = json_object_new_object();
388 char *bus_propname = "busError";
Lawrence Tang7f21db62022-07-06 11:09:39 +0100389
Lawrence Tange407b4c2022-07-21 13:54:01 +0100390 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800391 ValidationTypes ui64Type = { UINT_64T,
392 .value.ui64 = bus_error->ValidationBits };
Lawrence Tang7f21db62022-07-06 11:09:39 +0100393
Lawrence Tange407b4c2022-07-21 13:54:01 +0100394 //Transaction type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800395 if (isvalid_prop_to_ir(&ui64Type, 0)) {
396 json_object *transaction_type = integer_to_readable_pair(
397 bus_error->TransactionType, 3,
398 ARM_ERROR_TRANSACTION_TYPES_KEYS,
399 ARM_ERROR_TRANSACTION_TYPES_VALUES,
400 "Unknown (Reserved)");
401 json_object_object_add(bus_error_ir, "transactionType",
402 transaction_type);
403 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100404
Lawrence Tange407b4c2022-07-21 13:54:01 +0100405 //Operation.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800406 if (isvalid_prop_to_ir(&ui64Type, 1)) {
407 json_object *operation = integer_to_readable_pair(
408 bus_error->Operation, 7,
409 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
410 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
411 "Unknown (Reserved)");
412 json_object_object_add(bus_error_ir, "operation", operation);
413 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100414
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800415 if (isvalid_prop_to_ir(&ui64Type, 2)) {
416 //Affinity level of bus error, + miscellaneous fields.
417 json_object_object_add(bus_error_ir, "level",
418 json_object_new_int(bus_error->Level));
419 }
420 if (isvalid_prop_to_ir(&ui64Type, 3)) {
421 json_object_object_add(
422 bus_error_ir, "processorContextCorrupt",
423 json_object_new_boolean(
424 bus_error->ProcessorContextCorrupt));
425 }
426 if (isvalid_prop_to_ir(&ui64Type, 4)) {
427 json_object_object_add(
428 bus_error_ir, "corrected",
429 json_object_new_boolean(bus_error->Corrected));
430 }
431 if (isvalid_prop_to_ir(&ui64Type, 5)) {
432 json_object_object_add(
433 bus_error_ir, "precisePC",
434 json_object_new_boolean(bus_error->PrecisePC));
435 }
436 if (isvalid_prop_to_ir(&ui64Type, 6)) {
437 json_object_object_add(
438 bus_error_ir, "restartablePC",
439 json_object_new_boolean(bus_error->RestartablePC));
440 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100441
Lawrence Tange407b4c2022-07-21 13:54:01 +0100442 //Participation type.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800443 if (isvalid_prop_to_ir(&ui64Type, 7)) {
444 json_object *participation_type = integer_to_readable_pair(
445 bus_error->ParticipationType, 4,
446 ARM_BUS_PARTICIPATION_TYPES_KEYS,
447 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
448 json_object_object_add(bus_error_ir, "participationType",
449 participation_type);
450 }
451 if (isvalid_prop_to_ir(&ui64Type, 8)) {
452 json_object_object_add(
453 bus_error_ir, "timedOut",
454 json_object_new_boolean(bus_error->TimeOut));
455 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100456
Lawrence Tange407b4c2022-07-21 13:54:01 +0100457 //Address space.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800458 if (isvalid_prop_to_ir(&ui64Type, 9)) {
459 json_object *address_space = integer_to_readable_pair(
460 bus_error->AddressSpace, 3,
461 ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
462 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
463 json_object_object_add(bus_error_ir, "addressSpace",
464 address_space);
465 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100466
Lawrence Tange407b4c2022-07-21 13:54:01 +0100467 //Memory access attributes.
468 //todo: find the specification of these in the ARM ARM
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800469 if (isvalid_prop_to_ir(&ui64Type, 10)) {
470 json_object_object_add(
471 bus_error_ir, "memoryAttributes",
472 json_object_new_int(
473 bus_error->MemoryAddressAttributes));
474 }
Lawrence Tang7f21db62022-07-06 11:09:39 +0100475
Lawrence Tange407b4c2022-07-21 13:54:01 +0100476 //Access Mode
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800477 if (isvalid_prop_to_ir(&ui64Type, 8)) {
478 json_object *access_mode = json_object_new_object();
479 json_object_object_add(
480 access_mode, "value",
481 json_object_new_int(bus_error->AccessMode));
482 json_object_object_add(
483 access_mode, "name",
484 json_object_new_string(bus_error->AccessMode == 0 ?
485 "Secure" :
486 "Normal"));
487 json_object_object_add(bus_error_ir, "accessMode", access_mode);
488 }
489 json_object_object_add(bus_prop, bus_propname, bus_error_ir);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100490
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800491 return bus_prop;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100492}
493
494//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100495json_object *
496cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
Ed Tanous5e2164a2025-03-09 09:20:44 -0700497 const UINT8 **cur_pos, UINT32 *remaining_size)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100498{
Ed Tanous5e2164a2025-03-09 09:20:44 -0700499 if (header->RegisterArraySize > *remaining_size) {
500 printf("Invalid CPER file: Invalid processor context info num.\n");
501 return NULL;
502 }
503
Lawrence Tange407b4c2022-07-21 13:54:01 +0100504 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100505
Lawrence Tange407b4c2022-07-21 13:54:01 +0100506 //Version.
507 json_object_object_add(context_ir, "version",
508 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100509
Lawrence Tange407b4c2022-07-21 13:54:01 +0100510 //Add the context type.
511 json_object *context_type = integer_to_readable_pair(
Ed Tanous5e2164a2025-03-09 09:20:44 -0700512 header->RegisterContextType,
513 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_COUNT,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100514 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
515 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
516 "Unknown (Reserved)");
517 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100518
Lawrence Tange407b4c2022-07-21 13:54:01 +0100519 //Register array size (bytes).
520 json_object_object_add(
521 context_ir, "registerArraySize",
522 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100523
Lawrence Tange407b4c2022-07-21 13:54:01 +0100524 //The register array itself.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100525 json_object *register_array = NULL;
526 switch (header->RegisterContextType) {
527 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700528 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH32_GPR)) {
529 printf("Invalid CPER file: Invalid processor context info num.\n");
530 goto fail;
531 }
532 if (header->RegisterArraySize <
533 sizeof(EFI_ARM_V8_AARCH32_GPR)) {
534 printf("Invalid CPER file: Not enough bytes for aarch32 gpr\n");
535 goto fail;
536 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100537 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800538 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100539 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
540 ARM_AARCH32_GPR_NAMES);
541 break;
542 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700543 if (*remaining_size <
544 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) {
545 printf("Invalid CPER file: Invalid processor context info num.\n");
546 goto fail;
547 }
548 if (header->RegisterArraySize <
549 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS)) {
550 printf("Invalid CPER file: Not enough bytes for aarch32 el1\n");
551 goto fail;
552 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100553 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800554 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100555 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
556 sizeof(UINT32),
557 ARM_AARCH32_EL1_REGISTER_NAMES);
558 break;
559 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700560 if (*remaining_size <
561 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) {
562 printf("Invalid CPER file: Invalid processor context info num.\n");
563 goto fail;
564 }
565 if (header->RegisterArraySize <
566 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS)) {
567 printf("Invalid CPER file: Not enough bytes for aarch32 el2\n");
568 goto fail;
569 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100570 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800571 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100572 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
573 sizeof(UINT32),
574 ARM_AARCH32_EL2_REGISTER_NAMES);
Ed Tanous5e2164a2025-03-09 09:20:44 -0700575
Lawrence Tange407b4c2022-07-21 13:54:01 +0100576 break;
577 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700578 if (*remaining_size <
579 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) {
580 json_object_put(context_ir);
581 printf("Invalid CPER file: Invalid processor context info num.\n");
582 return NULL;
583 }
584 if (header->RegisterArraySize <
585 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS)) {
586 printf("Invalid CPER file: Not enough bytes for aarch32 secure\n");
587 goto fail;
588 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100589 register_array = uniform_struct_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800590 (UINT32 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100591 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
592 sizeof(UINT32),
593 ARM_AARCH32_SECURE_REGISTER_NAMES);
594 break;
595 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700596 if (*remaining_size < sizeof(EFI_ARM_V8_AARCH64_GPR)) {
597 printf("Invalid CPER file: Invalid processor context info num.\n");
598 goto fail;
599 }
600 if (header->RegisterArraySize <
601 sizeof(EFI_ARM_V8_AARCH64_GPR)) {
602 printf("Invalid CPER file: Not enough bytes for aarch64 gpr\n");
603 goto fail;
604 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100605 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800606 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100607 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
608 ARM_AARCH64_GPR_NAMES);
609 break;
610 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700611 if (*remaining_size <
612 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) {
613 printf("Invalid CPER file: Invalid processor context info num.\n");
614 goto fail;
615 }
616 if (header->RegisterArraySize <
617 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS)) {
618 printf("Invalid CPER file: Not enough bytes for aarch64 el1\n");
619 goto fail;
620 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100621 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800622 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100623 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
624 sizeof(UINT64),
625 ARM_AARCH64_EL1_REGISTER_NAMES);
626 break;
627 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700628 if (*remaining_size <
629 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) {
630 printf("Invalid CPER file: Invalid processor context info num.\n");
631 goto fail;
632 }
633 if (header->RegisterArraySize <
634 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS)) {
635 printf("Invalid CPER file: Not enough bytes for aarch64 el2\n");
636 goto fail;
637 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100638 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800639 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100640 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
641 sizeof(UINT64),
642 ARM_AARCH64_EL2_REGISTER_NAMES);
643 break;
644 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700645 if (*remaining_size <
646 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) {
647 printf("Invalid CPER file: Invalid processor context info num.\n");
648 goto fail;
649 }
650 if (header->RegisterArraySize <
651 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS)) {
652 printf("Invalid CPER file: Not enough bytes for aarch64 el3\n");
653 goto fail;
654 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100655 register_array = uniform_struct64_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800656 (UINT64 *)*cur_pos,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100657 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
658 sizeof(UINT64),
659 ARM_AARCH64_EL3_REGISTER_NAMES);
660 break;
661 case EFI_ARM_CONTEXT_TYPE_MISC:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700662 if (*remaining_size < sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) {
663 printf("Invalid CPER file: Invalid processor context info num.\n");
664 goto fail;
665 }
666 if (header->RegisterArraySize <
667 sizeof(EFI_ARM_MISC_CONTEXT_REGISTER)) {
668 printf("Invalid CPER file: Not enough bytes for misc\n");
669 goto fail;
670 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100671 register_array = cper_arm_misc_register_array_to_ir(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800672 (EFI_ARM_MISC_CONTEXT_REGISTER *)*cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100673 break;
674 default:
Ed Tanous5e2164a2025-03-09 09:20:44 -0700675 if (*remaining_size < header->RegisterArraySize) {
676 printf("Invalid CPER file: Invalid processor context info num.\n");
677 goto fail;
678 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100679 //Unknown register array type, add as base64 data instead.
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700680 int32_t encoded_len = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800681 char *encoded = base64_encode((UINT8 *)*cur_pos,
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700682 header->RegisterArraySize,
683 &encoded_len);
684 if (encoded == NULL) {
Ed Tanous5e2164a2025-03-09 09:20:44 -0700685 goto fail;
John Chungf8fc7052024-05-03 20:05:29 +0800686 }
Ed Tanous5e2164a2025-03-09 09:20:44 -0700687 register_array = json_object_new_object();
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700688 json_object_object_add(register_array, "data",
689 json_object_new_string_len(encoded,
690 encoded_len));
691 free(encoded);
692
Lawrence Tange407b4c2022-07-21 13:54:01 +0100693 break;
694 }
695 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100696
Lawrence Tange407b4c2022-07-21 13:54:01 +0100697 //Set the current position to after the processor context structure.
698 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700699 *remaining_size -= header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100700
Lawrence Tange407b4c2022-07-21 13:54:01 +0100701 return context_ir;
Ed Tanous5e2164a2025-03-09 09:20:44 -0700702
703fail:
704 json_object_put(context_ir);
705 return NULL;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100706}
707
708//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100709json_object *
710cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100711{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100712 json_object *register_array = json_object_new_object();
713 json_object *mrs_encoding = json_object_new_object();
714 json_object_object_add(mrs_encoding, "op2",
715 json_object_new_uint64(misc_register->MrsOp2));
716 json_object_object_add(mrs_encoding, "crm",
717 json_object_new_uint64(misc_register->MrsCrm));
718 json_object_object_add(mrs_encoding, "crn",
719 json_object_new_uint64(misc_register->MrsCrn));
720 json_object_object_add(mrs_encoding, "op1",
721 json_object_new_uint64(misc_register->MrsOp1));
722 json_object_object_add(mrs_encoding, "o0",
723 json_object_new_uint64(misc_register->MrsO0));
724 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
725 json_object_object_add(register_array, "value",
726 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100727
Lawrence Tange407b4c2022-07-21 13:54:01 +0100728 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100729}
730
731//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100732void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100733{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800734 EFI_ARM_ERROR_RECORD section_cper;
735 memset(&section_cper, 0, sizeof(section_cper));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100736
Lawrence Tange407b4c2022-07-21 13:54:01 +0100737 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800738 struct json_object *obj = NULL;
739 ValidationTypes u32Type = { UINT_32T, .value.ui32 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100740
Lawrence Tange407b4c2022-07-21 13:54:01 +0100741 //Count of error/context info structures.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800742 section_cper.ErrInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100743 json_object_object_get(section, "errorInfoNum"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800744 section_cper.ContextInfoNum = json_object_get_int(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100745 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100746
Lawrence Tange407b4c2022-07-21 13:54:01 +0100747 //Miscellaneous raw value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800748 section_cper.SectionLength = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100749 json_object_object_get(section, "sectionLength"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800750 if (json_object_object_get_ex(section, "mpidrEl1", &obj)) {
751 section_cper.MPIDR_EL1 = json_object_get_uint64(obj);
752 add_to_valid_bitfield(&u32Type, 0);
753 }
754 if (json_object_object_get_ex(section, "errorAffinity", &obj)) {
755 section_cper.ErrorAffinityLevel = readable_pair_to_integer(obj);
756 add_to_valid_bitfield(&u32Type, 1);
757 }
758 section_cper.MIDR_EL1 = json_object_get_uint64(
Lawrence Tange407b4c2022-07-21 13:54:01 +0100759 json_object_object_get(section, "midrEl1"));
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800760 if (json_object_object_get_ex(section, "running", &obj)) {
761 section_cper.RunningState = json_object_get_boolean(obj);
762 add_to_valid_bitfield(&u32Type, 2);
763 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100764
Lawrence Tange407b4c2022-07-21 13:54:01 +0100765 //Optional PSCI state.
766 json_object *psci_state = json_object_object_get(section, "psciState");
John Chungf8fc7052024-05-03 20:05:29 +0800767 if (psci_state != NULL) {
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800768 section_cper.PsciState = json_object_get_uint64(psci_state);
John Chungf8fc7052024-05-03 20:05:29 +0800769 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100770
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800771 //Validationbits for EFI_ARM_ERROR_RECORD should also consider vendorSpecificInfo
772 bool vendorSpecificPresent =
773 json_object_object_get_ex(section, "vendorSpecificInfo", &obj);
774 json_object *vendor_specific_info = obj;
775 if (vendorSpecificPresent) {
776 add_to_valid_bitfield(&u32Type, 3);
777 }
778
779 section_cper.ValidFields = u32Type.value.ui32;
780
Lawrence Tange407b4c2022-07-21 13:54:01 +0100781 //Flush header to stream.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800782 fwrite(&section_cper, sizeof(section_cper), 1, out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100783
Lawrence Tange407b4c2022-07-21 13:54:01 +0100784 //Error info structure array.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800785
Lawrence Tange407b4c2022-07-21 13:54:01 +0100786 json_object *error_info = json_object_object_get(section, "errorInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800787 for (int i = 0; i < section_cper.ErrInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100788 ir_arm_error_info_to_cper(
789 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800790 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100791
Lawrence Tange407b4c2022-07-21 13:54:01 +0100792 //Context info structure array.
793 json_object *context_info =
794 json_object_object_get(section, "contextInfo");
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800795 for (int i = 0; i < section_cper.ContextInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100796 ir_arm_context_info_to_cper(
797 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800798 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100799
Lawrence Tange407b4c2022-07-21 13:54:01 +0100800 //Vendor specific error info.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800801 if (vendorSpecificPresent) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100802 json_object *vendor_info_string =
803 json_object_object_get(vendor_specific_info, "data");
804 int vendor_specific_len =
805 json_object_get_string_len(vendor_info_string);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100806
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700807 int32_t decoded_len = 0;
808
809 UINT8 *decoded = base64_decode(
810 json_object_get_string(vendor_info_string),
811 vendor_specific_len, &decoded_len);
812
813 //Write out to file.
814 fwrite(decoded, decoded_len, 1, out);
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700815 free(decoded);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100816 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100817
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800818 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100819}
820
821//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100822void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100823{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100824 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800825 memset(&error_info_cper, 0, sizeof(error_info_cper));
826 struct json_object *obj = NULL;
827 ValidationTypes ui16Type = { UINT_16T, .value.ui16 = 0 };
Lawrence Tang7cd13902022-07-13 16:59:25 +0100828
Lawrence Tange407b4c2022-07-21 13:54:01 +0100829 //Version, length.
830 error_info_cper.Version = json_object_get_int(
831 json_object_object_get(error_info, "version"));
832 error_info_cper.Length = json_object_get_int(
833 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100834
Lawrence Tange407b4c2022-07-21 13:54:01 +0100835 //Type, multiple error.
836 error_info_cper.Type = (UINT8)readable_pair_to_integer(
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800837 json_object_object_get(error_info, "errorType"));
838
839 if (json_object_object_get_ex(error_info, "multipleError", &obj)) {
840 error_info_cper.MultipleError =
841 (UINT16)readable_pair_to_integer(obj);
842 add_to_valid_bitfield(&ui16Type, 0);
843 } else {
844 error_info_cper.MultipleError = 0;
845 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100846
Lawrence Tange407b4c2022-07-21 13:54:01 +0100847 //Flags object.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800848 if (json_object_object_get_ex(error_info, "flags", &obj)) {
849 error_info_cper.Flags = (UINT8)ir_to_bitfield(
850 obj, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
851 add_to_valid_bitfield(&ui16Type, 1);
852 } else {
853 error_info_cper.Flags = 0;
854 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100855
Lawrence Tange407b4c2022-07-21 13:54:01 +0100856 //Error information.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800857 if (json_object_object_get_ex(error_info, "errorInformation", &obj)) {
858 json_object *error_info_information = obj;
859 json_object *error_info_prop = NULL;
860 switch (error_info_cper.Type) {
861 case ARM_ERROR_INFORMATION_TYPE_CACHE:
862 error_info_cper.ErrorInformation.Value = 0;
863 error_info_prop = json_object_object_get(
864 error_info_information, "cacheError");
865 ir_arm_error_cache_tlb_info_to_cper(
866 error_info_prop,
867 &error_info_cper.ErrorInformation.CacheError);
868 break;
869 case ARM_ERROR_INFORMATION_TYPE_TLB:
870 error_info_cper.ErrorInformation.Value = 0;
871 error_info_prop = json_object_object_get(
872 error_info_information, "tlbError");
873 ir_arm_error_cache_tlb_info_to_cper(
874 error_info_prop,
875 &error_info_cper.ErrorInformation.CacheError);
876 break;
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700877
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800878 case ARM_ERROR_INFORMATION_TYPE_BUS:
879 error_info_cper.ErrorInformation.Value = 0;
880 error_info_prop = json_object_object_get(
881 error_info_information, "busError");
882 ir_arm_error_bus_info_to_cper(
883 error_info_prop,
884 &error_info_cper.ErrorInformation.BusError);
885 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100886
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800887 default:
888 //Unknown error information type.
889 break;
890 }
891 add_to_valid_bitfield(&ui16Type, 2);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100892 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100893
Lawrence Tange407b4c2022-07-21 13:54:01 +0100894 //Virtual/physical fault address.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800895 if (json_object_object_get_ex(error_info, "virtualFaultAddress",
896 &obj)) {
897 error_info_cper.VirtualFaultAddress =
898 json_object_get_uint64(obj);
899 add_to_valid_bitfield(&ui16Type, 3);
900 } else {
901 error_info_cper.VirtualFaultAddress = 0;
902 }
903
904 if (json_object_object_get_ex(error_info, "physicalFaultAddress",
905 &obj)) {
906 error_info_cper.PhysicalFaultAddress =
907 json_object_get_uint64(obj);
908 add_to_valid_bitfield(&ui16Type, 4);
909 } else {
910 error_info_cper.PhysicalFaultAddress = 0;
911 }
912 error_info_cper.ValidationBits = ui16Type.value.ui16;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100913
Lawrence Tange407b4c2022-07-21 13:54:01 +0100914 //Write out to stream.
915 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
916 out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100917}
918
Lawrence Tang71570a22022-07-14 11:45:28 +0100919//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100920void ir_arm_error_cache_tlb_info_to_cper(
921 json_object *error_information,
922 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100923{
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800924 // //Validation bits.
925 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
926 struct json_object *obj = NULL;
Lawrence Tang71570a22022-07-14 11:45:28 +0100927
Lawrence Tange407b4c2022-07-21 13:54:01 +0100928 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800929 if (json_object_object_get_ex(error_information, "transactionType",
930 &obj)) {
931 error_info_cper->TransactionType =
932 readable_pair_to_integer(obj);
933 add_to_valid_bitfield(&ui64Type, 0);
934 }
935 if (json_object_object_get_ex(error_information, "operation", &obj)) {
936 error_info_cper->Operation = readable_pair_to_integer(obj);
937 add_to_valid_bitfield(&ui64Type, 1);
938 }
939 if (json_object_object_get_ex(error_information, "level", &obj)) {
940 error_info_cper->Level = json_object_get_uint64(obj);
941 add_to_valid_bitfield(&ui64Type, 2);
942 }
943 if (json_object_object_get_ex(error_information,
944 "processorContextCorrupt", &obj)) {
945 error_info_cper->ProcessorContextCorrupt =
946 json_object_get_boolean(obj);
947 add_to_valid_bitfield(&ui64Type, 3);
948 }
949 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
950 error_info_cper->Corrected = json_object_get_boolean(obj);
951 add_to_valid_bitfield(&ui64Type, 4);
952 }
953 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
954 error_info_cper->PrecisePC = json_object_get_boolean(obj);
955 add_to_valid_bitfield(&ui64Type, 5);
956 }
957 if (json_object_object_get_ex(error_information, "restartablePC",
958 &obj)) {
959 error_info_cper->RestartablePC = json_object_get_boolean(obj);
960 add_to_valid_bitfield(&ui64Type, 6);
961 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100962 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800963 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +0100964}
965
966//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100967void ir_arm_error_bus_info_to_cper(json_object *error_information,
968 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100969{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100970 //Validation bits.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800971 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
972 struct json_object *obj = NULL;
973
974 memset(error_info_cper, 0, sizeof(EFI_ARM_BUS_ERROR_STRUCTURE));
Lawrence Tang71570a22022-07-14 11:45:28 +0100975
Lawrence Tange407b4c2022-07-21 13:54:01 +0100976 //Miscellaneous value fields.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800977 if (json_object_object_get_ex(error_information, "transactionType",
978 &obj)) {
979 error_info_cper->TransactionType =
980 readable_pair_to_integer(obj);
981 add_to_valid_bitfield(&ui64Type, 0);
982 } else {
983 error_info_cper->TransactionType = 0;
984 }
985 if (json_object_object_get_ex(error_information, "operation", &obj)) {
986 error_info_cper->Operation = readable_pair_to_integer(obj);
987 add_to_valid_bitfield(&ui64Type, 1);
988 } else {
989 error_info_cper->Operation = 0;
990 }
991 if (json_object_object_get_ex(error_information, "level", &obj)) {
992 error_info_cper->Level = json_object_get_uint64(obj);
993 add_to_valid_bitfield(&ui64Type, 2);
994 } else {
995 error_info_cper->Level = 0;
996 }
997 if (json_object_object_get_ex(error_information,
998 "processorContextCorrupt", &obj)) {
999 error_info_cper->ProcessorContextCorrupt =
1000 json_object_get_boolean(obj);
1001 add_to_valid_bitfield(&ui64Type, 3);
1002 } else {
1003 error_info_cper->ProcessorContextCorrupt = 0;
1004 }
1005 if (json_object_object_get_ex(error_information, "corrected", &obj)) {
1006 error_info_cper->Corrected = json_object_get_boolean(obj);
1007 add_to_valid_bitfield(&ui64Type, 4);
1008 } else {
1009 error_info_cper->Corrected = 0;
1010 }
1011 if (json_object_object_get_ex(error_information, "precisePC", &obj)) {
1012 error_info_cper->PrecisePC = json_object_get_boolean(obj);
1013 add_to_valid_bitfield(&ui64Type, 5);
1014 } else {
1015 error_info_cper->PrecisePC = 0;
1016 }
1017 if (json_object_object_get_ex(error_information, "restartablePC",
1018 &obj)) {
1019 error_info_cper->RestartablePC = json_object_get_boolean(obj);
1020 add_to_valid_bitfield(&ui64Type, 6);
1021 } else {
1022 error_info_cper->RestartablePC = 0;
1023 }
1024 if (json_object_object_get_ex(error_information, "participationType",
1025 &obj)) {
1026 error_info_cper->ParticipationType =
1027 readable_pair_to_integer(obj);
1028 add_to_valid_bitfield(&ui64Type, 7);
1029 } else {
1030 error_info_cper->ParticipationType = 0;
1031 }
1032 if (json_object_object_get_ex(error_information, "timedOut", &obj)) {
1033 error_info_cper->TimeOut = json_object_get_boolean(obj);
1034 add_to_valid_bitfield(&ui64Type, 8);
1035 } else {
1036 error_info_cper->TimeOut = 0;
1037 }
1038 if (json_object_object_get_ex(error_information, "addressSpace",
1039 &obj)) {
1040 error_info_cper->AddressSpace = readable_pair_to_integer(obj);
1041 add_to_valid_bitfield(&ui64Type, 9);
1042 } else {
1043 error_info_cper->AddressSpace = 0;
1044 }
1045 if (json_object_object_get_ex(error_information, "accessMode", &obj)) {
1046 error_info_cper->AccessMode = readable_pair_to_integer(obj);
1047 add_to_valid_bitfield(&ui64Type, 11);
1048 } else {
1049 error_info_cper->AccessMode = 0;
1050 }
1051 if (json_object_object_get_ex(error_information, "memoryAttributes",
1052 &obj)) {
1053 error_info_cper->MemoryAddressAttributes =
1054 json_object_get_uint64(obj);
1055 add_to_valid_bitfield(&ui64Type, 10);
1056 } else {
1057 error_info_cper->MemoryAddressAttributes = 0;
1058 }
Lawrence Tange407b4c2022-07-21 13:54:01 +01001059 error_info_cper->Reserved = 0;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -08001060 error_info_cper->ValidationBits = ui64Type.value.ui64;
Lawrence Tang71570a22022-07-14 11:45:28 +01001061}
1062
Lawrence Tang7cd13902022-07-13 16:59:25 +01001063//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001064void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +01001065{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001066 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +01001067
Lawrence Tange407b4c2022-07-21 13:54:01 +01001068 //Version, array size, context type.
1069 info_header.Version = json_object_get_int(
1070 json_object_object_get(context_info, "version"));
1071 info_header.RegisterArraySize = json_object_get_int(
1072 json_object_object_get(context_info, "registerArraySize"));
1073 info_header.RegisterContextType = readable_pair_to_integer(
1074 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001075
Lawrence Tange407b4c2022-07-21 13:54:01 +01001076 //Flush to stream, write the register array itself.
1077 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
1078 out);
1079 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001080
Lawrence Tange407b4c2022-07-21 13:54:01 +01001081 json_object *register_array =
1082 json_object_object_get(context_info, "registerArray");
1083 switch (info_header.RegisterContextType) {
1084 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
1085 ir_arm_aarch32_gpr_to_cper(register_array, out);
1086 break;
1087 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
1088 ir_arm_aarch32_el1_to_cper(register_array, out);
1089 break;
1090 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
1091 ir_arm_aarch32_el2_to_cper(register_array, out);
1092 break;
1093 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
1094 ir_arm_aarch32_secure_to_cper(register_array, out);
1095 break;
1096 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
1097 ir_arm_aarch64_gpr_to_cper(register_array, out);
1098 break;
1099 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
1100 ir_arm_aarch64_el1_to_cper(register_array, out);
1101 break;
1102 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
1103 ir_arm_aarch64_el2_to_cper(register_array, out);
1104 break;
1105 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
1106 ir_arm_aarch64_el3_to_cper(register_array, out);
1107 break;
1108 case EFI_ARM_CONTEXT_TYPE_MISC:
1109 ir_arm_misc_registers_to_cper(register_array, out);
1110 break;
1111 default:
1112 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +08001113 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +01001114 break;
1115 }
Lawrence Tang71570a22022-07-14 11:45:28 +01001116}
1117
1118//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001119void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001120{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001121 //Get uniform register array.
1122 EFI_ARM_V8_AARCH32_GPR reg_array;
1123 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1124 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
1125 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001126
Lawrence Tange407b4c2022-07-21 13:54:01 +01001127 //Flush to stream.
1128 fwrite(&reg_array, sizeof(reg_array), 1, out);
1129 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001130}
1131
1132//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 +01001133void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001134{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001135 //Get uniform register array.
1136 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
1137 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1138 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
1139 sizeof(UINT32),
1140 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001141
Lawrence Tange407b4c2022-07-21 13:54:01 +01001142 //Flush to stream.
1143 fwrite(&reg_array, sizeof(reg_array), 1, out);
1144 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001145}
1146
1147//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 +01001148void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001149{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001150 //Get uniform register array.
1151 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
1152 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1153 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
1154 sizeof(UINT32),
1155 ARM_AARCH32_EL2_REGISTER_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 secure register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001163void ir_arm_aarch32_secure_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_SECURE_CONTEXT_REGISTERS reg_array;
1167 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
1168 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
1169 sizeof(UINT32),
1170 ARM_AARCH32_SECURE_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 AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001178void ir_arm_aarch64_gpr_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_V8_AARCH64_GPR reg_array;
1182 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1183 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
1184 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001185
Lawrence Tange407b4c2022-07-21 13:54:01 +01001186 //Flush to stream.
1187 fwrite(&reg_array, sizeof(reg_array), 1, out);
1188 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001189}
1190
1191//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 +01001192void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001193{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001194 //Get uniform register array.
1195 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
1196 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1197 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
1198 sizeof(UINT64),
1199 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +01001200
Lawrence Tange407b4c2022-07-21 13:54:01 +01001201 //Flush to stream.
1202 fwrite(&reg_array, sizeof(reg_array), 1, out);
1203 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001204}
1205
1206//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 +01001207void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001208{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001209 //Get uniform register array.
1210 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
1211 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1212 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
1213 sizeof(UINT64),
1214 ARM_AARCH64_EL2_REGISTER_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 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001222void ir_arm_aarch64_el3_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_EL3_CONTEXT_REGISTERS reg_array;
1226 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
1227 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
1228 sizeof(UINT64),
1229 ARM_AARCH64_EL3_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 ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +01001237void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001238{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001239 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +01001240
Lawrence Tange407b4c2022-07-21 13:54:01 +01001241 //MRS encoding information.
1242 json_object *mrs_encoding =
1243 json_object_object_get(registers, "mrsEncoding");
1244 reg_array.MrsOp2 = json_object_get_uint64(
1245 json_object_object_get(mrs_encoding, "op2"));
1246 reg_array.MrsCrm = json_object_get_uint64(
1247 json_object_object_get(mrs_encoding, "crm"));
1248 reg_array.MrsCrn = json_object_get_uint64(
1249 json_object_object_get(mrs_encoding, "crn"));
1250 reg_array.MrsOp1 = json_object_get_uint64(
1251 json_object_object_get(mrs_encoding, "op1"));
1252 reg_array.MrsO0 = json_object_get_uint64(
1253 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001254
Lawrence Tange407b4c2022-07-21 13:54:01 +01001255 //Actual register value.
1256 reg_array.Value = json_object_get_uint64(
1257 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +01001258
Lawrence Tange407b4c2022-07-21 13:54:01 +01001259 //Flush to stream.
1260 fwrite(&reg_array, sizeof(reg_array), 1, out);
1261 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +01001262}
1263
1264//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +08001265void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +01001266{
Lawrence Tange407b4c2022-07-21 13:54:01 +01001267 //Get base64 represented data.
1268 json_object *encoded = json_object_object_get(registers, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -07001269
1270 int32_t decoded_len = 0;
1271
1272 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
1273 json_object_get_string_len(encoded),
1274 &decoded_len);
1275
1276 if (decoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +08001277 printf("Failed to allocate decode output buffer. \n");
1278 } else {
John Chungf8fc7052024-05-03 20:05:29 +08001279 //Flush out to stream.
1280 fwrite(&decoded, decoded_len, 1, out);
1281 fflush(out);
1282 free(decoded);
1283 }
1284}