1 /** 2 * Describes functions for converting IA32/x64 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-ia32x64.h" 14 15 //Private pre-definitions. 16 json_object* cper_ia32x64_processor_error_info_to_ir(EFI_IA32_X64_PROCESS_ERROR_INFO* error_info); 17 json_object* cper_ia32x64_cache_tlb_check_to_ir(EFI_IA32_X64_CACHE_CHECK_INFO* cache_tlb_check); 18 json_object* cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO* bus_check); 19 json_object* cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO* ms_check); 20 json_object* cper_ia32x64_processor_context_info_to_ir(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO* context_info, void** cur_pos); 21 json_object* cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE* registers); 22 json_object* cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE* registers); 23 24 //Converts the IA32/x64 error section described in the given descriptor into intermediate format. 25 json_object* cper_section_ia32x64_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor) 26 { 27 EFI_IA32_X64_PROCESSOR_ERROR_RECORD* record = (EFI_IA32_X64_PROCESSOR_ERROR_RECORD*)section; 28 json_object* record_ir = json_object_new_object(); 29 30 //Flags. 31 json_object* flags = json_object_new_object(); 32 json_object_object_add(flags, "localAPICIDValid", json_object_new_boolean(record->ValidFields & 0b1)); 33 json_object_object_add(flags, "cpuIDInfoValid", json_object_new_boolean((record->ValidFields >> 1) & 0b1)); 34 int processor_error_info_num = (record->ValidFields >> 2) & 0b111111; 35 json_object_object_add(flags, "processorErrorInfoNum", json_object_new_int(processor_error_info_num)); 36 int processor_context_info_num = (record->ValidFields >> 8) & 0b111111; 37 json_object_object_add(flags, "processorContextInfoNum", json_object_new_int(processor_context_info_num)); 38 json_object_object_add(record_ir, "flags", flags); 39 40 //APIC ID. 41 json_object_object_add(record_ir, "localAPICID", json_object_new_uint64(record->ApicId)); 42 43 //CPU ID information (todo, see generic). 44 //... 45 46 //Processor error information, of the amount described above. 47 EFI_IA32_X64_PROCESS_ERROR_INFO* current_error_info = (EFI_IA32_X64_PROCESS_ERROR_INFO*)(record + 1); 48 json_object* error_info_array = json_object_new_array(); 49 for (int i=0; i<processor_error_info_num; i++) 50 { 51 json_object_array_add(error_info_array, cper_ia32x64_processor_error_info_to_ir(current_error_info)); 52 current_error_info++; 53 } 54 json_object_object_add(record_ir, "processorErrorInfo", error_info_array); 55 56 //Processor context information, of the amount described above. 57 EFI_IA32_X64_PROCESSOR_CONTEXT_INFO* current_context_info = (EFI_IA32_X64_PROCESSOR_CONTEXT_INFO*)(current_error_info + 1); 58 json_object* context_info_array = json_object_new_array(); 59 for (int i=0; i<processor_context_info_num; i++) 60 { 61 json_object_array_add(context_info_array, cper_ia32x64_processor_context_info_to_ir(current_context_info, (void**)¤t_context_info)); 62 //The context array is a non-fixed size, pointer is shifted within the above function. 63 } 64 json_object_object_add(record_ir, "processorContextInfo", context_info_array); 65 66 return record_ir; 67 } 68 69 //Converts a single IA32/x64 processor error info block into JSON IR format. 70 json_object* cper_ia32x64_processor_error_info_to_ir(EFI_IA32_X64_PROCESS_ERROR_INFO* error_info) 71 { 72 json_object* error_info_ir = json_object_new_object(); 73 74 //Error structure type (as GUID). 75 char error_type[GUID_STRING_LENGTH]; 76 guid_to_string(error_type, &error_info->ErrorType); 77 json_object_object_add(error_info_ir, "type", json_object_new_string(error_type)); 78 79 //Validation bits. 80 json_object* validation = bitfield_to_ir(error_info->ValidFields, 5, IA32X64_PROCESSOR_ERROR_VALID_BITFIELD_NAMES); 81 json_object_object_add(error_info_ir, "validationBits", validation); 82 83 //Add the check information on a per-structure basis. 84 //Cache and TLB check information are identical, so can be equated. 85 json_object* checkInformation = NULL; 86 if (guid_equal(&error_info->ErrorType, &gEfiIa32x64ErrorTypeCacheCheckGuid) 87 || guid_equal(&error_info->ErrorType, &gEfiIa32x64ErrorTypeTlbCheckGuid)) 88 { 89 checkInformation = cper_ia32x64_cache_tlb_check_to_ir((EFI_IA32_X64_CACHE_CHECK_INFO*)&error_info->CheckInfo); 90 } 91 else if (guid_equal(&error_info->ErrorType, &gEfiIa32x64ErrorTypeBusCheckGuid)) 92 checkInformation = cper_ia32x64_bus_check_to_ir((EFI_IA32_X64_BUS_CHECK_INFO*)&error_info->CheckInfo); 93 else if (guid_equal(&error_info->ErrorType, &gEfiIa32x64ErrorTypeMsCheckGuid)) 94 checkInformation = cper_ia32x64_ms_check_to_ir((EFI_IA32_X64_MS_CHECK_INFO*)&error_info->CheckInfo); 95 json_object_object_add(error_info_ir, "checkInfo", checkInformation); 96 97 //Target, requestor, and responder identifiers. 98 json_object_object_add(error_info_ir, "targetIdentifier", json_object_new_uint64(error_info->TargetId)); 99 json_object_object_add(error_info_ir, "requestorIdentifier", json_object_new_uint64(error_info->RequestorId)); 100 json_object_object_add(error_info_ir, "responderIdentifier", json_object_new_uint64(error_info->ResponderId)); 101 json_object_object_add(error_info_ir, "instructionPointer", json_object_new_uint64(error_info->InstructionIP)); 102 103 return error_info_ir; 104 } 105 106 //Converts a single IA32/x64 cache or TLB check check info block into JSON IR format. 107 json_object* cper_ia32x64_cache_tlb_check_to_ir(EFI_IA32_X64_CACHE_CHECK_INFO* cache_tlb_check) 108 { 109 json_object* cache_tlb_check_ir = json_object_new_object(); 110 111 //Validation bits. 112 json_object* validation = bitfield_to_ir(cache_tlb_check->ValidFields, 8, IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 113 json_object_object_add(cache_tlb_check_ir, "validationBits", validation); 114 115 //Transaction type. 116 json_object* transaction_type = integer_to_readable_pair(cache_tlb_check->TransactionType, 3, 117 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS, 118 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES, 119 "Unknown (Reserved)"); 120 json_object_object_add(cache_tlb_check_ir, "transactionType", transaction_type); 121 122 //Operation. 123 json_object* operation = integer_to_readable_pair(cache_tlb_check->Operation, 9, 124 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS, 125 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES, 126 "Unknown (Reserved)"); 127 json_object_object_add(cache_tlb_check_ir, "operation", operation); 128 129 //Affected cache/TLB level. 130 json_object_object_add(cache_tlb_check_ir, "level", json_object_new_uint64(cache_tlb_check->Level)); 131 132 //Miscellaneous boolean fields. 133 json_object_object_add(cache_tlb_check_ir, "processorContextCorrupt", json_object_new_boolean(cache_tlb_check->ContextCorrupt)); 134 json_object_object_add(cache_tlb_check_ir, "uncorrected", json_object_new_boolean(cache_tlb_check->ErrorUncorrected)); 135 json_object_object_add(cache_tlb_check_ir, "preciseIP", json_object_new_boolean(cache_tlb_check->PreciseIp)); 136 json_object_object_add(cache_tlb_check_ir, "restartableIP", json_object_new_boolean(cache_tlb_check->RestartableIp)); 137 json_object_object_add(cache_tlb_check_ir, "overflow", json_object_new_boolean(cache_tlb_check->Overflow)); 138 139 return cache_tlb_check_ir; 140 } 141 142 //Converts a single IA32/x64 bus check check info block into JSON IR format. 143 json_object* cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO* bus_check) 144 { 145 json_object* bus_check_ir = json_object_new_object(); 146 147 //Validation bits. 148 json_object* validation = bitfield_to_ir(bus_check->ValidFields, 11, IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 149 json_object_object_add(bus_check_ir, "validationBits", validation); 150 151 //Transaction type. 152 json_object* transaction_type = integer_to_readable_pair(bus_check->TransactionType, 3, 153 IA32X64_CHECK_INFO_TRANSACTION_TYPES_KEYS, 154 IA32X64_CHECK_INFO_TRANSACTION_TYPES_VALUES, 155 "Unknown (Reserved)"); 156 json_object_object_add(bus_check_ir, "transactionType", transaction_type); 157 158 //Operation. 159 json_object* operation = integer_to_readable_pair(bus_check->Operation, 9, 160 IA32X64_CHECK_INFO_OPERATION_TYPES_KEYS, 161 IA32X64_CHECK_INFO_OPERATION_TYPES_VALUES, 162 "Unknown (Reserved)"); 163 json_object_object_add(bus_check_ir, "operation", operation); 164 165 //Affected bus level. 166 json_object_object_add(bus_check_ir, "level", json_object_new_uint64(bus_check->Level)); 167 168 //Miscellaneous boolean fields. 169 json_object_object_add(bus_check_ir, "processorContextCorrupt", json_object_new_boolean(bus_check->ContextCorrupt)); 170 json_object_object_add(bus_check_ir, "uncorrected", json_object_new_boolean(bus_check->ErrorUncorrected)); 171 json_object_object_add(bus_check_ir, "preciseIP", json_object_new_boolean(bus_check->PreciseIp)); 172 json_object_object_add(bus_check_ir, "restartableIP", json_object_new_boolean(bus_check->RestartableIp)); 173 json_object_object_add(bus_check_ir, "overflow", json_object_new_boolean(bus_check->Overflow)); 174 json_object_object_add(bus_check_ir, "timedOut", json_object_new_boolean(bus_check->TimeOut)); 175 176 //Participation type. 177 json_object* participation_type = integer_to_readable_pair(bus_check->ParticipationType, 4, 178 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_KEYS, 179 IA32X64_BUS_CHECK_INFO_PARTICIPATION_TYPES_VALUES, 180 "Unknown"); 181 json_object_object_add(bus_check_ir, "participationType", participation_type); 182 183 //Address space. 184 json_object* address_space = integer_to_readable_pair(bus_check->AddressSpace, 4, 185 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_KEYS, 186 IA32X64_BUS_CHECK_INFO_ADDRESS_SPACE_TYPES_VALUES, 187 "Unknown"); 188 json_object_object_add(bus_check_ir, "addressSpace", address_space); 189 190 return bus_check_ir; 191 } 192 193 //Converts a single IA32/x64 MS check check info block into JSON IR format. 194 json_object* cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO* ms_check) 195 { 196 json_object* ms_check_ir = json_object_new_object(); 197 198 //Validation bits. 199 json_object* validation = bitfield_to_ir(ms_check->ValidFields, 6, IA32X64_CHECK_INFO_VALID_BITFIELD_NAMES); 200 json_object_object_add(ms_check_ir, "validationBits", validation); 201 202 //Error type (operation that caused the error). 203 json_object* error_type = integer_to_readable_pair(ms_check->ErrorType, 4, 204 IA32X64_MS_CHECK_INFO_ERROR_TYPES_KEYS, 205 IA32X64_MS_CHECK_INFO_ERROR_TYPES_VALUES, 206 "Unknown (Processor Specific)"); 207 json_object_object_add(ms_check_ir, "errorType", error_type); 208 209 //Miscellaneous fields. 210 json_object_object_add(ms_check_ir, "processorContextCorrupt", json_object_new_boolean(ms_check->ContextCorrupt)); 211 json_object_object_add(ms_check_ir, "uncorrected", json_object_new_boolean(ms_check->ErrorUncorrected)); 212 json_object_object_add(ms_check_ir, "preciseIP", json_object_new_boolean(ms_check->PreciseIp)); 213 json_object_object_add(ms_check_ir, "restartableIP", json_object_new_boolean(ms_check->RestartableIp)); 214 json_object_object_add(ms_check_ir, "overflow", json_object_new_boolean(ms_check->Overflow)); 215 216 return ms_check_ir; 217 } 218 219 //Converts a single IA32/x64 processor context info entry into JSON IR format. 220 json_object* cper_ia32x64_processor_context_info_to_ir(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO* context_info, void** cur_pos) 221 { 222 json_object* context_info_ir = json_object_new_object(); 223 224 //Register context type. 225 json_object* context_type = integer_to_readable_pair(context_info->RegisterType, 8, 226 IA32X64_REGISTER_CONTEXT_TYPES_KEYS, 227 IA32X64_REGISTER_CONTEXT_TYPES_VALUES, 228 "Unknown (Reserved)"); 229 json_object_object_add(context_info_ir, "registerContextType", context_type); 230 231 //Register array size, MSR and MM address. 232 json_object_object_add(context_info_ir, "registerArraySize", json_object_new_uint64(context_info->ArraySize)); 233 json_object_object_add(context_info_ir, "msrAddress", json_object_new_uint64(context_info->MsrAddress)); 234 json_object_object_add(context_info_ir, "mmRegisterAddress", json_object_new_uint64(context_info->MmRegisterAddress)); 235 236 //Register array. 237 json_object* register_array = NULL; 238 if (context_info->RegisterType == 2) 239 { 240 EFI_CONTEXT_IA32_REGISTER_STATE* register_state = (EFI_CONTEXT_IA32_REGISTER_STATE*)(context_info + 1); 241 register_array = cper_ia32x64_register_32bit_to_ir(register_state); 242 *cur_pos = (void*)(register_state + 1); 243 } 244 else if (context_info->RegisterType == 3) 245 { 246 EFI_CONTEXT_X64_REGISTER_STATE* register_state = (EFI_CONTEXT_X64_REGISTER_STATE*)(context_info + 1); 247 register_array = cper_ia32x64_register_64bit_to_ir(register_state); 248 *cur_pos = (void*)(register_state + 1); 249 } 250 else 251 { 252 //No parseable data, just dump as base64 and shift the head to the next item. 253 *cur_pos = (void*)(context_info + 1); 254 255 char* encoded = b64_encode((unsigned char*)cur_pos, context_info->ArraySize); 256 register_array = json_object_new_object(); 257 json_object_object_add(register_array, "data", json_object_new_string(encoded)); 258 free(encoded); 259 260 *cur_pos = (void*)(((char*)*cur_pos) + context_info->ArraySize); 261 } 262 json_object_object_add(context_info_ir, "registerArray", register_array); 263 264 return context_info_ir; 265 } 266 267 //Converts a single CPER IA32 register state into JSON IR format. 268 json_object* cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE* registers) 269 { 270 json_object* ia32_registers = json_object_new_object(); 271 json_object_object_add(ia32_registers, "eax", json_object_new_int(registers->Eax)); 272 json_object_object_add(ia32_registers, "ebx", json_object_new_int(registers->Ebx)); 273 json_object_object_add(ia32_registers, "ecx", json_object_new_int(registers->Ecx)); 274 json_object_object_add(ia32_registers, "edx", json_object_new_int(registers->Edx)); 275 json_object_object_add(ia32_registers, "esi", json_object_new_int(registers->Esi)); 276 json_object_object_add(ia32_registers, "edi", json_object_new_int(registers->Edi)); 277 json_object_object_add(ia32_registers, "ebp", json_object_new_int(registers->Ebp)); 278 json_object_object_add(ia32_registers, "esp", json_object_new_int(registers->Esp)); 279 json_object_object_add(ia32_registers, "cs", json_object_new_int(registers->Cs)); 280 json_object_object_add(ia32_registers, "ds", json_object_new_int(registers->Ds)); 281 json_object_object_add(ia32_registers, "ss", json_object_new_int(registers->Ss)); 282 json_object_object_add(ia32_registers, "es", json_object_new_int(registers->Es)); 283 json_object_object_add(ia32_registers, "fs", json_object_new_int(registers->Fs)); 284 json_object_object_add(ia32_registers, "gs", json_object_new_int(registers->Gs)); 285 json_object_object_add(ia32_registers, "eflags", json_object_new_int(registers->Eflags)); 286 json_object_object_add(ia32_registers, "eip", json_object_new_int(registers->Eip)); 287 json_object_object_add(ia32_registers, "cr0", json_object_new_int(registers->Cr0)); 288 json_object_object_add(ia32_registers, "cr1", json_object_new_int(registers->Cr1)); 289 json_object_object_add(ia32_registers, "cr2", json_object_new_int(registers->Cr2)); 290 json_object_object_add(ia32_registers, "cr3", json_object_new_int(registers->Cr3)); 291 json_object_object_add(ia32_registers, "cr4", json_object_new_int(registers->Cr4)); 292 json_object_object_add(ia32_registers, "gdtr", json_object_new_uint64((registers->Gdtr[0] << 16) + registers->Gdtr[1])); 293 json_object_object_add(ia32_registers, "idtr", json_object_new_uint64((registers->Idtr[0] << 16) + registers->Idtr[1])); 294 json_object_object_add(ia32_registers, "ldtr", json_object_new_int(registers->Ldtr)); 295 json_object_object_add(ia32_registers, "tr", json_object_new_int(registers->Tr)); 296 297 return ia32_registers; 298 } 299 300 //Converts a single CPER x64 register state into JSON IR format. 301 json_object* cper_ia32x64_register_64bit_to_ir(EFI_CONTEXT_X64_REGISTER_STATE* registers) 302 { 303 json_object* x64_registers = json_object_new_object(); 304 json_object_object_add(x64_registers, "rax", json_object_new_uint64(registers->Rax)); 305 json_object_object_add(x64_registers, "rbx", json_object_new_uint64(registers->Rbx)); 306 json_object_object_add(x64_registers, "rcx", json_object_new_uint64(registers->Rcx)); 307 json_object_object_add(x64_registers, "rdx", json_object_new_uint64(registers->Rdx)); 308 json_object_object_add(x64_registers, "rsi", json_object_new_uint64(registers->Rsi)); 309 json_object_object_add(x64_registers, "rdi", json_object_new_uint64(registers->Rdi)); 310 json_object_object_add(x64_registers, "rbp", json_object_new_uint64(registers->Rbp)); 311 json_object_object_add(x64_registers, "rsp", json_object_new_uint64(registers->Rsp)); 312 json_object_object_add(x64_registers, "r8", json_object_new_uint64(registers->R8)); 313 json_object_object_add(x64_registers, "r9", json_object_new_uint64(registers->R9)); 314 json_object_object_add(x64_registers, "r10", json_object_new_uint64(registers->R10)); 315 json_object_object_add(x64_registers, "r11", json_object_new_uint64(registers->R11)); 316 json_object_object_add(x64_registers, "r12", json_object_new_uint64(registers->R12)); 317 json_object_object_add(x64_registers, "r13", json_object_new_uint64(registers->R13)); 318 json_object_object_add(x64_registers, "r14", json_object_new_uint64(registers->R14)); 319 json_object_object_add(x64_registers, "r15", json_object_new_uint64(registers->R15)); 320 json_object_object_add(x64_registers, "cs", json_object_new_int(registers->Cs)); 321 json_object_object_add(x64_registers, "ds", json_object_new_int(registers->Ds)); 322 json_object_object_add(x64_registers, "ss", json_object_new_int(registers->Ss)); 323 json_object_object_add(x64_registers, "es", json_object_new_int(registers->Es)); 324 json_object_object_add(x64_registers, "fs", json_object_new_int(registers->Fs)); 325 json_object_object_add(x64_registers, "gs", json_object_new_int(registers->Gs)); 326 json_object_object_add(x64_registers, "rflags", json_object_new_uint64(registers->Rflags)); 327 json_object_object_add(x64_registers, "eip", json_object_new_uint64(registers->Rip)); 328 json_object_object_add(x64_registers, "cr0", json_object_new_uint64(registers->Cr0)); 329 json_object_object_add(x64_registers, "cr1", json_object_new_uint64(registers->Cr1)); 330 json_object_object_add(x64_registers, "cr2", json_object_new_uint64(registers->Cr2)); 331 json_object_object_add(x64_registers, "cr3", json_object_new_uint64(registers->Cr3)); 332 json_object_object_add(x64_registers, "cr4", json_object_new_uint64(registers->Cr4)); 333 //todo: Where is CR8? On the specification, not in the headers. 334 //json_object_object_add(x64_registers, "cr8", json_object_new_uint64(registers->)); 335 json_object_object_add(x64_registers, "gdtr_0", json_object_new_uint64(registers->Gdtr[0])); 336 json_object_object_add(x64_registers, "gdtr_1", json_object_new_uint64(registers->Gdtr[1])); 337 json_object_object_add(x64_registers, "idtr_0", json_object_new_uint64(registers->Idtr[0])); 338 json_object_object_add(x64_registers, "idtr_1", json_object_new_uint64(registers->Idtr[1])); 339 json_object_object_add(x64_registers, "ldtr", json_object_new_int(registers->Ldtr)); 340 json_object_object_add(x64_registers, "tr", json_object_new_int(registers->Tr)); 341 342 return x64_registers; 343 }