1 /** 2 * Describes functions for converting PCI/PCI-X device 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 <json.h> 9 #include "../edk/Cper.h" 10 #include "../cper-utils.h" 11 #include "cper-section-pci-dev.h" 12 13 //Converts a single PCI/PCI-X device CPER section into JSON IR. 14 json_object *cper_section_pci_dev_to_ir(void *section) 15 { 16 EFI_PCI_PCIX_DEVICE_ERROR_DATA *dev_error = 17 (EFI_PCI_PCIX_DEVICE_ERROR_DATA *)section; 18 json_object *section_ir = json_object_new_object(); 19 20 //Validation bits. 21 json_object *validation = bitfield_to_ir( 22 dev_error->ValidFields, 5, PCI_DEV_ERROR_VALID_BITFIELD_NAMES); 23 json_object_object_add(section_ir, "validationBits", validation); 24 25 //Error status. 26 json_object *error_status = 27 cper_generic_error_status_to_ir(&dev_error->ErrorStatus); 28 json_object_object_add(section_ir, "errorStatus", error_status); 29 30 //ID information. 31 json_object *id_info = json_object_new_object(); 32 json_object_object_add( 33 id_info, "vendorID", 34 json_object_new_uint64(dev_error->IdInfo.VendorId)); 35 json_object_object_add( 36 id_info, "deviceID", 37 json_object_new_uint64(dev_error->IdInfo.DeviceId)); 38 json_object_object_add( 39 id_info, "classCode", 40 json_object_new_uint64(dev_error->IdInfo.ClassCode)); 41 json_object_object_add( 42 id_info, "functionNumber", 43 json_object_new_uint64(dev_error->IdInfo.FunctionNumber)); 44 json_object_object_add( 45 id_info, "deviceNumber", 46 json_object_new_uint64(dev_error->IdInfo.DeviceNumber)); 47 json_object_object_add( 48 id_info, "busNumber", 49 json_object_new_uint64(dev_error->IdInfo.BusNumber)); 50 json_object_object_add( 51 id_info, "segmentNumber", 52 json_object_new_uint64(dev_error->IdInfo.SegmentNumber)); 53 json_object_object_add(section_ir, "idInfo", id_info); 54 55 //Number of following register data pairs. 56 json_object_object_add(section_ir, "memoryNumber", 57 json_object_new_uint64(dev_error->MemoryNumber)); 58 json_object_object_add(section_ir, "ioNumber", 59 json_object_new_uint64(dev_error->IoNumber)); 60 int num_data_pairs = dev_error->MemoryNumber + dev_error->IoNumber; 61 62 //Register pairs, described by the numeric fields. 63 //The actual "pairs" of address and data aren't necessarily 8 bytes long, so can't assume the contents. 64 //Hence the naming "firstHalf" and "secondHalf" rather than "address" and "data". 65 json_object *register_data_pair_array = json_object_new_array(); 66 UINT64 *cur_pos = (UINT64 *)(dev_error + 1); 67 for (int i = 0; i < num_data_pairs; i++) { 68 //Save current pair to array. 69 json_object *register_data_pair = json_object_new_object(); 70 json_object_object_add(register_data_pair, "firstHalf", 71 json_object_new_uint64(*cur_pos)); 72 json_object_object_add(register_data_pair, "secondHalf", 73 json_object_new_uint64(*(cur_pos + 1))); 74 json_object_array_add(register_data_pair_array, 75 register_data_pair); 76 77 //Move to next pair. 78 cur_pos += 2; 79 } 80 json_object_object_add(section_ir, "registerDataPairs", 81 register_data_pair_array); 82 83 return section_ir; 84 } 85 86 void ir_section_pci_dev_to_cper(json_object *section, FILE *out) 87 { 88 EFI_PCI_PCIX_DEVICE_ERROR_DATA *section_cper = 89 (EFI_PCI_PCIX_DEVICE_ERROR_DATA *)calloc( 90 1, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA)); 91 92 //Validation bits. 93 section_cper->ValidFields = ir_to_bitfield( 94 json_object_object_get(section, "validationBits"), 5, 95 PCI_DEV_ERROR_VALID_BITFIELD_NAMES); 96 97 //Error status. 98 ir_generic_error_status_to_cper(json_object_object_get(section, 99 "errorStatus"), 100 §ion_cper->ErrorStatus); 101 102 //Device ID information. 103 json_object *id_info = json_object_object_get(section, "idInfo"); 104 section_cper->IdInfo.VendorId = json_object_get_uint64( 105 json_object_object_get(id_info, "vendorID")); 106 section_cper->IdInfo.DeviceId = json_object_get_uint64( 107 json_object_object_get(id_info, "deviceID")); 108 section_cper->IdInfo.ClassCode = json_object_get_uint64( 109 json_object_object_get(id_info, "classCode")); 110 section_cper->IdInfo.FunctionNumber = json_object_get_uint64( 111 json_object_object_get(id_info, "functionNumber")); 112 section_cper->IdInfo.DeviceNumber = json_object_get_uint64( 113 json_object_object_get(id_info, "deviceNumber")); 114 section_cper->IdInfo.BusNumber = json_object_get_uint64( 115 json_object_object_get(id_info, "busNumber")); 116 section_cper->IdInfo.SegmentNumber = json_object_get_uint64( 117 json_object_object_get(id_info, "segmentNumber")); 118 119 //Amount of following data pairs. 120 section_cper->MemoryNumber = (UINT32)json_object_get_uint64( 121 json_object_object_get(section, "memoryNumber")); 122 section_cper->IoNumber = (UINT32)json_object_get_uint64( 123 json_object_object_get(section, "ioNumber")); 124 125 //Write header out to stream, free it. 126 fwrite(section_cper, sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA), 1, out); 127 fflush(out); 128 free(section_cper); 129 130 //Begin writing register pairs. 131 json_object *register_pairs = 132 json_object_object_get(section, "registerDataPairs"); 133 int num_pairs = json_object_array_length(register_pairs); 134 for (int i = 0; i < num_pairs; i++) { 135 //Get the pair array item out. 136 json_object *register_pair = 137 json_object_array_get_idx(register_pairs, i); 138 139 //Create the pair array. 140 UINT64 pair[2]; 141 pair[0] = json_object_get_uint64( 142 json_object_object_get(register_pair, "firstHalf")); 143 pair[1] = json_object_get_uint64( 144 json_object_object_get(register_pair, "secondHalf")); 145 146 //Push to stream. 147 fwrite(pair, sizeof(UINT64), 2, out); 148 fflush(out); 149 } 150 } 151