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