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