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, 12, 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 long starting_stream_pos = ftell(out); 364 365 //Validation bits. 366 section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"), 367 4, ARM_ERROR_VALID_BITFIELD_NAMES); 368 369 //Count of error/context info structures. 370 section_cper->ErrInfoNum = json_object_get_int(json_object_object_get(section, "errorInfoNum")); 371 section_cper->ContextInfoNum = json_object_get_int(json_object_object_get(section, "contextInfoNum")); 372 373 //Miscellaneous raw value fields. 374 section_cper->SectionLength = json_object_get_uint64(json_object_object_get(section, "sectionLength")); 375 section_cper->ErrorAffinityLevel = readable_pair_to_integer(json_object_object_get(section, "errorAffinity")); 376 section_cper->MPIDR_EL1 = json_object_get_uint64(json_object_object_get(section, "mpidrEl1")); 377 section_cper->MIDR_EL1 = json_object_get_uint64(json_object_object_get(section, "midrEl1")); 378 section_cper->RunningState = json_object_get_boolean(json_object_object_get(section, "running")); 379 380 //Optional PSCI state. 381 json_object* psci_state = json_object_object_get(section, "psciState"); 382 if (psci_state != NULL) 383 section_cper->PsciState = json_object_get_uint64(psci_state); 384 385 //Flush header to stream. 386 fwrite(section_cper, sizeof(EFI_ARM_ERROR_RECORD), 1, out); 387 fflush(out); 388 389 //Error info structure array. 390 json_object* error_info = json_object_object_get(section, "errorInfo"); 391 for (int i=0; i<section_cper->ErrInfoNum; i++) 392 ir_arm_error_info_to_cper(json_object_array_get_idx(error_info, i), out); 393 394 //Context info structure array. 395 json_object* context_info = json_object_object_get(section, "contextInfo"); 396 for (int i=0; i<section_cper->ContextInfoNum; i++) 397 ir_arm_context_info_to_cper(json_object_array_get_idx(context_info, i), out); 398 399 //Vendor specific error info. 400 json_object* vendor_specific_info = json_object_object_get(section, "vendorSpecificInfo"); 401 if (vendor_specific_info != NULL) 402 { 403 json_object* vendor_info_string = json_object_object_get(vendor_specific_info, "data"); 404 int vendor_specific_len = json_object_get_string_len(vendor_info_string); 405 UINT8* decoded = b64_decode(json_object_get_string(vendor_info_string), vendor_specific_len); 406 407 //Write out to file. 408 long cur_stream_pos = ftell(out); 409 fwrite(decoded, starting_stream_pos + section_cper->SectionLength - cur_stream_pos, 1, out); 410 fflush(out); 411 free(decoded); 412 } 413 414 //Free remaining resources. 415 free(section_cper); 416 } 417 418 //Converts a single ARM error information structure into CPER binary, outputting to the given stream. 419 void ir_arm_error_info_to_cper(json_object* error_info, FILE* out) 420 { 421 EFI_ARM_ERROR_INFORMATION_ENTRY error_info_cper; 422 423 //Version, length. 424 error_info_cper.Version = json_object_get_int(json_object_object_get(error_info, "version")); 425 error_info_cper.Length = json_object_get_int(json_object_object_get(error_info, "length")); 426 427 //Validation bits. 428 error_info_cper.ValidationBits = ir_to_bitfield(json_object_object_get(error_info, "validationBits"), 429 5, ARM_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES); 430 431 //Type, multiple error. 432 error_info_cper.Type = (UINT8)readable_pair_to_integer(json_object_object_get(error_info, "type")); 433 error_info_cper.MultipleError = (UINT16)readable_pair_to_integer(json_object_object_get(error_info, "multipleError")); 434 435 //Flags object. 436 error_info_cper.Flags = (UINT8)ir_to_bitfield(json_object_object_get(error_info, "flags"), 437 4, ARM_ERROR_INFO_ENTRY_FLAGS_NAMES); 438 439 //Error information. 440 json_object* error_info_information = json_object_object_get(error_info, "errorInformation"); 441 switch (error_info_cper.Type) 442 { 443 case ARM_ERROR_INFORMATION_TYPE_CACHE: 444 case ARM_ERROR_INFORMATION_TYPE_TLB: 445 ir_arm_error_cache_tlb_info_to_cper(error_info_information, &error_info_cper.ErrorInformation.CacheError); 446 break; 447 448 case ARM_ERROR_INFORMATION_TYPE_BUS: 449 ir_arm_error_bus_info_to_cper(error_info_information, &error_info_cper.ErrorInformation.BusError); 450 break; 451 452 default: 453 //Unknown error information type. 454 *((UINT64*)&error_info_cper.ErrorInformation) = 455 json_object_get_uint64(json_object_object_get(error_info_information, "data")); 456 break; 457 } 458 459 //Virtual/physical fault address. 460 error_info_cper.VirtualFaultAddress = json_object_get_uint64(json_object_object_get(error_info, "virtualFaultAddress")); 461 error_info_cper.PhysicalFaultAddress = json_object_get_uint64(json_object_object_get(error_info, "physicalFaultAddress")); 462 463 //Write out to stream. 464 fwrite(&error_info_cper, sizeof(EFI_ARM_ERROR_INFORMATION_ENTRY), 1, out); 465 fflush(out); 466 } 467 468 //Converts a single ARM cache/TLB error information structure into a CPER structure. 469 void ir_arm_error_cache_tlb_info_to_cper(json_object* error_information, EFI_ARM_CACHE_ERROR_STRUCTURE* error_info_cper) 470 { 471 //Validation bits. 472 error_info_cper->ValidationBits = ir_to_bitfield(json_object_object_get(error_information, "validationBits"), 473 7, ARM_CACHE_TLB_ERROR_VALID_BITFIELD_NAMES); 474 475 //Miscellaneous value fields. 476 error_info_cper->TransactionType = readable_pair_to_integer(json_object_object_get(error_information, "transactionType")); 477 error_info_cper->Operation = readable_pair_to_integer(json_object_object_get(error_information, "operation")); 478 error_info_cper->Level = json_object_get_uint64(json_object_object_get(error_information, "level")); 479 error_info_cper->ProcessorContextCorrupt = 480 json_object_get_boolean(json_object_object_get(error_information, "processorContextCorrupt")); 481 error_info_cper->Corrected = json_object_get_boolean(json_object_object_get(error_information, "corrected")); 482 error_info_cper->PrecisePC = json_object_get_boolean(json_object_object_get(error_information, "precisePC")); 483 error_info_cper->RestartablePC = json_object_get_boolean(json_object_object_get(error_information, "restartablePC")); 484 error_info_cper->Reserved = 0; 485 } 486 487 //Converts a single ARM bus error information structure into a CPER structure. 488 void ir_arm_error_bus_info_to_cper(json_object* error_information, EFI_ARM_BUS_ERROR_STRUCTURE* error_info_cper) 489 { 490 //Validation bits. 491 error_info_cper->ValidationBits = ir_to_bitfield(json_object_object_get(error_information, "validationBits"), 492 7, ARM_BUS_ERROR_VALID_BITFIELD_NAMES); 493 494 //Miscellaneous value fields. 495 error_info_cper->TransactionType = readable_pair_to_integer(json_object_object_get(error_information, "transactionType")); 496 error_info_cper->Operation = readable_pair_to_integer(json_object_object_get(error_information, "operation")); 497 error_info_cper->Level = json_object_get_uint64(json_object_object_get(error_information, "level")); 498 error_info_cper->ProcessorContextCorrupt = 499 json_object_get_boolean(json_object_object_get(error_information, "processorContextCorrupt")); 500 error_info_cper->Corrected = json_object_get_boolean(json_object_object_get(error_information, "corrected")); 501 error_info_cper->PrecisePC = json_object_get_boolean(json_object_object_get(error_information, "precisePC")); 502 error_info_cper->RestartablePC = json_object_get_boolean(json_object_object_get(error_information, "restartablePC")); 503 error_info_cper->ParticipationType = 504 readable_pair_to_integer(json_object_object_get(error_information, "participationType")); 505 error_info_cper->AddressSpace = readable_pair_to_integer(json_object_object_get(error_information, "addressSpace")); 506 error_info_cper->AccessMode = readable_pair_to_integer(json_object_object_get(error_information, "accessMode")); 507 error_info_cper->MemoryAddressAttributes = json_object_get_uint64(json_object_object_get(error_information, "memoryAttributes")); 508 error_info_cper->Reserved = 0; 509 } 510 511 //Converts a single ARM context information structure into CPER binary, outputting to the given stream. 512 void ir_arm_context_info_to_cper(json_object* context_info, FILE* out) 513 { 514 EFI_ARM_CONTEXT_INFORMATION_HEADER info_header; 515 516 //Version, array size, context type. 517 info_header.Version = json_object_get_int(json_object_object_get(context_info, "version")); 518 info_header.RegisterArraySize = json_object_get_int(json_object_object_get(context_info, "registerArraySize")); 519 info_header.RegisterContextType = readable_pair_to_integer(json_object_object_get(context_info, "registerContextType")); 520 521 //Flush to stream, write the register array itself. 522 fwrite(&info_header, sizeof(EFI_ARM_CONTEXT_INFORMATION_HEADER), 1, out); 523 fflush(out); 524 525 json_object* register_array = json_object_object_get(context_info, "registerArray"); 526 switch (info_header.RegisterContextType) 527 { 528 case EFI_ARM_CONTEXT_TYPE_AARCH32_GPR: 529 ir_arm_aarch32_gpr_to_cper(register_array, out); 530 break; 531 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL1: 532 ir_arm_aarch32_el1_to_cper(register_array, out); 533 break; 534 case EFI_ARM_CONTEXT_TYPE_AARCH32_EL2: 535 ir_arm_aarch32_el2_to_cper(register_array, out); 536 break; 537 case EFI_ARM_CONTEXT_TYPE_AARCH32_SECURE: 538 ir_arm_aarch32_secure_to_cper(register_array, out); 539 break; 540 case EFI_ARM_CONTEXT_TYPE_AARCH64_GPR: 541 ir_arm_aarch64_gpr_to_cper(register_array, out); 542 break; 543 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL1: 544 ir_arm_aarch64_el1_to_cper(register_array, out); 545 break; 546 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL2: 547 ir_arm_aarch64_el2_to_cper(register_array, out); 548 break; 549 case EFI_ARM_CONTEXT_TYPE_AARCH64_EL3: 550 ir_arm_aarch64_el3_to_cper(register_array, out); 551 break; 552 case EFI_ARM_CONTEXT_TYPE_MISC: 553 ir_arm_misc_registers_to_cper(register_array, out); 554 break; 555 default: 556 //Unknown register structure. 557 ir_arm_unknown_register_to_cper(register_array, &info_header, out); 558 break; 559 } 560 } 561 562 //Converts a single AARCH32 GPR CPER-JSON object to CPER binary, outputting to the given stream. 563 void ir_arm_aarch32_gpr_to_cper(json_object* registers, FILE* out) 564 { 565 //Get uniform register array. 566 EFI_ARM_V8_AARCH32_GPR reg_array; 567 ir_to_uniform_struct(registers, (UINT32*)®_array, 568 sizeof(EFI_ARM_V8_AARCH32_GPR) / sizeof(UINT32), ARM_AARCH32_GPR_NAMES); 569 570 //Flush to stream. 571 fwrite(®_array, sizeof(reg_array), 1, out); 572 fflush(out); 573 } 574 575 //Converts a single AARCH32 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 576 void ir_arm_aarch32_el1_to_cper(json_object* registers, FILE* out) 577 { 578 //Get uniform register array. 579 EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS reg_array; 580 ir_to_uniform_struct(registers, (UINT32*)®_array, 581 sizeof(EFI_ARM_AARCH32_EL1_CONTEXT_REGISTERS) / sizeof(UINT32), ARM_AARCH32_EL1_REGISTER_NAMES); 582 583 //Flush to stream. 584 fwrite(®_array, sizeof(reg_array), 1, out); 585 fflush(out); 586 } 587 588 //Converts a single AARCH32 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 589 void ir_arm_aarch32_el2_to_cper(json_object* registers, FILE* out) 590 { 591 //Get uniform register array. 592 EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS reg_array; 593 ir_to_uniform_struct(registers, (UINT32*)®_array, 594 sizeof(EFI_ARM_AARCH32_EL2_CONTEXT_REGISTERS) / sizeof(UINT32), ARM_AARCH32_EL2_REGISTER_NAMES); 595 596 //Flush to stream. 597 fwrite(®_array, sizeof(reg_array), 1, out); 598 fflush(out); 599 } 600 601 //Converts a single AARCH32 secure register set CPER-JSON object to CPER binary, outputting to the given stream. 602 void ir_arm_aarch32_secure_to_cper(json_object* registers, FILE* out) 603 { 604 //Get uniform register array. 605 EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS reg_array; 606 ir_to_uniform_struct(registers, (UINT32*)®_array, 607 sizeof(EFI_ARM_AARCH32_SECURE_CONTEXT_REGISTERS) / sizeof(UINT32), ARM_AARCH32_SECURE_REGISTER_NAMES); 608 609 //Flush to stream. 610 fwrite(®_array, sizeof(reg_array), 1, out); 611 fflush(out); 612 } 613 614 //Converts a single AARCH64 GPR CPER-JSON object to CPER binary, outputting to the given stream. 615 void ir_arm_aarch64_gpr_to_cper(json_object* registers, FILE* out) 616 { 617 //Get uniform register array. 618 EFI_ARM_V8_AARCH64_GPR reg_array; 619 ir_to_uniform_struct64(registers, (UINT64*)®_array, 620 sizeof(EFI_ARM_V8_AARCH64_GPR) / sizeof(UINT64), ARM_AARCH64_GPR_NAMES); 621 622 //Flush to stream. 623 fwrite(®_array, sizeof(reg_array), 1, out); 624 fflush(out); 625 } 626 627 //Converts a single AARCH64 EL1 register set CPER-JSON object to CPER binary, outputting to the given stream. 628 void ir_arm_aarch64_el1_to_cper(json_object* registers, FILE* out) 629 { 630 //Get uniform register array. 631 EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS reg_array; 632 ir_to_uniform_struct64(registers, (UINT64*)®_array, 633 sizeof(EFI_ARM_AARCH64_EL1_CONTEXT_REGISTERS) / sizeof(UINT64), ARM_AARCH64_EL1_REGISTER_NAMES); 634 635 //Flush to stream. 636 fwrite(®_array, sizeof(reg_array), 1, out); 637 fflush(out); 638 } 639 640 //Converts a single AARCH64 EL2 register set CPER-JSON object to CPER binary, outputting to the given stream. 641 void ir_arm_aarch64_el2_to_cper(json_object* registers, FILE* out) 642 { 643 //Get uniform register array. 644 EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS reg_array; 645 ir_to_uniform_struct64(registers, (UINT64*)®_array, 646 sizeof(EFI_ARM_AARCH64_EL2_CONTEXT_REGISTERS) / sizeof(UINT64), ARM_AARCH64_EL2_REGISTER_NAMES); 647 648 //Flush to stream. 649 fwrite(®_array, sizeof(reg_array), 1, out); 650 fflush(out); 651 } 652 653 //Converts a single AARCH64 EL3 register set CPER-JSON object to CPER binary, outputting to the given stream. 654 void ir_arm_aarch64_el3_to_cper(json_object* registers, FILE* out) 655 { 656 //Get uniform register array. 657 EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS reg_array; 658 ir_to_uniform_struct64(registers, (UINT64*)®_array, 659 sizeof(EFI_ARM_AARCH64_EL3_CONTEXT_REGISTERS) / sizeof(UINT64), ARM_AARCH64_EL3_REGISTER_NAMES); 660 661 //Flush to stream. 662 fwrite(®_array, sizeof(reg_array), 1, out); 663 fflush(out); 664 } 665 666 //Converts a single ARM miscellaneous register set CPER-JSON object to CPER binary, outputting to the given stream. 667 void ir_arm_misc_registers_to_cper(json_object* registers, FILE* out) 668 { 669 EFI_ARM_MISC_CONTEXT_REGISTER reg_array; 670 671 //MRS encoding information. 672 json_object* mrs_encoding = json_object_object_get(registers, "mrsEncoding"); 673 reg_array.MrsOp2 = json_object_get_uint64(json_object_object_get(mrs_encoding, "op2")); 674 reg_array.MrsCrm = json_object_get_uint64(json_object_object_get(mrs_encoding, "crm")); 675 reg_array.MrsCrn = json_object_get_uint64(json_object_object_get(mrs_encoding, "crn")); 676 reg_array.MrsOp1 = json_object_get_uint64(json_object_object_get(mrs_encoding, "op1")); 677 reg_array.MrsO0 = json_object_get_uint64(json_object_object_get(mrs_encoding, "o0")); 678 679 //Actual register value. 680 reg_array.Value = json_object_get_uint64(json_object_object_get(registers, "value")); 681 682 //Flush to stream. 683 fwrite(®_array, sizeof(reg_array), 1, out); 684 fflush(out); 685 } 686 687 //Converts a single ARM unknown register CPER-JSON object to CPER binary, outputting to the given stream. 688 void ir_arm_unknown_register_to_cper(json_object* registers, EFI_ARM_CONTEXT_INFORMATION_HEADER* header, FILE* out) 689 { 690 //Get base64 represented data. 691 json_object* encoded = json_object_object_get(registers, "data"); 692 UINT8* decoded = b64_decode(json_object_get_string(encoded), json_object_get_string_len(encoded)); 693 694 //Flush out to stream. 695 fwrite(&decoded, header->RegisterArraySize, 1, out); 696 fflush(out); 697 free(decoded); 698 }