blob: d172a99a1aa8a11e0f09f34c0f2d145c7177b9d1 [file] [log] [blame]
Lawrence Tang2800cd82022-07-05 16:08:20 +01001/**
2 * Describes functions for converting ARM CPER sections from binary and JSON format
3 * into an intermediate format.
Ed Tanousfedd4572024-07-12 13:56:00 -07004 *
Lawrence Tang2800cd82022-07-05 16:08:20 +01005 * Author: Lawrence.Tang@arm.com
6 **/
7
8#include <stdio.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +01009#include <json.h>
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070010#include "base64.h"
Lawrence Tang2800cd82022-07-05 16:08:20 +010011#include "../edk/Cper.h"
12#include "../cper-utils.h"
13#include "cper-section-arm.h"
14
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010015//Private pre-definitions.
Lawrence Tange407b4c2022-07-21 13:54:01 +010016json_object *
17cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
18json_object *
19cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
20 void **cur_pos);
21json_object *
22cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
23 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info);
24json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error);
25json_object *cper_arm_misc_register_array_to_ir(
26 EFI_ARM_MISC_CONTEXT_REGISTER *misc_register);
27void ir_arm_error_info_to_cper(json_object *error_info, FILE *out);
28void ir_arm_context_info_to_cper(json_object *context_info, FILE *out);
29void ir_arm_error_cache_tlb_info_to_cper(
30 json_object *error_information,
31 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper);
32void ir_arm_error_bus_info_to_cper(json_object *error_information,
33 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper);
34void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out);
35void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out);
36void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out);
37void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out);
38void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out);
39void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out);
40void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out);
41void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out);
42void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out);
John Chungf8fc7052024-05-03 20:05:29 +080043void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +010044
Lawrence Tang2800cd82022-07-05 16:08:20 +010045//Converts the given processor-generic CPER section into JSON IR.
John Chungf8fc7052024-05-03 20:05:29 +080046json_object *cper_section_arm_to_ir(void *section)
Lawrence Tang2800cd82022-07-05 16:08:20 +010047{
Lawrence Tange407b4c2022-07-21 13:54:01 +010048 EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section;
49 json_object *section_ir = json_object_new_object();
Lawrence Tang2800cd82022-07-05 16:08:20 +010050
Lawrence Tange407b4c2022-07-21 13:54:01 +010051 //Validation bits.
52 json_object *validation = bitfield_to_ir(
53 record->ValidFields, 4, ARM_ERROR_VALID_BITFIELD_NAMES);
54 json_object_object_add(section_ir, "validationBits", validation);
Lawrence Tang2800cd82022-07-05 16:08:20 +010055
Lawrence Tange407b4c2022-07-21 13:54:01 +010056 //Number of error info and context info structures, and length.
57 json_object_object_add(section_ir, "errorInfoNum",
58 json_object_new_int(record->ErrInfoNum));
59 json_object_object_add(section_ir, "contextInfoNum",
60 json_object_new_int(record->ContextInfoNum));
61 json_object_object_add(section_ir, "sectionLength",
62 json_object_new_uint64(record->SectionLength));
Lawrence Tang2800cd82022-07-05 16:08:20 +010063
Lawrence Tange407b4c2022-07-21 13:54:01 +010064 //Error affinity.
65 json_object *error_affinity = json_object_new_object();
66 json_object_object_add(error_affinity, "value",
67 json_object_new_int(record->ErrorAffinityLevel));
68 json_object_object_add(
69 error_affinity, "type",
70 json_object_new_string(record->ErrorAffinityLevel < 4 ?
John Chungf8fc7052024-05-03 20:05:29 +080071 "Vendor Defined" :
72 "Reserved"));
Lawrence Tange407b4c2022-07-21 13:54:01 +010073 json_object_object_add(section_ir, "errorAffinity", error_affinity);
Lawrence Tang2800cd82022-07-05 16:08:20 +010074
Lawrence Tange407b4c2022-07-21 13:54:01 +010075 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1).
76 json_object_object_add(section_ir, "mpidrEl1",
77 json_object_new_uint64(record->MPIDR_EL1));
78 json_object_object_add(section_ir, "midrEl1",
79 json_object_new_uint64(record->MIDR_EL1));
Lawrence Tang2800cd82022-07-05 16:08:20 +010080
Lawrence Tange407b4c2022-07-21 13:54:01 +010081 //Whether the processor is running, and the state of it if so.
82 json_object_object_add(section_ir, "running",
83 json_object_new_boolean(record->RunningState &
John Chungf8fc7052024-05-03 20:05:29 +080084 0x1));
Lawrence Tange407b4c2022-07-21 13:54:01 +010085 if (!(record->RunningState >> 31)) {
86 //Bit 32 of running state is on, so PSCI state information is included.
87 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format
88 //or the newer Extended StateID format.
89 json_object_object_add(
90 section_ir, "psciState",
91 json_object_new_uint64(record->PsciState));
92 }
Lawrence Tang7f21db62022-07-06 11:09:39 +010093
Lawrence Tange407b4c2022-07-21 13:54:01 +010094 //Processor error structures.
95 json_object *error_info_array = json_object_new_array();
96 EFI_ARM_ERROR_INFORMATION_ENTRY *cur_error =
97 (EFI_ARM_ERROR_INFORMATION_ENTRY *)(record + 1);
98 for (int i = 0; i < record->ErrInfoNum; i++) {
99 json_object_array_add(error_info_array,
100 cper_arm_error_info_to_ir(cur_error));
101 cur_error++;
102 }
103 json_object_object_add(section_ir, "errorInfo", error_info_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100104
Lawrence Tange407b4c2022-07-21 13:54:01 +0100105 //Processor context structures.
106 //The current position is moved within the processing, as it is a dynamic size structure.
John Chungf8fc7052024-05-03 20:05:29 +0800107 uint8_t *cur_pos = (uint8_t *)cur_error;
Lawrence Tange407b4c2022-07-21 13:54:01 +0100108 json_object *context_info_array = json_object_new_array();
109 for (int i = 0; i < record->ContextInfoNum; i++) {
110 EFI_ARM_CONTEXT_INFORMATION_HEADER *header =
111 (EFI_ARM_CONTEXT_INFORMATION_HEADER *)cur_pos;
112 json_object *processor_context =
John Chungf8fc7052024-05-03 20:05:29 +0800113 cper_arm_processor_context_to_ir(header,
114 (void **)&cur_pos);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100115 json_object_array_add(context_info_array, processor_context);
116 }
117 json_object_object_add(section_ir, "contextInfo", context_info_array);
Lawrence Tangd7e8ca32022-07-07 10:25:53 +0100118
Lawrence Tange407b4c2022-07-21 13:54:01 +0100119 //Is there any vendor-specific information following?
John Chungf8fc7052024-05-03 20:05:29 +0800120 if (cur_pos < (uint8_t *)section + record->SectionLength) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121 json_object *vendor_specific = json_object_new_object();
John Chungf8fc7052024-05-03 20:05:29 +0800122 size_t input_size =
123 (uint8_t *)section + record->SectionLength - cur_pos;
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700124 int32_t encoded_len = 0;
125 char *encoded =
126 base64_encode(cur_pos, input_size, &encoded_len);
127 if (encoded == NULL) {
128 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +0800129 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700130 json_object_object_add(vendor_specific, "data",
131 json_object_new_string_len(encoded,
132 encoded_len));
133 free(encoded);
134
135 json_object_object_add(section_ir, "vendorSpecificInfo",
136 vendor_specific);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100137 }
138
139 return section_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100140}
141
142//Converts a single ARM Process Error Information structure into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100143json_object *
144cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100145{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100146 json_object *error_info_ir = json_object_new_object();
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100147
Lawrence Tange407b4c2022-07-21 13:54:01 +0100148 //Version, length.
149 json_object_object_add(error_info_ir, "version",
150 json_object_new_int(error_info->Version));
151 json_object_object_add(error_info_ir, "length",
152 json_object_new_int(error_info->Length));
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100153
Lawrence Tange407b4c2022-07-21 13:54:01 +0100154 //Validation bitfield.
155 json_object *validation =
156 bitfield_to_ir(error_info->ValidationBits, 5,
157 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
158 json_object_object_add(error_info_ir, "validationBits", validation);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100159
Lawrence Tange407b4c2022-07-21 13:54:01 +0100160 //The type of error information in this log.
161 json_object *error_type = integer_to_readable_pair(
162 error_info->Type, 4, ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
163 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, "Unknown (Reserved)");
164 json_object_object_add(error_info_ir, "errorType", error_type);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100165
Lawrence Tange407b4c2022-07-21 13:54:01 +0100166 //Multiple error count.
167 json_object *multiple_error = json_object_new_object();
168 json_object_object_add(multiple_error, "value",
169 json_object_new_int(error_info->MultipleError));
170 json_object_object_add(
171 multiple_error, "type",
172 json_object_new_string(error_info->MultipleError < 1 ?
John Chungf8fc7052024-05-03 20:05:29 +0800173 "Single Error" :
174 "Multiple Errors"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100175 json_object_object_add(error_info_ir, "multipleError", multiple_error);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100176
Lawrence Tange407b4c2022-07-21 13:54:01 +0100177 //Flags.
178 json_object *flags = bitfield_to_ir(error_info->Flags, 4,
179 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
180 json_object_object_add(error_info_ir, "flags", flags);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100181
Lawrence Tange407b4c2022-07-21 13:54:01 +0100182 //Error information, split by type.
183 json_object *error_subinfo = NULL;
184 switch (error_info->Type) {
185 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache
John Chungf8fc7052024-05-03 20:05:29 +0800186 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB
Lawrence Tange407b4c2022-07-21 13:54:01 +0100187 error_subinfo = cper_arm_cache_tlb_error_to_ir(
188 (EFI_ARM_CACHE_ERROR_STRUCTURE *)&error_info
189 ->ErrorInformation,
190 error_info);
191 break;
192 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus
193 error_subinfo = cper_arm_bus_error_to_ir(
194 (EFI_ARM_BUS_ERROR_STRUCTURE *)&error_info
195 ->ErrorInformation);
196 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100197
Lawrence Tange407b4c2022-07-21 13:54:01 +0100198 default:
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700199 //Unknown/microarch, will not support.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100200 break;
201 }
202 json_object_object_add(error_info_ir, "errorInformation",
203 error_subinfo);
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100204
Lawrence Tange407b4c2022-07-21 13:54:01 +0100205 //Virtual fault address, physical fault address.
206 json_object_object_add(
207 error_info_ir, "virtualFaultAddress",
208 json_object_new_uint64(error_info->VirtualFaultAddress));
209 json_object_object_add(
210 error_info_ir, "physicalFaultAddress",
211 json_object_new_uint64(error_info->PhysicalFaultAddress));
212
213 return error_info_ir;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100214}
215
Lawrence Tang7f21db62022-07-06 11:09:39 +0100216//Converts a single ARM cache/TLB error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100217json_object *
218cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE *cache_tlb_error,
219 EFI_ARM_ERROR_INFORMATION_ENTRY *error_info)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100220{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100221 json_object *cache_tlb_error_ir = json_object_new_object();
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700222 json_object *cache_tlb_prop = json_object_new_object();
223 char *cache_tlb_propname;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100224
Lawrence Tange407b4c2022-07-21 13:54:01 +0100225 //Validation bitfield.
226 json_object *validation =
227 bitfield_to_ir(cache_tlb_error->ValidationBits, 7,
228 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
229 json_object_object_add(cache_tlb_error_ir, "validationBits",
230 validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100231
Lawrence Tange407b4c2022-07-21 13:54:01 +0100232 //Transaction type.
233 json_object *transaction_type = integer_to_readable_pair(
234 cache_tlb_error->TransactionType, 3,
235 ARM_ERROR_TRANSACTION_TYPES_KEYS,
236 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
237 json_object_object_add(cache_tlb_error_ir, "transactionType",
238 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100239
Lawrence Tange407b4c2022-07-21 13:54:01 +0100240 //Operation.
241 json_object *operation;
242 if (error_info->Type == 0) {
243 //Cache operation.
244 operation = integer_to_readable_pair(
245 cache_tlb_error->Operation, 11,
246 ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
247 ARM_CACHE_BUS_OPERATION_TYPES_VALUES,
248 "Unknown (Reserved)");
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700249 cache_tlb_propname = "cacheError";
Lawrence Tange407b4c2022-07-21 13:54:01 +0100250 } else {
251 //TLB operation.
252 operation = integer_to_readable_pair(
253 cache_tlb_error->Operation, 9,
254 ARM_TLB_OPERATION_TYPES_KEYS,
255 ARM_TLB_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700256 cache_tlb_propname = "tlbError";
Lawrence Tange407b4c2022-07-21 13:54:01 +0100257 }
258 json_object_object_add(cache_tlb_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100259
Lawrence Tange407b4c2022-07-21 13:54:01 +0100260 //Miscellaneous remaining fields.
261 json_object_object_add(cache_tlb_error_ir, "level",
262 json_object_new_int(cache_tlb_error->Level));
263 json_object_object_add(
264 cache_tlb_error_ir, "processorContextCorrupt",
265 json_object_new_boolean(
266 cache_tlb_error->ProcessorContextCorrupt));
267 json_object_object_add(
268 cache_tlb_error_ir, "corrected",
269 json_object_new_boolean(cache_tlb_error->Corrected));
270 json_object_object_add(
271 cache_tlb_error_ir, "precisePC",
272 json_object_new_boolean(cache_tlb_error->PrecisePC));
273 json_object_object_add(
274 cache_tlb_error_ir, "restartablePC",
275 json_object_new_boolean(cache_tlb_error->RestartablePC));
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700276
277 json_object_object_add(cache_tlb_prop, cache_tlb_propname,
278 cache_tlb_error_ir);
279 return cache_tlb_prop;
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100280}
281
282//Converts a single ARM bus error information structure into JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100283json_object *cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE *bus_error)
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100284{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100285 json_object *bus_error_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100286
Lawrence Tange407b4c2022-07-21 13:54:01 +0100287 //Validation bits.
288 json_object *validation =
289 bitfield_to_ir(bus_error->ValidationBits, 12,
290 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
291 json_object_object_add(bus_error_ir, "validationBits", validation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100292
Lawrence Tange407b4c2022-07-21 13:54:01 +0100293 //Transaction type.
294 json_object *transaction_type = integer_to_readable_pair(
295 bus_error->TransactionType, 3, ARM_ERROR_TRANSACTION_TYPES_KEYS,
296 ARM_ERROR_TRANSACTION_TYPES_VALUES, "Unknown (Reserved)");
297 json_object_object_add(bus_error_ir, "transactionType",
298 transaction_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100299
Lawrence Tange407b4c2022-07-21 13:54:01 +0100300 //Operation.
301 json_object *operation = integer_to_readable_pair(
302 bus_error->Operation, 7, ARM_CACHE_BUS_OPERATION_TYPES_KEYS,
303 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
304 json_object_object_add(bus_error_ir, "operation", operation);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100305
Lawrence Tange407b4c2022-07-21 13:54:01 +0100306 //Affinity level of bus error, + miscellaneous fields.
307 json_object_object_add(bus_error_ir, "level",
308 json_object_new_int(bus_error->Level));
309 json_object_object_add(
310 bus_error_ir, "processorContextCorrupt",
311 json_object_new_boolean(bus_error->ProcessorContextCorrupt));
312 json_object_object_add(bus_error_ir, "corrected",
313 json_object_new_boolean(bus_error->Corrected));
314 json_object_object_add(bus_error_ir, "precisePC",
315 json_object_new_boolean(bus_error->PrecisePC));
316 json_object_object_add(
317 bus_error_ir, "restartablePC",
318 json_object_new_boolean(bus_error->RestartablePC));
319 json_object_object_add(bus_error_ir, "timedOut",
320 json_object_new_boolean(bus_error->TimeOut));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100321
Lawrence Tange407b4c2022-07-21 13:54:01 +0100322 //Participation type.
323 json_object *participation_type = integer_to_readable_pair(
324 bus_error->ParticipationType, 4,
325 ARM_BUS_PARTICIPATION_TYPES_KEYS,
326 ARM_BUS_PARTICIPATION_TYPES_VALUES, "Unknown");
327 json_object_object_add(bus_error_ir, "participationType",
328 participation_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100329
Lawrence Tange407b4c2022-07-21 13:54:01 +0100330 //Address space.
331 json_object *address_space = integer_to_readable_pair(
332 bus_error->AddressSpace, 3, ARM_BUS_ADDRESS_SPACE_TYPES_KEYS,
333 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, "Unknown");
334 json_object_object_add(bus_error_ir, "addressSpace", address_space);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100335
Lawrence Tange407b4c2022-07-21 13:54:01 +0100336 //Memory access attributes.
337 //todo: find the specification of these in the ARM ARM
338 json_object_object_add(
339 bus_error_ir, "memoryAttributes",
340 json_object_new_int(bus_error->MemoryAddressAttributes));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100341
Lawrence Tange407b4c2022-07-21 13:54:01 +0100342 //Access Mode
343 json_object *access_mode = json_object_new_object();
344 json_object_object_add(access_mode, "value",
345 json_object_new_int(bus_error->AccessMode));
346 json_object_object_add(
347 access_mode, "name",
348 json_object_new_string(bus_error->AccessMode == 0 ? "Secure" :
John Chungf8fc7052024-05-03 20:05:29 +0800349 "Normal"));
Lawrence Tange407b4c2022-07-21 13:54:01 +0100350 json_object_object_add(bus_error_ir, "accessMode", access_mode);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100351
Lawrence Tange407b4c2022-07-21 13:54:01 +0100352 return bus_error_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100353}
354
355//Converts a single ARM processor context block into JSON IR.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100356json_object *
357cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER *header,
358 void **cur_pos)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100359{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100360 json_object *context_ir = json_object_new_object();
Lawrence Tang7f21db62022-07-06 11:09:39 +0100361
Lawrence Tange407b4c2022-07-21 13:54:01 +0100362 //Version.
363 json_object_object_add(context_ir, "version",
364 json_object_new_int(header->Version));
Lawrence Tang71570a22022-07-14 11:45:28 +0100365
Lawrence Tange407b4c2022-07-21 13:54:01 +0100366 //Add the context type.
367 json_object *context_type = integer_to_readable_pair(
368 header->RegisterContextType, 9,
369 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS,
370 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES,
371 "Unknown (Reserved)");
372 json_object_object_add(context_ir, "registerContextType", context_type);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100373
Lawrence Tange407b4c2022-07-21 13:54:01 +0100374 //Register array size (bytes).
375 json_object_object_add(
376 context_ir, "registerArraySize",
377 json_object_new_uint64(header->RegisterArraySize));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100378
Lawrence Tange407b4c2022-07-21 13:54:01 +0100379 //The register array itself.
380 *cur_pos = (void *)(header + 1);
381 json_object *register_array = NULL;
382 switch (header->RegisterContextType) {
383 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
384 register_array = uniform_struct_to_ir(
385 (UINT32 *)cur_pos,
386 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
387 ARM_AARCH32_GPR_NAMES);
388 break;
389 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
390 register_array = uniform_struct_to_ir(
391 (UINT32 *)cur_pos,
392 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
393 sizeof(UINT32),
394 ARM_AARCH32_EL1_REGISTER_NAMES);
395 break;
396 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
397 register_array = uniform_struct_to_ir(
398 (UINT32 *)cur_pos,
399 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
400 sizeof(UINT32),
401 ARM_AARCH32_EL2_REGISTER_NAMES);
402 break;
403 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
404 register_array = uniform_struct_to_ir(
405 (UINT32 *)cur_pos,
406 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
407 sizeof(UINT32),
408 ARM_AARCH32_SECURE_REGISTER_NAMES);
409 break;
410 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
411 register_array = uniform_struct64_to_ir(
412 (UINT64 *)cur_pos,
413 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
414 ARM_AARCH64_GPR_NAMES);
415 break;
416 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
417 register_array = uniform_struct64_to_ir(
418 (UINT64 *)cur_pos,
419 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
420 sizeof(UINT64),
421 ARM_AARCH64_EL1_REGISTER_NAMES);
422 break;
423 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
424 register_array = uniform_struct64_to_ir(
425 (UINT64 *)cur_pos,
426 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
427 sizeof(UINT64),
428 ARM_AARCH64_EL2_REGISTER_NAMES);
429 break;
430 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
431 register_array = uniform_struct64_to_ir(
432 (UINT64 *)cur_pos,
433 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
434 sizeof(UINT64),
435 ARM_AARCH64_EL3_REGISTER_NAMES);
436 break;
437 case EFI_ARM_CONTEXT_TYPE_MISC:
438 register_array = cper_arm_misc_register_array_to_ir(
439 (EFI_ARM_MISC_CONTEXT_REGISTER *)cur_pos);
440 break;
441 default:
442 //Unknown register array type, add as base64 data instead.
443 register_array = json_object_new_object();
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700444 int32_t encoded_len = 0;
445 char *encoded = base64_encode((UINT8 *)cur_pos,
446 header->RegisterArraySize,
447 &encoded_len);
448 if (encoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800449 printf("Failed to allocate encode output buffer. \n");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700450 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +0800451 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700452 json_object_object_add(register_array, "data",
453 json_object_new_string_len(encoded,
454 encoded_len));
455 free(encoded);
456
Lawrence Tange407b4c2022-07-21 13:54:01 +0100457 break;
458 }
459 json_object_object_add(context_ir, "registerArray", register_array);
Lawrence Tang7f21db62022-07-06 11:09:39 +0100460
Lawrence Tange407b4c2022-07-21 13:54:01 +0100461 //Set the current position to after the processor context structure.
462 *cur_pos = (UINT8 *)(*cur_pos) + header->RegisterArraySize;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100463
Lawrence Tange407b4c2022-07-21 13:54:01 +0100464 return context_ir;
Lawrence Tang7f21db62022-07-06 11:09:39 +0100465}
466
467//Converts a single CPER ARM miscellaneous register array to JSON IR format.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100468json_object *
469cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER *misc_register)
Lawrence Tang7f21db62022-07-06 11:09:39 +0100470{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100471 json_object *register_array = json_object_new_object();
472 json_object *mrs_encoding = json_object_new_object();
473 json_object_object_add(mrs_encoding, "op2",
474 json_object_new_uint64(misc_register->MrsOp2));
475 json_object_object_add(mrs_encoding, "crm",
476 json_object_new_uint64(misc_register->MrsCrm));
477 json_object_object_add(mrs_encoding, "crn",
478 json_object_new_uint64(misc_register->MrsCrn));
479 json_object_object_add(mrs_encoding, "op1",
480 json_object_new_uint64(misc_register->MrsOp1));
481 json_object_object_add(mrs_encoding, "o0",
482 json_object_new_uint64(misc_register->MrsO0));
483 json_object_object_add(register_array, "mrsEncoding", mrs_encoding);
484 json_object_object_add(register_array, "value",
485 json_object_new_uint64(misc_register->Value));
Lawrence Tang7f21db62022-07-06 11:09:39 +0100486
Lawrence Tange407b4c2022-07-21 13:54:01 +0100487 return register_array;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100488}
489
490//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100491void ir_section_arm_to_cper(json_object *section, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100492{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100493 EFI_ARM_ERROR_RECORD *section_cper =
494 (EFI_ARM_ERROR_RECORD *)calloc(1, sizeof(EFI_ARM_ERROR_RECORD));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100495
Lawrence Tange407b4c2022-07-21 13:54:01 +0100496 //Validation bits.
497 section_cper->ValidFields = ir_to_bitfield(
498 json_object_object_get(section, "validationBits"), 4,
499 ARM_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100500
Lawrence Tange407b4c2022-07-21 13:54:01 +0100501 //Count of error/context info structures.
502 section_cper->ErrInfoNum = json_object_get_int(
503 json_object_object_get(section, "errorInfoNum"));
504 section_cper->ContextInfoNum = json_object_get_int(
505 json_object_object_get(section, "contextInfoNum"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100506
Lawrence Tange407b4c2022-07-21 13:54:01 +0100507 //Miscellaneous raw value fields.
508 section_cper->SectionLength = json_object_get_uint64(
509 json_object_object_get(section, "sectionLength"));
510 section_cper->ErrorAffinityLevel = readable_pair_to_integer(
511 json_object_object_get(section, "errorAffinity"));
512 section_cper->MPIDR_EL1 = json_object_get_uint64(
513 json_object_object_get(section, "mpidrEl1"));
514 section_cper->MIDR_EL1 = json_object_get_uint64(
515 json_object_object_get(section, "midrEl1"));
516 section_cper->RunningState = json_object_get_boolean(
517 json_object_object_get(section, "running"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100518
Lawrence Tange407b4c2022-07-21 13:54:01 +0100519 //Optional PSCI state.
520 json_object *psci_state = json_object_object_get(section, "psciState");
John Chungf8fc7052024-05-03 20:05:29 +0800521 if (psci_state != NULL) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100522 section_cper->PsciState = json_object_get_uint64(psci_state);
John Chungf8fc7052024-05-03 20:05:29 +0800523 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100524
Lawrence Tange407b4c2022-07-21 13:54:01 +0100525 //Flush header to stream.
526 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out);
527 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100528
Lawrence Tange407b4c2022-07-21 13:54:01 +0100529 //Error info structure array.
530 json_object *error_info = json_object_object_get(section, "errorInfo");
John Chungf8fc7052024-05-03 20:05:29 +0800531 for (int i = 0; i < section_cper->ErrInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100532 ir_arm_error_info_to_cper(
533 json_object_array_get_idx(error_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800534 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100535
Lawrence Tange407b4c2022-07-21 13:54:01 +0100536 //Context info structure array.
537 json_object *context_info =
538 json_object_object_get(section, "contextInfo");
John Chungf8fc7052024-05-03 20:05:29 +0800539 for (int i = 0; i < section_cper->ContextInfoNum; i++) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100540 ir_arm_context_info_to_cper(
541 json_object_array_get_idx(context_info, i), out);
John Chungf8fc7052024-05-03 20:05:29 +0800542 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100543
Lawrence Tange407b4c2022-07-21 13:54:01 +0100544 //Vendor specific error info.
545 json_object *vendor_specific_info =
546 json_object_object_get(section, "vendorSpecificInfo");
547 if (vendor_specific_info != NULL) {
548 json_object *vendor_info_string =
549 json_object_object_get(vendor_specific_info, "data");
550 int vendor_specific_len =
551 json_object_get_string_len(vendor_info_string);
Lawrence Tang01e3a442022-07-20 15:14:50 +0100552
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700553 int32_t decoded_len = 0;
554
555 UINT8 *decoded = base64_decode(
556 json_object_get_string(vendor_info_string),
557 vendor_specific_len, &decoded_len);
558
559 //Write out to file.
560 fwrite(decoded, decoded_len, 1, out);
561 fflush(out);
562 free(decoded);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100563 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100564
Lawrence Tange407b4c2022-07-21 13:54:01 +0100565 //Free remaining resources.
566 free(section_cper);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100567}
568
569//Converts a single ARM error information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100570void ir_arm_error_info_to_cper(json_object *error_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100571{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100572 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100573
Lawrence Tange407b4c2022-07-21 13:54:01 +0100574 //Version, length.
575 error_info_cper.Version = json_object_get_int(
576 json_object_object_get(error_info, "version"));
577 error_info_cper.Length = json_object_get_int(
578 json_object_object_get(error_info, "length"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100579
Lawrence Tange407b4c2022-07-21 13:54:01 +0100580 //Validation bits.
581 error_info_cper.ValidationBits = ir_to_bitfield(
582 json_object_object_get(error_info, "validationBits"), 5,
583 ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100584
Lawrence Tange407b4c2022-07-21 13:54:01 +0100585 //Type, multiple error.
586 error_info_cper.Type = (UINT8)readable_pair_to_integer(
587 json_object_object_get(error_info, "type"));
588 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer(
589 json_object_object_get(error_info, "multipleError"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100590
Lawrence Tange407b4c2022-07-21 13:54:01 +0100591 //Flags object.
592 error_info_cper.Flags = (UINT8)ir_to_bitfield(
593 json_object_object_get(error_info, "flags"), 4,
594 ARM_ERROR_INFO_ENTRY_FLAGS_NAMES);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100595
Lawrence Tange407b4c2022-07-21 13:54:01 +0100596 //Error information.
597 json_object *error_info_information =
598 json_object_object_get(error_info, "errorInformation");
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700599 json_object *error_info_prop = NULL;
600
Lawrence Tange407b4c2022-07-21 13:54:01 +0100601 switch (error_info_cper.Type) {
602 case ARM_ERROR_INFORMATION_TYPE_CACHE:
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700603 error_info_prop = json_object_object_get(error_info_information,
604 "cacheError");
Lawrence Tange407b4c2022-07-21 13:54:01 +0100605 ir_arm_error_cache_tlb_info_to_cper(
Aushim Nagarkatti5b793002024-09-26 17:07:30 -0700606 error_info_prop,
607 &error_info_cper.ErrorInformation.CacheError);
608 break;
609 case ARM_ERROR_INFORMATION_TYPE_TLB:
610 error_info_prop = json_object_object_get(error_info_information,
611 "tlbError");
612 ir_arm_error_cache_tlb_info_to_cper(
613 error_info_prop,
Lawrence Tange407b4c2022-07-21 13:54:01 +0100614 &error_info_cper.ErrorInformation.CacheError);
615 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100616
Lawrence Tange407b4c2022-07-21 13:54:01 +0100617 case ARM_ERROR_INFORMATION_TYPE_BUS:
618 ir_arm_error_bus_info_to_cper(
619 error_info_information,
620 &error_info_cper.ErrorInformation.BusError);
621 break;
Lawrence Tang71570a22022-07-14 11:45:28 +0100622
Lawrence Tange407b4c2022-07-21 13:54:01 +0100623 default:
624 //Unknown error information type.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100625 break;
626 }
Lawrence Tang7cd13902022-07-13 16:59:25 +0100627
Lawrence Tange407b4c2022-07-21 13:54:01 +0100628 //Virtual/physical fault address.
629 error_info_cper.VirtualFaultAddress = json_object_get_uint64(
630 json_object_object_get(error_info, "virtualFaultAddress"));
631 error_info_cper.PhysicalFaultAddress = json_object_get_uint64(
632 json_object_object_get(error_info, "physicalFaultAddress"));
Lawrence Tang7cd13902022-07-13 16:59:25 +0100633
Lawrence Tange407b4c2022-07-21 13:54:01 +0100634 //Write out to stream.
635 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1,
636 out);
637 fflush(out);
Lawrence Tang7cd13902022-07-13 16:59:25 +0100638}
639
Lawrence Tang71570a22022-07-14 11:45:28 +0100640//Converts a single ARM cache/TLB error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100641void ir_arm_error_cache_tlb_info_to_cper(
642 json_object *error_information,
643 EFI_ARM_CACHE_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100644{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100645 //Validation bits.
646 error_info_cper->ValidationBits = ir_to_bitfield(
647 json_object_object_get(error_information, "validationBits"), 7,
648 ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100649
Lawrence Tange407b4c2022-07-21 13:54:01 +0100650 //Miscellaneous value fields.
651 error_info_cper->TransactionType = readable_pair_to_integer(
652 json_object_object_get(error_information, "transactionType"));
653 error_info_cper->Operation = readable_pair_to_integer(
654 json_object_object_get(error_information, "operation"));
655 error_info_cper->Level = json_object_get_uint64(
656 json_object_object_get(error_information, "level"));
657 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
658 json_object_object_get(error_information,
659 "processorContextCorrupt"));
660 error_info_cper->Corrected = json_object_get_boolean(
661 json_object_object_get(error_information, "corrected"));
662 error_info_cper->PrecisePC = json_object_get_boolean(
663 json_object_object_get(error_information, "precisePC"));
664 error_info_cper->RestartablePC = json_object_get_boolean(
665 json_object_object_get(error_information, "restartablePC"));
666 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100667}
668
669//Converts a single ARM bus error information structure into a CPER structure.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100670void ir_arm_error_bus_info_to_cper(json_object *error_information,
671 EFI_ARM_BUS_ERROR_STRUCTURE *error_info_cper)
Lawrence Tang71570a22022-07-14 11:45:28 +0100672{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100673 //Validation bits.
674 error_info_cper->ValidationBits = ir_to_bitfield(
675 json_object_object_get(error_information, "validationBits"), 7,
676 ARM_BUS_ERROR_VALID_BITFIELD_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100677
Lawrence Tange407b4c2022-07-21 13:54:01 +0100678 //Miscellaneous value fields.
679 error_info_cper->TransactionType = readable_pair_to_integer(
680 json_object_object_get(error_information, "transactionType"));
681 error_info_cper->Operation = readable_pair_to_integer(
682 json_object_object_get(error_information, "operation"));
683 error_info_cper->Level = json_object_get_uint64(
684 json_object_object_get(error_information, "level"));
685 error_info_cper->ProcessorContextCorrupt = json_object_get_boolean(
686 json_object_object_get(error_information,
687 "processorContextCorrupt"));
688 error_info_cper->Corrected = json_object_get_boolean(
689 json_object_object_get(error_information, "corrected"));
690 error_info_cper->PrecisePC = json_object_get_boolean(
691 json_object_object_get(error_information, "precisePC"));
692 error_info_cper->RestartablePC = json_object_get_boolean(
693 json_object_object_get(error_information, "restartablePC"));
694 error_info_cper->ParticipationType = readable_pair_to_integer(
695 json_object_object_get(error_information, "participationType"));
696 error_info_cper->AddressSpace = readable_pair_to_integer(
697 json_object_object_get(error_information, "addressSpace"));
698 error_info_cper->AccessMode = readable_pair_to_integer(
699 json_object_object_get(error_information, "accessMode"));
700 error_info_cper->MemoryAddressAttributes = json_object_get_uint64(
701 json_object_object_get(error_information, "memoryAttributes"));
702 error_info_cper->Reserved = 0;
Lawrence Tang71570a22022-07-14 11:45:28 +0100703}
704
Lawrence Tang7cd13902022-07-13 16:59:25 +0100705//Converts a single ARM context information structure into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100706void ir_arm_context_info_to_cper(json_object *context_info, FILE *out)
Lawrence Tang7cd13902022-07-13 16:59:25 +0100707{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100708 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header;
Lawrence Tang7cd13902022-07-13 16:59:25 +0100709
Lawrence Tange407b4c2022-07-21 13:54:01 +0100710 //Version, array size, context type.
711 info_header.Version = json_object_get_int(
712 json_object_object_get(context_info, "version"));
713 info_header.RegisterArraySize = json_object_get_int(
714 json_object_object_get(context_info, "registerArraySize"));
715 info_header.RegisterContextType = readable_pair_to_integer(
716 json_object_object_get(context_info, "registerContextType"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100717
Lawrence Tange407b4c2022-07-21 13:54:01 +0100718 //Flush to stream, write the register array itself.
719 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1,
720 out);
721 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100722
Lawrence Tange407b4c2022-07-21 13:54:01 +0100723 json_object *register_array =
724 json_object_object_get(context_info, "registerArray");
725 switch (info_header.RegisterContextType) {
726 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR:
727 ir_arm_aarch32_gpr_to_cper(register_array, out);
728 break;
729 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1:
730 ir_arm_aarch32_el1_to_cper(register_array, out);
731 break;
732 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2:
733 ir_arm_aarch32_el2_to_cper(register_array, out);
734 break;
735 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE:
736 ir_arm_aarch32_secure_to_cper(register_array, out);
737 break;
738 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR:
739 ir_arm_aarch64_gpr_to_cper(register_array, out);
740 break;
741 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1:
742 ir_arm_aarch64_el1_to_cper(register_array, out);
743 break;
744 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2:
745 ir_arm_aarch64_el2_to_cper(register_array, out);
746 break;
747 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3:
748 ir_arm_aarch64_el3_to_cper(register_array, out);
749 break;
750 case EFI_ARM_CONTEXT_TYPE_MISC:
751 ir_arm_misc_registers_to_cper(register_array, out);
752 break;
753 default:
754 //Unknown register structure.
John Chungf8fc7052024-05-03 20:05:29 +0800755 ir_arm_unknown_register_to_cper(register_array, out);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100756 break;
757 }
Lawrence Tang71570a22022-07-14 11:45:28 +0100758}
759
760//Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100761void ir_arm_aarch32_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100762{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100763 //Get uniform register array.
764 EFI_ARM_V8_AARCH32_GPR reg_array;
765 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
766 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32),
767 ARM_AARCH32_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100768
Lawrence Tange407b4c2022-07-21 13:54:01 +0100769 //Flush to stream.
770 fwrite(&reg_array, sizeof(reg_array), 1, out);
771 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100772}
773
774//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 +0100775void ir_arm_aarch32_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100776{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100777 //Get uniform register array.
778 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array;
779 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
780 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) /
781 sizeof(UINT32),
782 ARM_AARCH32_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100783
Lawrence Tange407b4c2022-07-21 13:54:01 +0100784 //Flush to stream.
785 fwrite(&reg_array, sizeof(reg_array), 1, out);
786 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100787}
788
789//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 +0100790void ir_arm_aarch32_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100791{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100792 //Get uniform register array.
793 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array;
794 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
795 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) /
796 sizeof(UINT32),
797 ARM_AARCH32_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100798
Lawrence Tange407b4c2022-07-21 13:54:01 +0100799 //Flush to stream.
800 fwrite(&reg_array, sizeof(reg_array), 1, out);
801 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100802}
803
804//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 +0100805void ir_arm_aarch32_secure_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100806{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100807 //Get uniform register array.
808 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array;
809 ir_to_uniform_struct(registers, (UINT32 *)&reg_array,
810 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) /
811 sizeof(UINT32),
812 ARM_AARCH32_SECURE_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100813
Lawrence Tange407b4c2022-07-21 13:54:01 +0100814 //Flush to stream.
815 fwrite(&reg_array, sizeof(reg_array), 1, out);
816 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100817}
818
819//Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100820void ir_arm_aarch64_gpr_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100821{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100822 //Get uniform register array.
823 EFI_ARM_V8_AARCH64_GPR reg_array;
824 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
825 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64),
826 ARM_AARCH64_GPR_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100827
Lawrence Tange407b4c2022-07-21 13:54:01 +0100828 //Flush to stream.
829 fwrite(&reg_array, sizeof(reg_array), 1, out);
830 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100831}
832
833//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 +0100834void ir_arm_aarch64_el1_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100835{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100836 //Get uniform register array.
837 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array;
838 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
839 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) /
840 sizeof(UINT64),
841 ARM_AARCH64_EL1_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100842
Lawrence Tange407b4c2022-07-21 13:54:01 +0100843 //Flush to stream.
844 fwrite(&reg_array, sizeof(reg_array), 1, out);
845 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100846}
847
848//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 +0100849void ir_arm_aarch64_el2_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100850{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100851 //Get uniform register array.
852 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array;
853 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
854 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) /
855 sizeof(UINT64),
856 ARM_AARCH64_EL2_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100857
Lawrence Tange407b4c2022-07-21 13:54:01 +0100858 //Flush to stream.
859 fwrite(&reg_array, sizeof(reg_array), 1, out);
860 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100861}
862
863//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 +0100864void ir_arm_aarch64_el3_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100865{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100866 //Get uniform register array.
867 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array;
868 ir_to_uniform_struct64(registers, (UINT64 *)&reg_array,
869 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) /
870 sizeof(UINT64),
871 ARM_AARCH64_EL3_REGISTER_NAMES);
Lawrence Tang71570a22022-07-14 11:45:28 +0100872
Lawrence Tange407b4c2022-07-21 13:54:01 +0100873 //Flush to stream.
874 fwrite(&reg_array, sizeof(reg_array), 1, out);
875 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100876}
877
878//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 +0100879void ir_arm_misc_registers_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100880{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100881 EFI_ARM_MISC_CONTEXT_REGISTER reg_array;
Lawrence Tang71570a22022-07-14 11:45:28 +0100882
Lawrence Tange407b4c2022-07-21 13:54:01 +0100883 //MRS encoding information.
884 json_object *mrs_encoding =
885 json_object_object_get(registers, "mrsEncoding");
886 reg_array.MrsOp2 = json_object_get_uint64(
887 json_object_object_get(mrs_encoding, "op2"));
888 reg_array.MrsCrm = json_object_get_uint64(
889 json_object_object_get(mrs_encoding, "crm"));
890 reg_array.MrsCrn = json_object_get_uint64(
891 json_object_object_get(mrs_encoding, "crn"));
892 reg_array.MrsOp1 = json_object_get_uint64(
893 json_object_object_get(mrs_encoding, "op1"));
894 reg_array.MrsO0 = json_object_get_uint64(
895 json_object_object_get(mrs_encoding, "o0"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100896
Lawrence Tange407b4c2022-07-21 13:54:01 +0100897 //Actual register value.
898 reg_array.Value = json_object_get_uint64(
899 json_object_object_get(registers, "value"));
Lawrence Tang71570a22022-07-14 11:45:28 +0100900
Lawrence Tange407b4c2022-07-21 13:54:01 +0100901 //Flush to stream.
902 fwrite(&reg_array, sizeof(reg_array), 1, out);
903 fflush(out);
Lawrence Tang71570a22022-07-14 11:45:28 +0100904}
905
906//Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream.
John Chungf8fc7052024-05-03 20:05:29 +0800907void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out)
Lawrence Tang71570a22022-07-14 11:45:28 +0100908{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100909 //Get base64 represented data.
910 json_object *encoded = json_object_object_get(registers, "data");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700911
912 int32_t decoded_len = 0;
913
914 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
915 json_object_get_string_len(encoded),
916 &decoded_len);
917
918 if (decoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800919 printf("Failed to allocate decode output buffer. \n");
920 } else {
John Chungf8fc7052024-05-03 20:05:29 +0800921 //Flush out to stream.
922 fwrite(&decoded, decoded_len, 1, out);
923 fflush(out);
924 free(decoded);
925 }
926}