1 /** 2 * Describes functions for converting IOMMU 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-iommu.h" 14 15 //Converts a single IOMMU specific DMAr CPER section into JSON IR. 16 json_object * 17 cper_section_dmar_iommu_to_ir(void *section, 18 EFI_ERROR_SECTION_DESCRIPTOR *descriptor) 19 { 20 EFI_IOMMU_DMAR_ERROR_DATA *iommu_error = 21 (EFI_IOMMU_DMAR_ERROR_DATA *)section; 22 json_object *section_ir = json_object_new_object(); 23 24 //Revision. 25 json_object_object_add(section_ir, "revision", 26 json_object_new_int(iommu_error->Revision)); 27 28 //IOMMU registers. 29 json_object_object_add(section_ir, "controlRegister", 30 json_object_new_uint64(iommu_error->Control)); 31 json_object_object_add(section_ir, "statusRegister", 32 json_object_new_uint64(iommu_error->Status)); 33 34 //IOMMU event log entry. 35 //The format of these entries differ widely by the type of error. 36 char *encoded = 37 b64_encode((unsigned char *)iommu_error->EventLogEntry, 16); 38 json_object_object_add(section_ir, "eventLogEntry", 39 json_object_new_string(encoded)); 40 free(encoded); 41 42 //Device table entry (as base64). 43 encoded = 44 b64_encode((unsigned char *)iommu_error->DeviceTableEntry, 32); 45 json_object_object_add(section_ir, "deviceTableEntry", 46 json_object_new_string(encoded)); 47 free(encoded); 48 49 //Page table entries. 50 json_object_object_add(section_ir, "pageTableEntry_Level6", 51 json_object_new_uint64(iommu_error->PteL6)); 52 json_object_object_add(section_ir, "pageTableEntry_Level5", 53 json_object_new_uint64(iommu_error->PteL5)); 54 json_object_object_add(section_ir, "pageTableEntry_Level4", 55 json_object_new_uint64(iommu_error->PteL4)); 56 json_object_object_add(section_ir, "pageTableEntry_Level3", 57 json_object_new_uint64(iommu_error->PteL3)); 58 json_object_object_add(section_ir, "pageTableEntry_Level2", 59 json_object_new_uint64(iommu_error->PteL2)); 60 json_object_object_add(section_ir, "pageTableEntry_Level1", 61 json_object_new_uint64(iommu_error->PteL1)); 62 63 return section_ir; 64 } 65 66 //Converts a single DMAR IOMMU CPER-JSON section into CPER binary, outputting to the given stream. 67 void ir_section_dmar_iommu_to_cper(json_object *section, FILE *out) 68 { 69 EFI_IOMMU_DMAR_ERROR_DATA *section_cper = 70 (EFI_IOMMU_DMAR_ERROR_DATA *)calloc( 71 1, sizeof(EFI_IOMMU_DMAR_ERROR_DATA)); 72 73 //Revision, registers. 74 section_cper->Revision = (UINT8)json_object_get_int( 75 json_object_object_get(section, "revision")); 76 section_cper->Control = json_object_get_uint64( 77 json_object_object_get(section, "controlRegister")); 78 section_cper->Status = json_object_get_uint64( 79 json_object_object_get(section, "statusRegister")); 80 81 //IOMMU event log entry. 82 json_object *encoded = json_object_object_get(section, "eventLogEntry"); 83 UINT8 *decoded = b64_decode(json_object_get_string(encoded), 84 json_object_get_string_len(encoded)); 85 memcpy(section_cper->EventLogEntry, decoded, 16); 86 free(decoded); 87 88 //Device table entry. 89 encoded = json_object_object_get(section, "deviceTableEntry"); 90 decoded = b64_decode(json_object_get_string(encoded), 91 json_object_get_string_len(encoded)); 92 memcpy(section_cper->DeviceTableEntry, decoded, 32); 93 free(decoded); 94 95 //Page table entries. 96 section_cper->PteL1 = json_object_get_uint64( 97 json_object_object_get(section, "pageTableEntry_Level1")); 98 section_cper->PteL2 = json_object_get_uint64( 99 json_object_object_get(section, "pageTableEntry_Level2")); 100 section_cper->PteL3 = json_object_get_uint64( 101 json_object_object_get(section, "pageTableEntry_Level3")); 102 section_cper->PteL4 = json_object_get_uint64( 103 json_object_object_get(section, "pageTableEntry_Level4")); 104 section_cper->PteL5 = json_object_get_uint64( 105 json_object_object_get(section, "pageTableEntry_Level5")); 106 section_cper->PteL6 = json_object_get_uint64( 107 json_object_object_get(section, "pageTableEntry_Level6")); 108 109 //Write to stream, free resources. 110 fwrite(section_cper, sizeof(EFI_IOMMU_DMAR_ERROR_DATA), 1, out); 111 fflush(out); 112 free(section_cper); 113 }