1 /** 2 * Describes functions for converting ARM CPER sections from binary and JSON format 3 * into an intermediate format. 4 * 5 * Author: Lawrence.Tang@arm.com 6 **/ 7 8 #include <stdio.h> 9 #include "json.h" 10 #include "b64.h" 11 #include "../edk/Cper.h" 12 #include "../cper-utils.h" 13 #include "cper-section-arm.h" 14 15 //Private pre-definitions. 16 json_object* cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY* error_info); 17 json_object* cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER* header, void** cur_pos); 18 json_object* cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE* cache_tlb_error, EFI_ARM_ERROR_INFORMATION_ENTRY* error_info); 19 json_object* cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE* bus_error); 20 json_object* cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER* misc_register); 21 void ir_arm_error_info_to_cper(json_object* error_info, FILE* out); 22 void ir_arm_context_info_to_cper(json_object* context_info, FILE* out); 23 void ir_arm_error_cache_tlb_info_to_cper(json_object* error_information, EFI_ARM_CACHE_ERROR_STRUCTURE* error_info_cper); 24 void ir_arm_error_bus_info_to_cper(json_object* error_information, EFI_ARM_BUS_ERROR_STRUCTURE* error_info_cper); 25 void ir_arm_aarch32_gpr_to_cper(json_object* registers, FILE* out); 26 void ir_arm_aarch32_el1_to_cper(json_object* registers, FILE* out); 27 void ir_arm_aarch32_el2_to_cper(json_object* registers, FILE* out); 28 void ir_arm_aarch32_secure_to_cper(json_object* registers, FILE* out); 29 void ir_arm_aarch64_gpr_to_cper(json_object* registers, FILE* out); 30 void ir_arm_aarch64_el1_to_cper(json_object* registers, FILE* out); 31 void ir_arm_aarch64_el2_to_cper(json_object* registers, FILE* out); 32 void ir_arm_aarch64_el3_to_cper(json_object* registers, FILE* out); 33 void ir_arm_misc_registers_to_cper(json_object* registers, FILE* out); 34 void ir_arm_unknown_register_to_cper(json_object* registers, EFI_ARM_CONTEXT_INFORMATION_HEADER* header, FILE* out); 35 36 //Converts the given processor-generic CPER section into JSON IR. 37 json_object* cper_section_arm_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor) 38 { 39 EFI_ARM_ERROR_RECORD* record = (EFI_ARM_ERROR_RECORD*)section; 40 json_object* section_ir = json_object_new_object(); 41 42 //Validation bits. 43 json_object* validation = bitfield_to_ir(record->ValidFields, 4, ARM_ERROR_VALID_BITFIELD_NAMES); 44 json_object_object_add(section_ir, "validationBits", validation); 45 46 //Number of error info and context info structures, and length. 47 json_object_object_add(section_ir, "errorInfoNum", json_object_new_int(record->ErrInfoNum)); 48 json_object_object_add(section_ir, "contextInfoNum", json_object_new_int(record->ContextInfoNum)); 49 json_object_object_add(section_ir, "sectionLength", json_object_new_uint64(record->SectionLength)); 50 51 //Error affinity. 52 json_object* error_affinity = json_object_new_object(); 53 json_object_object_add(error_affinity, "value", json_object_new_int(record->ErrorAffinityLevel)); 54 json_object_object_add(error_affinity, "type", 55 json_object_new_string(record->ErrorAffinityLevel < 4 ? "Vendor Defined" : "Reserved")); 56 json_object_object_add(section_ir, "errorAffinity", error_affinity); 57 58 //Processor ID (MPIDR_EL1) and chip ID (MIDR_EL1). 59 json_object_object_add(section_ir, "mpidrEl1", json_object_new_uint64(record->MPIDR_EL1)); 60 json_object_object_add(section_ir, "midrEl1", json_object_new_uint64(record->MIDR_EL1)); 61 62 //Whether the processor is running, and the state of it if so. 63 json_object_object_add(section_ir, "running", json_object_new_boolean(record->RunningState & 0b1)); 64 if (record->RunningState >> 31) 65 { 66 //Bit 32 of running state is on, so PSCI state information is included. 67 //This can't be made human readable, as it is unknown whether this will be the pre-PSCI 1.0 format 68 //or the newer Extended StateID format. 69 json_object_object_add(section_ir, "psciState", json_object_new_uint64(record->PsciState)); 70 } 71 72 //Processor error structures. 73 json_object* error_info_array = json_object_new_array(); 74 EFI_ARM_ERROR_INFORMATION_ENTRY* cur_error = (EFI_ARM_ERROR_INFORMATION_ENTRY*)(record + 1); 75 for (int i=0; i<record->ErrInfoNum; i++) 76 { 77 json_object_array_add(error_info_array, cper_arm_error_info_to_ir(cur_error)); 78 cur_error++; 79 } 80 json_object_object_add(section_ir, "errorInfo", error_info_array); 81 82 //Processor context structures. 83 //The current position is moved within the processing, as it is a dynamic size structure. 84 void* cur_pos = (void*)cur_error; 85 json_object* context_info_array = json_object_new_array(); 86 for (int i=0; i<record->ContextInfoNum; i++) 87 { 88 EFI_ARM_CONTEXT_INFORMATION_HEADER* header = (EFI_ARM_CONTEXT_INFORMATION_HEADER*)cur_pos; 89 json_object* processor_context = cper_arm_processor_context_to_ir(header, &cur_pos); 90 json_object_array_add(context_info_array, processor_context); 91 } 92 json_object_object_add(section_ir, "contextInfo", context_info_array); 93 94 //Is there any vendor-specific information following? 95 if (cur_pos < section + record->SectionLength) 96 { 97 json_object* vendor_specific = json_object_new_object(); 98 char* encoded = b64_encode((unsigned char*)cur_pos, section + record->SectionLength - cur_pos); 99 json_object_object_add(vendor_specific, "data", json_object_new_string(encoded)); 100 free(encoded); 101 102 json_object_object_add(section_ir, "vendorSpecificInfo", vendor_specific); 103 } 104 105 return section_ir; 106 } 107 108 //Converts a single ARM Process Error Information structure into JSON IR. 109 json_object* cper_arm_error_info_to_ir(EFI_ARM_ERROR_INFORMATION_ENTRY* error_info) 110 { 111 json_object* error_info_ir = json_object_new_object(); 112 113 //Version, length. 114 json_object_object_add(error_info_ir, "version", json_object_new_int(error_info->Version)); 115 json_object_object_add(error_info_ir, "length", json_object_new_int(error_info->Length)); 116 117 //Validation bitfield. 118 json_object* validation = bitfield_to_ir(error_info->ValidationBits, 5, ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 119 json_object_object_add(error_info_ir, "validationBits", validation); 120 121 //The type of error information in this log. 122 json_object* error_type = integer_to_readable_pair(error_info->Type, 4, 123 ARM_ERROR_INFO_ENTRY_INFO_TYPES_KEYS, 124 ARM_ERROR_INFO_ENTRY_INFO_TYPES_VALUES, 125 "Unknown (Reserved)"); 126 json_object_object_add(error_info_ir, "errorType", error_type); 127 128 //Multiple error count. 129 json_object* multiple_error = json_object_new_object(); 130 json_object_object_add(multiple_error, "value", json_object_new_int(error_info->MultipleError)); 131 json_object_object_add(multiple_error, "type", 132 json_object_new_string(error_info->MultipleError < 1 ? "Single Error" : "Multiple Errors")); 133 json_object_object_add(error_info_ir, "multipleError", multiple_error); 134 135 //Flags. 136 json_object* flags = bitfield_to_ir(error_info->Flags, 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 137 json_object_object_add(error_info_ir, "flags", flags); 138 139 //Error information, split by type. 140 json_object* error_subinfo = NULL; 141 switch (error_info->Type) 142 { 143 case ARM_ERROR_INFORMATION_TYPE_CACHE: //Cache 144 case ARM_ERROR_INFORMATION_TYPE_TLB: //TLB 145 error_subinfo = cper_arm_cache_tlb_error_to_ir((EFI_ARM_CACHE_ERROR_STRUCTURE*)&error_info->ErrorInformation, error_info); 146 break; 147 case ARM_ERROR_INFORMATION_TYPE_BUS: //Bus 148 error_subinfo = cper_arm_bus_error_to_ir((EFI_ARM_BUS_ERROR_STRUCTURE*)&error_info->ErrorInformation); 149 break; 150 151 default: 152 //Unknown/microarch, so can't be made readable. Simply dump as a uint64 data object. 153 error_subinfo = json_object_new_object(); 154 json_object_object_add(error_subinfo, "data", json_object_new_uint64(*((UINT64*)&error_info->ErrorInformation))); 155 break; 156 } 157 json_object_object_add(error_info_ir, "errorInformation", error_subinfo); 158 159 //Virtual fault address, physical fault address. 160 json_object_object_add(error_info_ir, "virtualFaultAddress", json_object_new_uint64(error_info->VirtualFaultAddress)); 161 json_object_object_add(error_info_ir, "physicalFaultAddress", json_object_new_uint64(error_info->PhysicalFaultAddress)); 162 163 return error_info_ir; 164 } 165 166 //Converts a single ARM cache/TLB error information structure into JSON IR format. 167 json_object* cper_arm_cache_tlb_error_to_ir(EFI_ARM_CACHE_ERROR_STRUCTURE* cache_tlb_error, EFI_ARM_ERROR_INFORMATION_ENTRY* error_info) 168 { 169 json_object* cache_tlb_error_ir = json_object_new_object(); 170 171 //Validation bitfield. 172 json_object* validation = bitfield_to_ir(cache_tlb_error->ValidationBits, 7, ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 173 json_object_object_add(cache_tlb_error_ir, "validationBits", validation); 174 175 //Transaction type. 176 json_object* transaction_type = integer_to_readable_pair(cache_tlb_error->TransactionType, 3, 177 ARM_ERROR_TRANSACTION_TYPES_KEYS, 178 ARM_ERROR_TRANSACTION_TYPES_VALUES, 179 "Unknown (Reserved)"); 180 json_object_object_add(cache_tlb_error_ir, "transactionType", transaction_type); 181 182 //Operation. 183 json_object* operation; 184 if (error_info->Type == 0) 185 { 186 //Cache operation. 187 operation = integer_to_readable_pair(cache_tlb_error->Operation, 11, 188 ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 189 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, 190 "Unknown (Reserved)"); 191 } 192 else 193 { 194 //TLB operation. 195 operation = integer_to_readable_pair(cache_tlb_error->Operation, 9, 196 ARM_TLB_OPERATION_TYPES_KEYS, 197 ARM_TLB_OPERATION_TYPES_VALUES, 198 "Unknown (Reserved)"); 199 } 200 json_object_object_add(cache_tlb_error_ir, "operation", operation); 201 202 //Miscellaneous remaining fields. 203 json_object_object_add(cache_tlb_error_ir, "level", json_object_new_int(cache_tlb_error->Level)); 204 json_object_object_add(cache_tlb_error_ir, "processorContextCorrupt", json_object_new_boolean(cache_tlb_error->ProcessorContextCorrupt)); 205 json_object_object_add(cache_tlb_error_ir, "corrected", json_object_new_boolean(cache_tlb_error->Corrected)); 206 json_object_object_add(cache_tlb_error_ir, "precisePC", json_object_new_boolean(cache_tlb_error->PrecisePC)); 207 json_object_object_add(cache_tlb_error_ir, "restartablePC", json_object_new_boolean(cache_tlb_error->RestartablePC)); 208 return cache_tlb_error_ir; 209 } 210 211 //Converts a single ARM bus error information structure into JSON IR format. 212 json_object* cper_arm_bus_error_to_ir(EFI_ARM_BUS_ERROR_STRUCTURE* bus_error) 213 { 214 json_object* bus_error_ir = json_object_new_object(); 215 216 //Validation bits. 217 json_object* validation = bitfield_to_ir(bus_error->ValidationBits, 7, ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 218 json_object_object_add(bus_error_ir, "validationBits", validation); 219 220 //Transaction type. 221 json_object* transaction_type = integer_to_readable_pair(bus_error->TransactionType, 3, 222 ARM_ERROR_TRANSACTION_TYPES_KEYS, 223 ARM_ERROR_TRANSACTION_TYPES_VALUES, 224 "Unknown (Reserved)"); 225 json_object_object_add(bus_error_ir, "transactionType", transaction_type); 226 227 //Operation. 228 json_object* operation = integer_to_readable_pair(bus_error->Operation, 7, 229 ARM_CACHE_BUS_OPERATION_TYPES_KEYS, 230 ARM_CACHE_BUS_OPERATION_TYPES_VALUES, 231 "Unknown (Reserved)"); 232 json_object_object_add(bus_error_ir, "operation", operation); 233 234 //Affinity level of bus error, + miscellaneous fields. 235 json_object_object_add(bus_error_ir, "level", json_object_new_int(bus_error->Level)); 236 json_object_object_add(bus_error_ir, "processorContextCorrupt", json_object_new_boolean(bus_error->ProcessorContextCorrupt)); 237 json_object_object_add(bus_error_ir, "corrected", json_object_new_boolean(bus_error->Corrected)); 238 json_object_object_add(bus_error_ir, "precisePC", json_object_new_boolean(bus_error->PrecisePC)); 239 json_object_object_add(bus_error_ir, "restartablePC", json_object_new_boolean(bus_error->RestartablePC)); 240 json_object_object_add(bus_error_ir, "timedOut", json_object_new_boolean(bus_error->TimeOut)); 241 242 //Participation type. 243 json_object* participation_type = integer_to_readable_pair(bus_error->ParticipationType, 4, 244 ARM_BUS_PARTICIPATION_TYPES_KEYS, 245 ARM_BUS_PARTICIPATION_TYPES_VALUES, 246 "Unknown"); 247 json_object_object_add(bus_error_ir, "participationType", participation_type); 248 249 //Address space. 250 json_object* address_space = integer_to_readable_pair(bus_error->AddressSpace, 3, 251 ARM_BUS_ADDRESS_SPACE_TYPES_KEYS, 252 ARM_BUS_ADDRESS_SPACE_TYPES_VALUES, 253 "Unknown"); 254 json_object_object_add(bus_error_ir, "addressSpace", address_space); 255 256 //Memory access attributes. 257 //todo: find the specification of these in the ARM ARM 258 json_object_object_add(bus_error_ir, "memoryAttributes", json_object_new_int(bus_error->MemoryAddressAttributes)); 259 260 //Access Mode 261 json_object* access_mode = json_object_new_object(); 262 json_object_object_add(access_mode, "value", json_object_new_int(bus_error->AccessMode)); 263 json_object_object_add(access_mode, "name", json_object_new_string(bus_error->AccessMode == 0 ? "Secure" : "Normal")); 264 json_object_object_add(bus_error_ir, "accessMode", access_mode); 265 266 return bus_error_ir; 267 } 268 269 //Converts a single ARM processor context block into JSON IR. 270 json_object* cper_arm_processor_context_to_ir(EFI_ARM_CONTEXT_INFORMATION_HEADER* header, void** cur_pos) 271 { 272 json_object* context_ir = json_object_new_object(); 273 274 //Version. 275 json_object_object_add(context_ir, "version", json_object_new_int(header->Version)); 276 277 //Add the context type. 278 json_object* context_type = integer_to_readable_pair(header->RegisterContextType, 9, 279 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS, 280 ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES, 281 "Unknown (Reserved)"); 282 json_object_object_add(context_ir, "registerContextType", context_type); 283 284 //Register array size (bytes). 285 json_object_object_add(context_ir, "registerArraySize", json_object_new_uint64(header->RegisterArraySize)); 286 287 //The register array itself. 288 *cur_pos = (void*)(header + 1); 289 json_object* register_array = NULL; 290 switch (header->RegisterContextType) 291 { 292 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 293 register_array = uniform_struct_to_ir((UINT32*)cur_pos, 294 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), ARM_AARCH32_GPR_NAMES); 295 break; 296 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 297 register_array = uniform_struct_to_ir((UINT32*)cur_pos, 298 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / sizeof(UINT32), ARM_AARCH32_EL1_REGISTER_NAMES); 299 break; 300 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 301 register_array = uniform_struct_to_ir((UINT32*)cur_pos, 302 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / sizeof(UINT32), ARM_AARCH32_EL2_REGISTER_NAMES); 303 break; 304 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 305 register_array = uniform_struct_to_ir((UINT32*)cur_pos, 306 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / sizeof(UINT32), ARM_AARCH32_SECURE_REGISTER_NAMES); 307 break; 308 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 309 register_array = uniform_struct64_to_ir((UINT64*)cur_pos, 310 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), ARM_AARCH64_GPR_NAMES); 311 break; 312 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 313 register_array = uniform_struct64_to_ir((UINT64*)cur_pos, 314 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / sizeof(UINT64), ARM_AARCH64_EL1_REGISTER_NAMES); 315 break; 316 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 317 register_array = uniform_struct64_to_ir((UINT64*)cur_pos, 318 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / sizeof(UINT64), ARM_AARCH64_EL2_REGISTER_NAMES); 319 break; 320 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 321 register_array = uniform_struct64_to_ir((UINT64*)cur_pos, 322 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / sizeof(UINT64), ARM_AARCH64_EL3_REGISTER_NAMES); 323 break; 324 case EFI_ARM_CONTEXT_TYPE_MISC: 325 register_array = cper_arm_misc_register_array_to_ir((EFI_ARM_MISC_CONTEXT_REGISTER*)cur_pos); 326 break; 327 default: 328 //Unknown register array type, add as base64 data instead. 329 register_array = json_object_new_object(); 330 char* encoded = b64_encode((unsigned char*)cur_pos, header->RegisterArraySize); 331 json_object_object_add(register_array, "data", json_object_new_string(encoded)); 332 free(encoded); 333 break; 334 } 335 json_object_object_add(context_ir, "registerArray", register_array); 336 337 //Set the current position to after the processor context structure. 338 *cur_pos = (UINT8*)(*cur_pos) + header->RegisterArraySize; 339 340 return context_ir; 341 } 342 343 //Converts a single CPER ARM miscellaneous register array to JSON IR format. 344 json_object* cper_arm_misc_register_array_to_ir(EFI_ARM_MISC_CONTEXT_REGISTER* misc_register) 345 { 346 json_object* register_array = json_object_new_object(); 347 json_object* mrs_encoding = json_object_new_object(); 348 json_object_object_add(mrs_encoding, "op2", json_object_new_uint64(misc_register->MrsOp2)); 349 json_object_object_add(mrs_encoding, "crm", json_object_new_uint64(misc_register->MrsCrm)); 350 json_object_object_add(mrs_encoding, "crn", json_object_new_uint64(misc_register->MrsCrn)); 351 json_object_object_add(mrs_encoding, "op1", json_object_new_uint64(misc_register->MrsOp1)); 352 json_object_object_add(mrs_encoding, "o0", json_object_new_uint64(misc_register->MrsO0)); 353 json_object_object_add(register_array, "mrsEncoding", mrs_encoding); 354 json_object_object_add(register_array, "value", json_object_new_uint64(misc_register->Value)); 355 356 return register_array; 357 } 358 359 //Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream. 360 void ir_section_arm_to_cper(json_object* section, FILE* out) 361 { 362 EFI_ARM_ERROR_RECORD* section_cper = (EFI_ARM_ERROR_RECORD*)calloc(1, sizeof(EFI_ARM_ERROR_RECORD)); 363 364 //Validation bits. 365 section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"), 366 4, ARM_ERROR_VALID_BITFIELD_NAMES); 367 368 //Count of error/context info structures. 369 section_cper->ErrInfoNum = json_object_get_int(json_object_object_get(section, "errorInfoNum")); 370 section_cper->ContextInfoNum = json_object_get_int(json_object_object_get(section, "contextInfoNum")); 371 372 //Miscellaneous raw value fields. 373 section_cper->SectionLength = json_object_get_uint64(json_object_object_get(section, "sectionLength")); 374 section_cper->ErrorAffinityLevel = readable_pair_to_integer(json_object_object_get(section, "errorAffinity")); 375 section_cper->MPIDR_EL1 = json_object_get_uint64(json_object_object_get(section, "mpidrEl1")); 376 section_cper->MIDR_EL1 = json_object_get_uint64(json_object_object_get(section, "midrEl1")); 377 section_cper->RunningState = json_object_get_boolean(json_object_object_get(section, "running")); 378 379 //Optional PSCI state. 380 json_object* psci_state = json_object_object_get(section, "psciState"); 381 if (psci_state != NULL) 382 section_cper->PsciState = json_object_get_uint64(psci_state); 383 384 //Flush header to stream. 385 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out); 386 fflush(out); 387 388 //Error info structure array. 389 json_object* error_info = json_object_object_get(section, "errorInfo"); 390 for (int i=0; i<section_cper->ErrInfoNum; i++) 391 ir_arm_error_info_to_cper(json_object_array_get_idx(error_info, i), out); 392 393 //Context info structure array. 394 json_object* context_info = json_object_object_get(section, "contextInfo"); 395 for (int i=0; i<section_cper->ContextInfoNum; i++) 396 ir_arm_context_info_to_cper(json_object_array_get_idx(context_info, i), out); 397 398 //Vendor specific error info. 399 json_object* vendor_specific_info = json_object_object_get(section, "vendorSpecificInfo"); 400 if (vendor_specific_info != NULL) 401 { 402 int vendor_specific_len = json_object_get_string_len(vendor_specific_info); 403 UINT8* decoded = b64_decode(json_object_get_string(vendor_specific_info), vendor_specific_len); 404 fwrite(decoded, vendor_specific_len / 4 * 3, 1, out); //b64 length to byte length 405 fflush(out); 406 free(decoded); 407 } 408 409 //Free remaining resources. 410 free(section_cper); 411 } 412 413 //Converts a single ARM error information structure into CPER binary, outputting to the given stream. 414 void ir_arm_error_info_to_cper(json_object* error_info, FILE* out) 415 { 416 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper; 417 418 //Version, length. 419 error_info_cper.Version = json_object_get_int(json_object_object_get(error_info, "version")); 420 error_info_cper.Length = json_object_get_int(json_object_object_get(error_info, "length")); 421 422 //Validation bits. 423 error_info_cper.ValidationBits = ir_to_bitfield(json_object_object_get(error_info, "validationBits"), 424 5, ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 425 426 //Type, multiple error. 427 error_info_cper.Type = (UINT8)readable_pair_to_integer(json_object_object_get(error_info, "type")); 428 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer(json_object_object_get(error_info, "multipleError")); 429 430 //Flags object. 431 error_info_cper.Flags = (UINT8)ir_to_bitfield(json_object_object_get(error_info, "flags"), 432 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 433 434 //Error information. 435 json_object* error_info_information = json_object_object_get(error_info, "errorInformation"); 436 switch (error_info_cper.Type) 437 { 438 case ARM_ERROR_INFORMATION_TYPE_CACHE: 439 case ARM_ERROR_INFORMATION_TYPE_TLB: 440 ir_arm_error_cache_tlb_info_to_cper(error_info_information, &error_info_cper.ErrorInformation.CacheError); 441 break; 442 443 case ARM_ERROR_INFORMATION_TYPE_BUS: 444 ir_arm_error_bus_info_to_cper(error_info_information, &error_info_cper.ErrorInformation.BusError); 445 break; 446 447 default: 448 //Unknown error information type. 449 *((UINT64*)&error_info_cper.ErrorInformation) = 450 json_object_get_uint64(json_object_object_get(error_info_information, "data")); 451 break; 452 } 453 454 //Virtual/physical fault address. 455 error_info_cper.VirtualFaultAddress = json_object_get_uint64(json_object_object_get(error_info, "virtualFaultAddress")); 456 error_info_cper.PhysicalFaultAddress = json_object_get_uint64(json_object_object_get(error_info, "physicalFaultAddress")); 457 458 //Write out to stream. 459 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1, out); 460 fflush(out); 461 } 462 463 //Converts a single ARM cache/TLB error information structure into a CPER structure. 464 void ir_arm_error_cache_tlb_info_to_cper(json_object* error_information, EFI_ARM_CACHE_ERROR_STRUCTURE* error_info_cper) 465 { 466 //Validation bits. 467 error_info_cper->ValidationBits = ir_to_bitfield(json_object_object_get(error_information, "validationBits"), 468 7, ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 469 470 //Miscellaneous value fields. 471 error_info_cper->TransactionType = readable_pair_to_integer(json_object_object_get(error_information, "transactionType")); 472 error_info_cper->Operation = readable_pair_to_integer(json_object_object_get(error_information, "operation")); 473 error_info_cper->Level = json_object_get_uint64(json_object_object_get(error_information, "level")); 474 error_info_cper->ProcessorContextCorrupt = 475 json_object_get_boolean(json_object_object_get(error_information, "processorContextCorrupt")); 476 error_info_cper->Corrected = json_object_get_boolean(json_object_object_get(error_information, "corrected")); 477 error_info_cper->PrecisePC = json_object_get_boolean(json_object_object_get(error_information, "precisePC")); 478 error_info_cper->RestartablePC = json_object_get_boolean(json_object_object_get(error_information, "restartablePC")); 479 error_info_cper->Reserved = 0; 480 } 481 482 //Converts a single ARM bus error information structure into a CPER structure. 483 void ir_arm_error_bus_info_to_cper(json_object* error_information, EFI_ARM_BUS_ERROR_STRUCTURE* error_info_cper) 484 { 485 //Validation bits. 486 error_info_cper->ValidationBits = ir_to_bitfield(json_object_object_get(error_information, "validationBits"), 487 7, ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 488 489 //Miscellaneous value fields. 490 error_info_cper->TransactionType = readable_pair_to_integer(json_object_object_get(error_information, "transactionType")); 491 error_info_cper->Operation = readable_pair_to_integer(json_object_object_get(error_information, "operation")); 492 error_info_cper->Level = json_object_get_uint64(json_object_object_get(error_information, "level")); 493 error_info_cper->ProcessorContextCorrupt = 494 json_object_get_boolean(json_object_object_get(error_information, "processorContextCorrupt")); 495 error_info_cper->Corrected = json_object_get_boolean(json_object_object_get(error_information, "corrected")); 496 error_info_cper->PrecisePC = json_object_get_boolean(json_object_object_get(error_information, "precisePC")); 497 error_info_cper->RestartablePC = json_object_get_boolean(json_object_object_get(error_information, "restartablePC")); 498 error_info_cper->ParticipationType = 499 readable_pair_to_integer(json_object_object_get(error_information, "participationType")); 500 error_info_cper->AddressSpace = readable_pair_to_integer(json_object_object_get(error_information, "addressSpace")); 501 error_info_cper->AccessMode = readable_pair_to_integer(json_object_object_get(error_information, "accessMode")); 502 error_info_cper->MemoryAddressAttributes = json_object_get_uint64(json_object_object_get(error_information, "memoryAttributes")); 503 error_info_cper->Reserved = 0; 504 } 505 506 //Converts a single ARM context information structure into CPER binary, outputting to the given stream. 507 void ir_arm_context_info_to_cper(json_object* context_info, FILE* out) 508 { 509 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header; 510 511 //Version, array size, context type. 512 info_header.Version = json_object_get_int(json_object_object_get(context_info, "version")); 513 info_header.RegisterArraySize = json_object_get_int(json_object_object_get(context_info, "registerArraySize")); 514 info_header.RegisterContextType = readable_pair_to_integer(json_object_object_get(context_info, "registerContextType")); 515 516 //Flush to stream, write the register array itself. 517 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1, out); 518 fflush(out); 519 520 json_object* register_array = json_object_object_get(context_info, "registerArray"); 521 switch (info_header.RegisterContextType) 522 { 523 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 524 ir_arm_aarch32_gpr_to_cper(register_array, out); 525 break; 526 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 527 ir_arm_aarch32_el1_to_cper(register_array, out); 528 break; 529 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 530 ir_arm_aarch32_el2_to_cper(register_array, out); 531 break; 532 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 533 ir_arm_aarch32_secure_to_cper(register_array, out); 534 break; 535 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 536 ir_arm_aarch64_gpr_to_cper(register_array, out); 537 break; 538 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 539 ir_arm_aarch64_el1_to_cper(register_array, out); 540 break; 541 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 542 ir_arm_aarch64_el2_to_cper(register_array, out); 543 break; 544 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 545 ir_arm_aarch64_el3_to_cper(register_array, out); 546 break; 547 case EFI_ARM_CONTEXT_TYPE_MISC: 548 ir_arm_misc_registers_to_cper(register_array, out); 549 break; 550 default: 551 //Unknown register structure. 552 ir_arm_unknown_register_to_cper(register_array, &info_header, out); 553 break; 554 } 555 } 556 557 //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream. 558 void ir_arm_aarch32_gpr_to_cper(json_object* registers, FILE* out) 559 { 560 //Get uniform register array. 561 EFI_ARM_V8_AARCH32_GPR reg_array; 562 ir_to_uniform_struct(registers, (UINT32*)®_array, 563 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), ARM_AARCH32_GPR_NAMES); 564 565 //Flush to stream. 566 fwrite(®_array, sizeof(reg_array), 1, out); 567 fflush(out); 568 } 569 570 //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 571 void ir_arm_aarch32_el1_to_cper(json_object* registers, FILE* out) 572 { 573 //Get uniform register array. 574 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array; 575 ir_to_uniform_struct(registers, (UINT32*)®_array, 576 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / sizeof(UINT32), ARM_AARCH32_EL1_REGISTER_NAMES); 577 578 //Flush to stream. 579 fwrite(®_array, sizeof(reg_array), 1, out); 580 fflush(out); 581 } 582 583 //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 584 void ir_arm_aarch32_el2_to_cper(json_object* registers, FILE* out) 585 { 586 //Get uniform register array. 587 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array; 588 ir_to_uniform_struct(registers, (UINT32*)®_array, 589 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / sizeof(UINT32), ARM_AARCH32_EL2_REGISTER_NAMES); 590 591 //Flush to stream. 592 fwrite(®_array, sizeof(reg_array), 1, out); 593 fflush(out); 594 } 595 596 //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream. 597 void ir_arm_aarch32_secure_to_cper(json_object* registers, FILE* out) 598 { 599 //Get uniform register array. 600 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array; 601 ir_to_uniform_struct(registers, (UINT32*)®_array, 602 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / sizeof(UINT32), ARM_AARCH32_SECURE_REGISTER_NAMES); 603 604 //Flush to stream. 605 fwrite(®_array, sizeof(reg_array), 1, out); 606 fflush(out); 607 } 608 609 //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream. 610 void ir_arm_aarch64_gpr_to_cper(json_object* registers, FILE* out) 611 { 612 //Get uniform register array. 613 EFI_ARM_V8_AARCH64_GPR reg_array; 614 ir_to_uniform_struct64(registers, (UINT64*)®_array, 615 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), ARM_AARCH64_GPR_NAMES); 616 617 //Flush to stream. 618 fwrite(®_array, sizeof(reg_array), 1, out); 619 fflush(out); 620 } 621 622 //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 623 void ir_arm_aarch64_el1_to_cper(json_object* registers, FILE* out) 624 { 625 //Get uniform register array. 626 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array; 627 ir_to_uniform_struct64(registers, (UINT64*)®_array, 628 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / sizeof(UINT64), ARM_AARCH64_EL1_REGISTER_NAMES); 629 630 //Flush to stream. 631 fwrite(®_array, sizeof(reg_array), 1, out); 632 fflush(out); 633 } 634 635 //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 636 void ir_arm_aarch64_el2_to_cper(json_object* registers, FILE* out) 637 { 638 //Get uniform register array. 639 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array; 640 ir_to_uniform_struct64(registers, (UINT64*)®_array, 641 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / sizeof(UINT64), ARM_AARCH64_EL2_REGISTER_NAMES); 642 643 //Flush to stream. 644 fwrite(®_array, sizeof(reg_array), 1, out); 645 fflush(out); 646 } 647 648 //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream. 649 void ir_arm_aarch64_el3_to_cper(json_object* registers, FILE* out) 650 { 651 //Get uniform register array. 652 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array; 653 ir_to_uniform_struct64(registers, (UINT64*)®_array, 654 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / sizeof(UINT64), ARM_AARCH64_EL3_REGISTER_NAMES); 655 656 //Flush to stream. 657 fwrite(®_array, sizeof(reg_array), 1, out); 658 fflush(out); 659 } 660 661 //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream. 662 void ir_arm_misc_registers_to_cper(json_object* registers, FILE* out) 663 { 664 EFI_ARM_MISC_CONTEXT_REGISTER reg_array; 665 666 //MRS encoding information. 667 json_object* mrs_encoding = json_object_object_get(registers, "mrsEncoding"); 668 reg_array.MrsOp2 = json_object_get_uint64(json_object_object_get(mrs_encoding, "op2")); 669 reg_array.MrsCrm = json_object_get_uint64(json_object_object_get(mrs_encoding, "crm")); 670 reg_array.MrsCrn = json_object_get_uint64(json_object_object_get(mrs_encoding, "crn")); 671 reg_array.MrsOp1 = json_object_get_uint64(json_object_object_get(mrs_encoding, "op1")); 672 reg_array.MrsO0 = json_object_get_uint64(json_object_object_get(mrs_encoding, "o0")); 673 674 //Actual register value. 675 reg_array.Value = json_object_get_uint64(json_object_object_get(registers, "value")); 676 677 //Flush to stream. 678 fwrite(®_array, sizeof(reg_array), 1, out); 679 fflush(out); 680 } 681 682 //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream. 683 void ir_arm_unknown_register_to_cper(json_object* registers, EFI_ARM_CONTEXT_INFORMATION_HEADER* header, FILE* out) 684 { 685 //Get base64 represented data. 686 json_object* encoded = json_object_object_get(registers, "data"); 687 UINT8* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded)); 688 689 //Flush out to stream. 690 fwrite(&decoded, header->RegisterArraySize, 1, out); 691 fflush(out); 692 free(decoded); 693 }