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> 9*5202bbb4SLawrence 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. 16e407b4c8SLawrence Tang json_object * 17e407b4c8SLawrence Tang cper_section_dmar_vtd_to_ir(void *section, 18e407b4c8SLawrence Tang EFI_ERROR_SECTION_DESCRIPTOR *descriptor) 19db1b7ce2SLawrence Tang { 20e407b4c8SLawrence Tang EFI_DIRECTED_IO_DMAR_ERROR_DATA *vtd_error = 21e407b4c8SLawrence 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); 28e407b4c8SLawrence Tang json_object_object_add(section_ir, "version", 29e407b4c8SLawrence Tang json_object_new_int(vtd_error->Version)); 30e407b4c8SLawrence Tang json_object_object_add(section_ir, "revision", 31e407b4c8SLawrence Tang json_object_new_int(vtd_error->Revision)); 32e407b4c8SLawrence Tang json_object_object_add(section_ir, "oemID", 33e407b4c8SLawrence Tang json_object_new_uint64(oem_id)); 34db1b7ce2SLawrence Tang 35db1b7ce2SLawrence Tang //Registers. 36e407b4c8SLawrence Tang json_object_object_add(section_ir, "capabilityRegister", 37e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->Capability)); 38e407b4c8SLawrence Tang json_object_object_add(section_ir, "extendedCapabilityRegister", 39e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->CapabilityEx)); 40e407b4c8SLawrence Tang json_object_object_add( 41e407b4c8SLawrence Tang section_ir, "globalCommandRegister", 42e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->GlobalCommand)); 43e407b4c8SLawrence Tang json_object_object_add(section_ir, "globalStatusRegister", 44e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->GlobalStatus)); 45e407b4c8SLawrence Tang json_object_object_add(section_ir, "faultStatusRegister", 46e407b4c8SLawrence 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(); 50e407b4c8SLawrence Tang EFI_VTD_FAULT_RECORD *fault_record = 51e407b4c8SLawrence Tang (EFI_VTD_FAULT_RECORD *)vtd_error->FaultRecord; 52e407b4c8SLawrence Tang json_object_object_add( 53e407b4c8SLawrence Tang fault_record_ir, "faultInformation", 54e407b4c8SLawrence Tang json_object_new_uint64(fault_record->FaultInformation)); 55e407b4c8SLawrence Tang json_object_object_add( 56e407b4c8SLawrence Tang fault_record_ir, "sourceIdentifier", 57e407b4c8SLawrence Tang json_object_new_uint64(fault_record->SourceIdentifier)); 58e407b4c8SLawrence Tang json_object_object_add( 59e407b4c8SLawrence Tang fault_record_ir, "privelegeModeRequested", 60ce0f82bfSLawrence Tang json_object_new_boolean(fault_record->PrivelegeModeRequested)); 61e407b4c8SLawrence Tang json_object_object_add( 62e407b4c8SLawrence Tang fault_record_ir, "executePermissionRequested", 63e407b4c8SLawrence Tang json_object_new_boolean( 64e407b4c8SLawrence Tang fault_record->ExecutePermissionRequested)); 65e407b4c8SLawrence Tang json_object_object_add( 66e407b4c8SLawrence Tang fault_record_ir, "pasidPresent", 67e407b4c8SLawrence Tang json_object_new_boolean(fault_record->PasidPresent)); 68e407b4c8SLawrence Tang json_object_object_add( 69e407b4c8SLawrence Tang fault_record_ir, "faultReason", 70e407b4c8SLawrence Tang json_object_new_uint64(fault_record->FaultReason)); 71e407b4c8SLawrence Tang json_object_object_add( 72e407b4c8SLawrence Tang fault_record_ir, "pasidValue", 73e407b4c8SLawrence Tang json_object_new_uint64(fault_record->PasidValue)); 74e407b4c8SLawrence Tang json_object_object_add( 75e407b4c8SLawrence Tang fault_record_ir, "addressType", 76e407b4c8SLawrence Tang json_object_new_uint64(fault_record->AddressType)); 77ce0f82bfSLawrence Tang 78205dd1d7SLawrence Tang //Fault record type. 79e407b4c8SLawrence Tang json_object *fault_record_type = integer_to_readable_pair( 80e407b4c8SLawrence Tang fault_record->Type, 2, VTD_FAULT_RECORD_TYPES_KEYS, 81e407b4c8SLawrence 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); 87e407b4c8SLawrence Tang json_object_object_add(section_ir, "rootEntry", 88e407b4c8SLawrence 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); 93e407b4c8SLawrence Tang json_object_object_add(section_ir, "contextEntry", 94e407b4c8SLawrence Tang json_object_new_string(encoded)); 95ce0f82bfSLawrence Tang free(encoded); 96db1b7ce2SLawrence Tang 97db1b7ce2SLawrence Tang //PTE entry for all page levels. 98e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level6", 99e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL6)); 100e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level5", 101e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL5)); 102e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level4", 103e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL4)); 104e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level3", 105e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL3)); 106e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level2", 107e407b4c8SLawrence Tang json_object_new_uint64(vtd_error->PteL2)); 108e407b4c8SLawrence Tang json_object_object_add(section_ir, "pageTableEntry_Level1", 109e407b4c8SLawrence 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 = 118e407b4c8SLawrence Tang (EFI_DIRECTED_IO_DMAR_ERROR_DATA *)calloc( 119e407b4c8SLawrence Tang 1, sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA)); 120205dd1d7SLawrence Tang 121205dd1d7SLawrence Tang //OEM ID. 122e407b4c8SLawrence Tang UINT64 oem_id = json_object_get_uint64( 123e407b4c8SLawrence 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. 128e407b4c8SLawrence Tang section_cper->Version = (UINT8)json_object_get_int( 129e407b4c8SLawrence Tang json_object_object_get(section, "version")); 130e407b4c8SLawrence Tang section_cper->Revision = (UINT8)json_object_get_int( 131e407b4c8SLawrence Tang json_object_object_get(section, "revision")); 132e407b4c8SLawrence Tang section_cper->Capability = json_object_get_uint64( 133e407b4c8SLawrence Tang json_object_object_get(section, "capabilityRegister")); 134e407b4c8SLawrence Tang section_cper->CapabilityEx = json_object_get_uint64( 135e407b4c8SLawrence Tang json_object_object_get(section, "extendedCapabilityRegister")); 136e407b4c8SLawrence Tang section_cper->GlobalCommand = json_object_get_uint64( 137e407b4c8SLawrence Tang json_object_object_get(section, "globalCommandRegister")); 138e407b4c8SLawrence Tang section_cper->GlobalStatus = json_object_get_uint64( 139e407b4c8SLawrence Tang json_object_object_get(section, "globalStatusRegister")); 140e407b4c8SLawrence Tang section_cper->FaultStatus = json_object_get_uint64( 141e407b4c8SLawrence Tang json_object_object_get(section, "faultStatusRegister")); 142205dd1d7SLawrence Tang 143205dd1d7SLawrence Tang //Fault record. 144e407b4c8SLawrence Tang json_object *fault_record = 145e407b4c8SLawrence Tang json_object_object_get(section, "faultRecord"); 146e407b4c8SLawrence Tang EFI_VTD_FAULT_RECORD *fault_record_cper = 147e407b4c8SLawrence Tang (EFI_VTD_FAULT_RECORD *)section_cper->FaultRecord; 148e407b4c8SLawrence Tang fault_record_cper->FaultInformation = json_object_get_uint64( 149e407b4c8SLawrence Tang json_object_object_get(fault_record, "faultInformation")); 150e407b4c8SLawrence Tang fault_record_cper->SourceIdentifier = json_object_get_uint64( 151e407b4c8SLawrence Tang json_object_object_get(fault_record, "sourceIdentifier")); 152e407b4c8SLawrence Tang fault_record_cper->PrivelegeModeRequested = json_object_get_boolean( 153e407b4c8SLawrence Tang json_object_object_get(fault_record, "privelegeModeRequested")); 154e407b4c8SLawrence Tang fault_record_cper->ExecutePermissionRequested = json_object_get_boolean( 155e407b4c8SLawrence Tang json_object_object_get(fault_record, 156e407b4c8SLawrence Tang "executePermissionRequested")); 157e407b4c8SLawrence Tang fault_record_cper->PasidPresent = json_object_get_boolean( 158e407b4c8SLawrence Tang json_object_object_get(fault_record, "pasidPresent")); 159e407b4c8SLawrence Tang fault_record_cper->FaultReason = json_object_get_uint64( 160e407b4c8SLawrence Tang json_object_object_get(fault_record, "faultReason")); 161e407b4c8SLawrence Tang fault_record_cper->PasidValue = json_object_get_uint64( 162e407b4c8SLawrence Tang json_object_object_get(fault_record, "pasidValue")); 163e407b4c8SLawrence Tang fault_record_cper->AddressType = json_object_get_uint64( 164e407b4c8SLawrence Tang json_object_object_get(fault_record, "addressType")); 165e407b4c8SLawrence Tang fault_record_cper->Type = readable_pair_to_integer( 166e407b4c8SLawrence 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"); 170e407b4c8SLawrence Tang UINT8 *decoded = b64_decode(json_object_get_string(encoded), 171e407b4c8SLawrence 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"); 177e407b4c8SLawrence Tang decoded = b64_decode(json_object_get_string(encoded), 178e407b4c8SLawrence 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. 183e407b4c8SLawrence Tang section_cper->PteL1 = json_object_get_uint64( 184e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level1")); 185e407b4c8SLawrence Tang section_cper->PteL2 = json_object_get_uint64( 186e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level2")); 187e407b4c8SLawrence Tang section_cper->PteL3 = json_object_get_uint64( 188e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level3")); 189e407b4c8SLawrence Tang section_cper->PteL4 = json_object_get_uint64( 190e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level4")); 191e407b4c8SLawrence Tang section_cper->PteL5 = json_object_get_uint64( 192e407b4c8SLawrence Tang json_object_object_get(section, "pageTableEntry_Level5")); 193e407b4c8SLawrence Tang section_cper->PteL6 = json_object_get_uint64( 194e407b4c8SLawrence 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 }