1db1b7ce2SLawrence Tang /** 2db1b7ce2SLawrence Tang * Describes functions for converting VT-d specific DMAr CPER sections from binary and JSON format 3db1b7ce2SLawrence Tang * into an intermediate format. 4db1b7ce2SLawrence Tang * 5db1b7ce2SLawrence Tang * Author: Lawrence.Tang@arm.com 6db1b7ce2SLawrence Tang **/ 7db1b7ce2SLawrence Tang #include <stdio.h> 8205dd1d7SLawrence Tang #include <string.h> 9db1b7ce2SLawrence Tang #include "json.h" 10ce0f82bfSLawrence Tang #include "b64.h" 11db1b7ce2SLawrence Tang #include "../edk/Cper.h" 12db1b7ce2SLawrence Tang #include "../cper-utils.h" 13db1b7ce2SLawrence Tang #include "cper-section-dmar-vtd.h" 14db1b7ce2SLawrence Tang 15db1b7ce2SLawrence Tang //Converts a single VT-d specific DMAr CPER section into JSON IR. 16*e407b4c8SLawrence Tang json_object * 17*e407b4c8SLawrence Tang cper_section_dmar_vtd_to_ir(void *section, 18*e407b4c8SLawrence Tang EFI_ERROR_SECTION_DESCRIPTOR *descriptor) 19db1b7ce2SLawrence Tang { 20*e407b4c8SLawrence Tang EFI_DIRECTED_IO_DMAR_ERROR_DATA *vtd_error = 21*e407b4c8SLawrence Tang (EFI_DIRECTED_IO_DMAR_ERROR_DATA *)section; 22db1b7ce2SLawrence Tang json_object *section_ir = json_object_new_object(); 23db1b7ce2SLawrence Tang 24db1b7ce2SLawrence Tang //Version, revision and OEM ID, as defined in the VT-d architecture. 250a4b3f2dSLawrence Tang UINT64 oem_id = 0; 260a4b3f2dSLawrence Tang for (int i = 0; i < 6; i++) 270a4b3f2dSLawrence Tang oem_id |= (UINT64)vtd_error->OemId[i] << (i * 8); 28*e407b4c8SLawrence Tang json_object_object_add(section_ir, "version", 29*e407b4c8SLawrence Tang json_object_new_int(vtd_error->Version)); 30*e407b4c8SLawrence Tang json_object_object_add(section_ir, "revision", 31*e407b4c8SLawrence Tang json_object_new_int(vtd_error->Revision)); 32*e407b4c8SLawrence Tang json_object_object_add(section_ir, "oemID", 33*e407b4c8SLawrence Tang json_object_new_uint64(oem_id)); 34db1b7ce2SLawrence Tang 35db1b7ce2SLawrence Tang //Registers. 36*e407b4c8SLawrence Tang json_object_object_add(section_ir, "capabilityRegister", 37*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->Capability)); 38*e407b4c8SLawrence Tang json_object_object_add(section_ir, "extendedCapabilityRegister", 39*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->CapabilityEx)); 40*e407b4c8SLawrence Tang json_object_object_add( 41*e407b4c8SLawrence Tang section_ir, "globalCommandRegister", 42*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->GlobalCommand)); 43*e407b4c8SLawrence Tang json_object_object_add(section_ir, "globalStatusRegister", 44*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->GlobalStatus)); 45*e407b4c8SLawrence Tang json_object_object_add(section_ir, "faultStatusRegister", 46*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->FaultStatus)); 47db1b7ce2SLawrence Tang 48ce0f82bfSLawrence Tang //Fault record basic fields. 49ce0f82bfSLawrence Tang json_object *fault_record_ir = json_object_new_object(); 50*e407b4c8SLawrence Tang EFI_VTD_FAULT_RECORD *fault_record = 51*e407b4c8SLawrence Tang (EFI_VTD_FAULT_RECORD *)vtd_error->FaultRecord; 52*e407b4c8SLawrence Tang json_object_object_add( 53*e407b4c8SLawrence Tang fault_record_ir, "faultInformation", 54*e407b4c8SLawrence Tang json_object_new_uint64(fault_record->FaultInformation)); 55*e407b4c8SLawrence Tang json_object_object_add( 56*e407b4c8SLawrence Tang fault_record_ir, "sourceIdentifier", 57*e407b4c8SLawrence Tang json_object_new_uint64(fault_record->SourceIdentifier)); 58*e407b4c8SLawrence Tang json_object_object_add( 59*e407b4c8SLawrence Tang fault_record_ir, "privelegeModeRequested", 60ce0f82bfSLawrence Tang json_object_new_boolean(fault_record->PrivelegeModeRequested)); 61*e407b4c8SLawrence Tang json_object_object_add( 62*e407b4c8SLawrence Tang fault_record_ir, "executePermissionRequested", 63*e407b4c8SLawrence Tang json_object_new_boolean( 64*e407b4c8SLawrence Tang fault_record->ExecutePermissionRequested)); 65*e407b4c8SLawrence Tang json_object_object_add( 66*e407b4c8SLawrence Tang fault_record_ir, "pasidPresent", 67*e407b4c8SLawrence Tang json_object_new_boolean(fault_record->PasidPresent)); 68*e407b4c8SLawrence Tang json_object_object_add( 69*e407b4c8SLawrence Tang fault_record_ir, "faultReason", 70*e407b4c8SLawrence Tang json_object_new_uint64(fault_record->FaultReason)); 71*e407b4c8SLawrence Tang json_object_object_add( 72*e407b4c8SLawrence Tang fault_record_ir, "pasidValue", 73*e407b4c8SLawrence Tang json_object_new_uint64(fault_record->PasidValue)); 74*e407b4c8SLawrence Tang json_object_object_add( 75*e407b4c8SLawrence Tang fault_record_ir, "addressType", 76*e407b4c8SLawrence Tang json_object_new_uint64(fault_record->AddressType)); 77ce0f82bfSLawrence Tang 78205dd1d7SLawrence Tang //Fault record type. 79*e407b4c8SLawrence Tang json_object *fault_record_type = integer_to_readable_pair( 80*e407b4c8SLawrence Tang fault_record->Type, 2, VTD_FAULT_RECORD_TYPES_KEYS, 81*e407b4c8SLawrence Tang VTD_FAULT_RECORD_TYPES_VALUES, "Unknown"); 82ce0f82bfSLawrence Tang json_object_object_add(fault_record_ir, "type", fault_record_type); 83ce0f82bfSLawrence Tang json_object_object_add(section_ir, "faultRecord", fault_record_ir); 84ce0f82bfSLawrence Tang 85ce0f82bfSLawrence Tang //Root entry. 86ce0f82bfSLawrence Tang char *encoded = b64_encode((unsigned char *)vtd_error->RootEntry, 16); 87*e407b4c8SLawrence Tang json_object_object_add(section_ir, "rootEntry", 88*e407b4c8SLawrence Tang json_object_new_string(encoded)); 89ce0f82bfSLawrence Tang free(encoded); 90ce0f82bfSLawrence Tang 91ce0f82bfSLawrence Tang //Context entry. 92ce0f82bfSLawrence Tang encoded = b64_encode((unsigned char *)vtd_error->ContextEntry, 16); 93*e407b4c8SLawrence Tang json_object_object_add(section_ir, "contextEntry", 94*e407b4c8SLawrence Tang json_object_new_string(encoded)); 95ce0f82bfSLawrence Tang free(encoded); 96db1b7ce2SLawrence Tang 97db1b7ce2SLawrence Tang //PTE entry for all page levels. 98*e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level6", 99*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL6)); 100*e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level5", 101*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL5)); 102*e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level4", 103*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL4)); 104*e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level3", 105*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL3)); 106*e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level2", 107*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL2)); 108*e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level1", 109*e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL1)); 110db1b7ce2SLawrence Tang 111db1b7ce2SLawrence Tang return section_ir; 112db1b7ce2SLawrence Tang } 113205dd1d7SLawrence Tang 114205dd1d7SLawrence Tang //Converts a single VT-d DMAR CPER-JSON segment into CPER binary, outputting to the given stream. 115205dd1d7SLawrence Tang void ir_section_dmar_vtd_to_cper(json_object *section, FILE *out) 116205dd1d7SLawrence Tang { 117205dd1d7SLawrence Tang EFI_DIRECTED_IO_DMAR_ERROR_DATA *section_cper = 118*e407b4c8SLawrence Tang (EFI_DIRECTED_IO_DMAR_ERROR_DATA *)calloc( 119*e407b4c8SLawrence Tang 1, sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA)); 120205dd1d7SLawrence Tang 121205dd1d7SLawrence Tang //OEM ID. 122*e407b4c8SLawrence Tang UINT64 oem_id = json_object_get_uint64( 123*e407b4c8SLawrence Tang json_object_object_get(section, "oemID")); 1240a4b3f2dSLawrence Tang for (int i = 0; i < 6; i++) 1250a4b3f2dSLawrence Tang section_cper->OemId[i] = (oem_id >> (i * 8)) & 0xFF; 126205dd1d7SLawrence Tang 127205dd1d7SLawrence Tang //Registers & basic numeric fields. 128*e407b4c8SLawrence Tang section_cper->Version = (UINT8)json_object_get_int( 129*e407b4c8SLawrence Tang json_object_object_get(section, "version")); 130*e407b4c8SLawrence Tang section_cper->Revision = (UINT8)json_object_get_int( 131*e407b4c8SLawrence Tang json_object_object_get(section, "revision")); 132*e407b4c8SLawrence Tang section_cper->Capability = json_object_get_uint64( 133*e407b4c8SLawrence Tang json_object_object_get(section, "capabilityRegister")); 134*e407b4c8SLawrence Tang section_cper->CapabilityEx = json_object_get_uint64( 135*e407b4c8SLawrence Tang json_object_object_get(section, "extendedCapabilityRegister")); 136*e407b4c8SLawrence Tang section_cper->GlobalCommand = json_object_get_uint64( 137*e407b4c8SLawrence Tang json_object_object_get(section, "globalCommandRegister")); 138*e407b4c8SLawrence Tang section_cper->GlobalStatus = json_object_get_uint64( 139*e407b4c8SLawrence Tang json_object_object_get(section, "globalStatusRegister")); 140*e407b4c8SLawrence Tang section_cper->FaultStatus = json_object_get_uint64( 141*e407b4c8SLawrence Tang json_object_object_get(section, "faultStatusRegister")); 142205dd1d7SLawrence Tang 143205dd1d7SLawrence Tang //Fault record. 144*e407b4c8SLawrence Tang json_object *fault_record = 145*e407b4c8SLawrence Tang json_object_object_get(section, "faultRecord"); 146*e407b4c8SLawrence Tang EFI_VTD_FAULT_RECORD *fault_record_cper = 147*e407b4c8SLawrence Tang (EFI_VTD_FAULT_RECORD *)section_cper->FaultRecord; 148*e407b4c8SLawrence Tang fault_record_cper->FaultInformation = json_object_get_uint64( 149*e407b4c8SLawrence Tang json_object_object_get(fault_record, "faultInformation")); 150*e407b4c8SLawrence Tang fault_record_cper->SourceIdentifier = json_object_get_uint64( 151*e407b4c8SLawrence Tang json_object_object_get(fault_record, "sourceIdentifier")); 152*e407b4c8SLawrence Tang fault_record_cper->PrivelegeModeRequested = json_object_get_boolean( 153*e407b4c8SLawrence Tang json_object_object_get(fault_record, "privelegeModeRequested")); 154*e407b4c8SLawrence Tang fault_record_cper->ExecutePermissionRequested = json_object_get_boolean( 155*e407b4c8SLawrence Tang json_object_object_get(fault_record, 156*e407b4c8SLawrence Tang "executePermissionRequested")); 157*e407b4c8SLawrence Tang fault_record_cper->PasidPresent = json_object_get_boolean( 158*e407b4c8SLawrence Tang json_object_object_get(fault_record, "pasidPresent")); 159*e407b4c8SLawrence Tang fault_record_cper->FaultReason = json_object_get_uint64( 160*e407b4c8SLawrence Tang json_object_object_get(fault_record, "faultReason")); 161*e407b4c8SLawrence Tang fault_record_cper->PasidValue = json_object_get_uint64( 162*e407b4c8SLawrence Tang json_object_object_get(fault_record, "pasidValue")); 163*e407b4c8SLawrence Tang fault_record_cper->AddressType = json_object_get_uint64( 164*e407b4c8SLawrence Tang json_object_object_get(fault_record, "addressType")); 165*e407b4c8SLawrence Tang fault_record_cper->Type = readable_pair_to_integer( 166*e407b4c8SLawrence Tang json_object_object_get(fault_record, "type")); 167205dd1d7SLawrence Tang 168205dd1d7SLawrence Tang //Root entry. 169205dd1d7SLawrence Tang json_object *encoded = json_object_object_get(section, "rootEntry"); 170*e407b4c8SLawrence Tang UINT8 *decoded = b64_decode(json_object_get_string(encoded), 171*e407b4c8SLawrence Tang json_object_get_string_len(encoded)); 172205dd1d7SLawrence Tang memcpy(section_cper->RootEntry, decoded, 16); 173205dd1d7SLawrence Tang free(decoded); 174205dd1d7SLawrence Tang 175205dd1d7SLawrence Tang //Context entry. 176205dd1d7SLawrence Tang encoded = json_object_object_get(section, "contextEntry"); 177*e407b4c8SLawrence Tang decoded = b64_decode(json_object_get_string(encoded), 178*e407b4c8SLawrence Tang json_object_get_string_len(encoded)); 179205dd1d7SLawrence Tang memcpy(section_cper->ContextEntry, decoded, 16); 180205dd1d7SLawrence Tang free(decoded); 181205dd1d7SLawrence Tang 182205dd1d7SLawrence Tang //Page table entries. 183*e407b4c8SLawrence Tang section_cper->PteL1 = json_object_get_uint64( 184*e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level1")); 185*e407b4c8SLawrence Tang section_cper->PteL2 = json_object_get_uint64( 186*e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level2")); 187*e407b4c8SLawrence Tang section_cper->PteL3 = json_object_get_uint64( 188*e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level3")); 189*e407b4c8SLawrence Tang section_cper->PteL4 = json_object_get_uint64( 190*e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level4")); 191*e407b4c8SLawrence Tang section_cper->PteL5 = json_object_get_uint64( 192*e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level5")); 193*e407b4c8SLawrence Tang section_cper->PteL6 = json_object_get_uint64( 194*e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level6")); 195205dd1d7SLawrence Tang 196205dd1d7SLawrence Tang //Write to stream, free resources. 1973ab351feSLawrence Tang fwrite(section_cper, sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA), 1, out); 198205dd1d7SLawrence Tang fflush(out); 199205dd1d7SLawrence Tang free(section_cper); 200205dd1d7SLawrence Tang }