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 "base64.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 *cper_section_dmar_iommu_to_ir(void *section) 17 { 18 EFI_IOMMU_DMAR_ERROR_DATA *iommu_error = 19 (EFI_IOMMU_DMAR_ERROR_DATA *)section; 20 json_object *section_ir = json_object_new_object(); 21 22 //Revision. 23 json_object_object_add(section_ir, "revision", 24 json_object_new_int(iommu_error->Revision)); 25 26 //IOMMU registers. 27 json_object_object_add(section_ir, "controlRegister", 28 json_object_new_uint64(iommu_error->Control)); 29 json_object_object_add(section_ir, "statusRegister", 30 json_object_new_uint64(iommu_error->Status)); 31 32 //IOMMU event log entry. 33 //The format of these entries differ widely by the type of error. 34 int32_t encoded_len = 0; 35 36 char *encoded = base64_encode((UINT8 *)iommu_error->EventLogEntry, 16, 37 &encoded_len); 38 if (encoded == NULL) { 39 printf("Failed to allocate encode output buffer. \n"); 40 41 return NULL; 42 } 43 json_object_object_add(section_ir, "eventLogEntry", 44 json_object_new_string_len(encoded, 45 encoded_len)); 46 free(encoded); 47 48 //Device table entry (as base64). 49 encoded_len = 0; 50 51 encoded = base64_encode((UINT8 *)iommu_error->DeviceTableEntry, 32, 52 &encoded_len); 53 if (encoded == NULL) { 54 printf("Failed to allocate encode output buffer. \n"); 55 return NULL; 56 } 57 json_object_object_add(section_ir, "deviceTableEntry", 58 json_object_new_string_len(encoded, 59 encoded_len)); 60 free(encoded); 61 62 //Page table entries. 63 json_object_object_add(section_ir, "pageTableEntry_Level6", 64 json_object_new_uint64(iommu_error->PteL6)); 65 json_object_object_add(section_ir, "pageTableEntry_Level5", 66 json_object_new_uint64(iommu_error->PteL5)); 67 json_object_object_add(section_ir, "pageTableEntry_Level4", 68 json_object_new_uint64(iommu_error->PteL4)); 69 json_object_object_add(section_ir, "pageTableEntry_Level3", 70 json_object_new_uint64(iommu_error->PteL3)); 71 json_object_object_add(section_ir, "pageTableEntry_Level2", 72 json_object_new_uint64(iommu_error->PteL2)); 73 json_object_object_add(section_ir, "pageTableEntry_Level1", 74 json_object_new_uint64(iommu_error->PteL1)); 75 76 return section_ir; 77 } 78 79 //Converts a single DMAR IOMMU CPER-JSON section into CPER binary, outputting to the given stream. 80 void ir_section_dmar_iommu_to_cper(json_object *section, FILE *out) 81 { 82 EFI_IOMMU_DMAR_ERROR_DATA *section_cper = 83 (EFI_IOMMU_DMAR_ERROR_DATA *)calloc( 84 1, sizeof(EFI_IOMMU_DMAR_ERROR_DATA)); 85 86 //Revision, registers. 87 section_cper->Revision = (UINT8)json_object_get_int( 88 json_object_object_get(section, "revision")); 89 section_cper->Control = json_object_get_uint64( 90 json_object_object_get(section, "controlRegister")); 91 section_cper->Status = json_object_get_uint64( 92 json_object_object_get(section, "statusRegister")); 93 94 //IOMMU event log entry. 95 json_object *encoded = json_object_object_get(section, "eventLogEntry"); 96 int32_t decoded_len = 0; 97 98 UINT8 *decoded = base64_decode(json_object_get_string(encoded), 99 json_object_get_string_len(encoded), 100 &decoded_len); 101 if (decoded == NULL) { 102 printf("Failed to allocate decode output buffer. \n"); 103 } else { 104 memcpy(section_cper->EventLogEntry, decoded, decoded_len); 105 free(decoded); 106 } 107 //Device table entry. 108 encoded = json_object_object_get(section, "deviceTableEntry"); 109 decoded_len = 0; 110 111 decoded = base64_decode(json_object_get_string(encoded), 112 json_object_get_string_len(encoded), 113 &decoded_len); 114 if (decoded == NULL) { 115 printf("Failed to allocate decode output buffer. \n"); 116 } else { 117 memcpy(section_cper->DeviceTableEntry, decoded, decoded_len); 118 free(decoded); 119 } 120 121 //Page table entries. 122 section_cper->PteL1 = json_object_get_uint64( 123 json_object_object_get(section, "pageTableEntry_Level1")); 124 section_cper->PteL2 = json_object_get_uint64( 125 json_object_object_get(section, "pageTableEntry_Level2")); 126 section_cper->PteL3 = json_object_get_uint64( 127 json_object_object_get(section, "pageTableEntry_Level3")); 128 section_cper->PteL4 = json_object_get_uint64( 129 json_object_object_get(section, "pageTableEntry_Level4")); 130 section_cper->PteL5 = json_object_get_uint64( 131 json_object_object_get(section, "pageTableEntry_Level5")); 132 section_cper->PteL6 = json_object_get_uint64( 133 json_object_object_get(section, "pageTableEntry_Level6")); 134 135 //Write to stream, free resources. 136 fwrite(section_cper, sizeof(EFI_IOMMU_DMAR_ERROR_DATA), 1, out); 137 fflush(out); 138 free(section_cper); 139 } 140