| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 1 | /** | 
|  | 2 | * Describes functions for converting PCIe CPER sections from binary and JSON format | 
|  | 3 | * into an intermediate format. | 
| Ed Tanous | fedd457 | 2024-07-12 13:56:00 -0700 | [diff] [blame] | 4 | * | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 5 | * Author: Lawrence.Tang@arm.com | 
|  | 6 | **/ | 
|  | 7 | #include <stdio.h> | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 8 | #include <string.h> | 
| Lawrence Tang | 5202bbb | 2022-08-12 14:54:36 +0100 | [diff] [blame] | 9 | #include <json.h> | 
| Thu Nguyen | e42fb48 | 2024-10-15 14:43:11 +0000 | [diff] [blame] | 10 | #include <libcper/base64.h> | 
|  | 11 | #include <libcper/Cper.h> | 
|  | 12 | #include <libcper/cper-utils.h> | 
|  | 13 | #include <libcper/sections/cper-section-pcie.h> | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 14 |  | 
| Andrew Adriance | 3cebfc2 | 2024-11-20 12:57:04 -0800 | [diff] [blame^] | 15 | struct aer_info_registers { | 
|  | 16 | UINT32 pcie_capability_header; | 
|  | 17 | UINT32 uncorrectable_error_status; | 
|  | 18 | UINT32 uncorrectable_error_mask; | 
|  | 19 | UINT32 uncorrectable_error_severity; | 
|  | 20 | UINT32 correctable_error_status; | 
|  | 21 | UINT32 correctable_error_mask; | 
|  | 22 | UINT32 aer_capabilites_control; | 
|  | 23 | UINT32 tlp_header_log[4]; | 
|  | 24 | }; | 
|  | 25 |  | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 26 | //Converts a single PCIe CPER section into JSON IR. | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 27 | json_object *cper_section_pcie_to_ir(void *section) | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 28 | { | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 29 | EFI_PCIE_ERROR_DATA *pcie_error = (EFI_PCIE_ERROR_DATA *)section; | 
|  | 30 | json_object *section_ir = json_object_new_object(); | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 31 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 32 | //Validation bits. | 
|  | 33 | json_object *validation = bitfield_to_ir( | 
|  | 34 | pcie_error->ValidFields, 8, PCIE_ERROR_VALID_BITFIELD_NAMES); | 
|  | 35 | json_object_object_add(section_ir, "validationBits", validation); | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 36 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 37 | //Port type. | 
|  | 38 | json_object *port_type = integer_to_readable_pair( | 
|  | 39 | pcie_error->PortType, 9, PCIE_ERROR_PORT_TYPES_KEYS, | 
|  | 40 | PCIE_ERROR_PORT_TYPES_VALUES, "Unknown"); | 
|  | 41 | json_object_object_add(section_ir, "portType", port_type); | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 42 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 43 | //Version, provided each half in BCD. | 
|  | 44 | json_object *version = json_object_new_object(); | 
|  | 45 | json_object_object_add( | 
|  | 46 | version, "minor", | 
|  | 47 | json_object_new_int(bcd_to_int(pcie_error->Version & 0xFF))); | 
|  | 48 | json_object_object_add( | 
|  | 49 | version, "major", | 
|  | 50 | json_object_new_int(bcd_to_int(pcie_error->Version >> 8))); | 
|  | 51 | json_object_object_add(section_ir, "version", version); | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 52 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 53 | //Command & status. | 
|  | 54 | json_object *command_status = json_object_new_object(); | 
|  | 55 | json_object_object_add( | 
|  | 56 | command_status, "commandRegister", | 
|  | 57 | json_object_new_uint64(pcie_error->CommandStatus & 0xFFFF)); | 
|  | 58 | json_object_object_add( | 
|  | 59 | command_status, "statusRegister", | 
|  | 60 | json_object_new_uint64(pcie_error->CommandStatus >> 16)); | 
|  | 61 | json_object_object_add(section_ir, "commandStatus", command_status); | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 62 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 63 | //PCIe Device ID. | 
|  | 64 | json_object *device_id = json_object_new_object(); | 
|  | 65 | UINT64 class_id = (pcie_error->DevBridge.ClassCode[0] << 16) + | 
|  | 66 | (pcie_error->DevBridge.ClassCode[1] << 8) + | 
|  | 67 | pcie_error->DevBridge.ClassCode[2]; | 
|  | 68 | json_object_object_add( | 
|  | 69 | device_id, "vendorID", | 
|  | 70 | json_object_new_uint64(pcie_error->DevBridge.VendorId)); | 
|  | 71 | json_object_object_add( | 
|  | 72 | device_id, "deviceID", | 
|  | 73 | json_object_new_uint64(pcie_error->DevBridge.DeviceId)); | 
|  | 74 | json_object_object_add(device_id, "classCode", | 
|  | 75 | json_object_new_uint64(class_id)); | 
|  | 76 | json_object_object_add( | 
|  | 77 | device_id, "functionNumber", | 
|  | 78 | json_object_new_uint64(pcie_error->DevBridge.Function)); | 
|  | 79 | json_object_object_add( | 
|  | 80 | device_id, "deviceNumber", | 
|  | 81 | json_object_new_uint64(pcie_error->DevBridge.Device)); | 
|  | 82 | json_object_object_add( | 
|  | 83 | device_id, "segmentNumber", | 
|  | 84 | json_object_new_uint64(pcie_error->DevBridge.Segment)); | 
|  | 85 | json_object_object_add( | 
|  | 86 | device_id, "primaryOrDeviceBusNumber", | 
|  | 87 | json_object_new_uint64( | 
|  | 88 | pcie_error->DevBridge.PrimaryOrDeviceBus)); | 
|  | 89 | json_object_object_add( | 
|  | 90 | device_id, "secondaryBusNumber", | 
|  | 91 | json_object_new_uint64(pcie_error->DevBridge.SecondaryBus)); | 
|  | 92 | json_object_object_add( | 
|  | 93 | device_id, "slotNumber", | 
|  | 94 | json_object_new_uint64(pcie_error->DevBridge.Slot.Number)); | 
|  | 95 | json_object_object_add(section_ir, "deviceID", device_id); | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 96 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 97 | //Device serial number. | 
|  | 98 | json_object_object_add(section_ir, "deviceSerialNumber", | 
|  | 99 | json_object_new_uint64(pcie_error->SerialNo)); | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 100 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 101 | //Bridge control status. | 
|  | 102 | json_object *bridge_control_status = json_object_new_object(); | 
|  | 103 | json_object_object_add( | 
|  | 104 | bridge_control_status, "secondaryStatusRegister", | 
|  | 105 | json_object_new_uint64(pcie_error->BridgeControlStatus & | 
|  | 106 | 0xFFFF)); | 
|  | 107 | json_object_object_add( | 
|  | 108 | bridge_control_status, "controlRegister", | 
|  | 109 | json_object_new_uint64(pcie_error->BridgeControlStatus >> 16)); | 
|  | 110 | json_object_object_add(section_ir, "bridgeControlStatus", | 
|  | 111 | bridge_control_status); | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 112 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 113 | //Capability structure. | 
|  | 114 | //The PCIe capability structure provided here could either be PCIe 1.1 Capability Structure | 
|  | 115 | //(36-byte, padded to 60 bytes) or PCIe 2.0 Capability Structure (60-byte). There does not seem | 
|  | 116 | //to be a way to differentiate these, so this is left as a b64 dump. | 
| Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 117 | int32_t encoded_len = 0; | 
|  | 118 |  | 
|  | 119 | char *encoded = base64_encode((UINT8 *)pcie_error->Capability.PcieCap, | 
|  | 120 | 60, &encoded_len); | 
|  | 121 | if (encoded == NULL) { | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 122 | printf("Failed to allocate encode output buffer. \n"); | 
|  | 123 | } else { | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 124 | json_object *capability = json_object_new_object(); | 
|  | 125 | json_object_object_add(capability, "data", | 
|  | 126 | json_object_new_string_len(encoded, | 
|  | 127 | encoded_len)); | 
|  | 128 | free(encoded); | 
| Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 129 |  | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 130 | json_object_object_add(section_ir, "capabilityStructure", | 
|  | 131 | capability); | 
|  | 132 | } | 
| Lawrence Tang | 4dbe3d7 | 2022-07-06 13:51:01 +0100 | [diff] [blame] | 133 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 134 | //AER information. | 
|  | 135 | json_object *aer_capability_ir = json_object_new_object(); | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 136 | encoded_len = 0; | 
| Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 137 |  | 
|  | 138 | encoded = base64_encode((UINT8 *)pcie_error->AerInfo.PcieAer, 96, | 
|  | 139 | &encoded_len); | 
|  | 140 | if (encoded == NULL) { | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 141 | printf("Failed to allocate encode output buffer. \n"); | 
|  | 142 | } else { | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 143 | json_object_object_add(aer_capability_ir, "data", | 
|  | 144 | json_object_new_string_len(encoded, | 
|  | 145 | encoded_len)); | 
|  | 146 | free(encoded); | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 147 | } | 
| Andrew Adriance | 3cebfc2 | 2024-11-20 12:57:04 -0800 | [diff] [blame^] | 148 |  | 
|  | 149 | struct aer_info_registers *aer_decode; | 
|  | 150 | aer_decode = (struct aer_info_registers *)&pcie_error->AerInfo.PcieAer; | 
|  | 151 | json_object_object_add( | 
|  | 152 | aer_capability_ir, "capability_header", | 
|  | 153 | json_object_new_uint64(aer_decode->pcie_capability_header)); | 
|  | 154 | json_object_object_add( | 
|  | 155 | aer_capability_ir, "uncorrectable_error_status", | 
|  | 156 | json_object_new_uint64(aer_decode->uncorrectable_error_status)); | 
|  | 157 | json_object_object_add( | 
|  | 158 | aer_capability_ir, "uncorrectable_error_mask", | 
|  | 159 | json_object_new_uint64(aer_decode->uncorrectable_error_mask)); | 
|  | 160 | json_object_object_add( | 
|  | 161 | aer_capability_ir, "uncorrectable_error_severity", | 
|  | 162 | json_object_new_uint64( | 
|  | 163 | aer_decode->uncorrectable_error_severity)); | 
|  | 164 | json_object_object_add( | 
|  | 165 | aer_capability_ir, "correctable_error_status", | 
|  | 166 | json_object_new_uint64(aer_decode->correctable_error_status)); | 
|  | 167 | json_object_object_add( | 
|  | 168 | aer_capability_ir, "correctable_error_mask", | 
|  | 169 | json_object_new_uint64(aer_decode->correctable_error_mask)); | 
|  | 170 | json_object_object_add( | 
|  | 171 | aer_capability_ir, "capabilites_control", | 
|  | 172 | json_object_new_uint64(aer_decode->aer_capabilites_control)); | 
|  | 173 | json_object_object_add( | 
|  | 174 | aer_capability_ir, "tlp_header_0", | 
|  | 175 | json_object_new_uint64(aer_decode->tlp_header_log[0])); | 
|  | 176 | json_object_object_add( | 
|  | 177 | aer_capability_ir, "tlp_header_1", | 
|  | 178 | json_object_new_uint64(aer_decode->tlp_header_log[1])); | 
|  | 179 | json_object_object_add( | 
|  | 180 | aer_capability_ir, "tlp_header_2", | 
|  | 181 | json_object_new_uint64(aer_decode->tlp_header_log[2])); | 
|  | 182 | json_object_object_add( | 
|  | 183 | aer_capability_ir, "tlp_header_3", | 
|  | 184 | json_object_new_uint64(aer_decode->tlp_header_log[3])); | 
| Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 185 | json_object_object_add(section_ir, "aerInfo", aer_capability_ir); | 
|  | 186 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 187 | return section_ir; | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 188 | } | 
|  | 189 |  | 
|  | 190 | //Converts a single CPER-JSON PCIe section into CPER binary, outputting to the given stream. | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 191 | void ir_section_pcie_to_cper(json_object *section, FILE *out) | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 192 | { | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 193 | EFI_PCIE_ERROR_DATA *section_cper = | 
|  | 194 | (EFI_PCIE_ERROR_DATA *)calloc(1, sizeof(EFI_PCIE_ERROR_DATA)); | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 195 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 196 | //Validation bits. | 
|  | 197 | section_cper->ValidFields = ir_to_bitfield( | 
|  | 198 | json_object_object_get(section, "validationBits"), 8, | 
|  | 199 | PCIE_ERROR_VALID_BITFIELD_NAMES); | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 200 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 201 | //Version. | 
|  | 202 | json_object *version = json_object_object_get(section, "version"); | 
|  | 203 | UINT32 minor = int_to_bcd( | 
|  | 204 | json_object_get_int(json_object_object_get(version, "minor"))); | 
|  | 205 | UINT32 major = int_to_bcd( | 
|  | 206 | json_object_get_int(json_object_object_get(version, "major"))); | 
|  | 207 | section_cper->Version = minor + (major << 8); | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 208 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 209 | //Command/status registers. | 
|  | 210 | json_object *command_status = | 
|  | 211 | json_object_object_get(section, "commandStatus"); | 
|  | 212 | UINT32 command = (UINT16)json_object_get_uint64( | 
|  | 213 | json_object_object_get(command_status, "commandRegister")); | 
|  | 214 | UINT32 status = (UINT16)json_object_get_uint64( | 
|  | 215 | json_object_object_get(command_status, "statusRegister")); | 
|  | 216 | section_cper->CommandStatus = command + (status << 16); | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 217 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 218 | //Device ID. | 
|  | 219 | json_object *device_id = json_object_object_get(section, "deviceID"); | 
|  | 220 | UINT64 class_id = json_object_get_uint64( | 
|  | 221 | json_object_object_get(device_id, "classCode")); | 
|  | 222 | section_cper->DevBridge.VendorId = (UINT16)json_object_get_uint64( | 
|  | 223 | json_object_object_get(device_id, "vendorID")); | 
|  | 224 | section_cper->DevBridge.DeviceId = (UINT16)json_object_get_uint64( | 
|  | 225 | json_object_object_get(device_id, "deviceID")); | 
|  | 226 | section_cper->DevBridge.ClassCode[0] = class_id >> 16; | 
|  | 227 | section_cper->DevBridge.ClassCode[1] = (class_id >> 8) & 0xFF; | 
|  | 228 | section_cper->DevBridge.ClassCode[2] = class_id & 0xFF; | 
|  | 229 | section_cper->DevBridge.Function = (UINT8)json_object_get_uint64( | 
|  | 230 | json_object_object_get(device_id, "functionNumber")); | 
|  | 231 | section_cper->DevBridge.Device = (UINT8)json_object_get_uint64( | 
|  | 232 | json_object_object_get(device_id, "deviceNumber")); | 
|  | 233 | section_cper->DevBridge.Segment = (UINT16)json_object_get_uint64( | 
|  | 234 | json_object_object_get(device_id, "segmentNumber")); | 
|  | 235 | section_cper->DevBridge.PrimaryOrDeviceBus = | 
|  | 236 | (UINT8)json_object_get_uint64(json_object_object_get( | 
|  | 237 | device_id, "primaryOrDeviceBusNumber")); | 
|  | 238 | section_cper->DevBridge.SecondaryBus = (UINT8)json_object_get_uint64( | 
|  | 239 | json_object_object_get(device_id, "secondaryBusNumber")); | 
|  | 240 | section_cper->DevBridge.Slot.Number = (UINT16)json_object_get_uint64( | 
|  | 241 | json_object_object_get(device_id, "slotNumber")); | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 242 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 243 | //Bridge/control status. | 
|  | 244 | json_object *bridge_control = | 
|  | 245 | json_object_object_get(section, "bridgeControlStatus"); | 
|  | 246 | UINT32 bridge_status = (UINT16)json_object_get_uint64( | 
|  | 247 | json_object_object_get(bridge_control, | 
|  | 248 | "secondaryStatusRegister")); | 
|  | 249 | UINT32 control_status = (UINT16)json_object_get_uint64( | 
|  | 250 | json_object_object_get(bridge_control, "controlRegister")); | 
|  | 251 | section_cper->BridgeControlStatus = | 
|  | 252 | bridge_status + (control_status << 16); | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 253 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 254 | //Capability structure. | 
|  | 255 | json_object *capability = | 
|  | 256 | json_object_object_get(section, "capabilityStructure"); | 
|  | 257 | json_object *encoded = json_object_object_get(capability, "data"); | 
| Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 258 |  | 
|  | 259 | int32_t decoded_len = 0; | 
|  | 260 |  | 
|  | 261 | UINT8 *decoded = base64_decode(json_object_get_string(encoded), | 
|  | 262 | json_object_get_string_len(encoded), | 
|  | 263 | &decoded_len); | 
|  | 264 | if (decoded == NULL) { | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 265 | printf("Failed to allocate decode output buffer. \n"); | 
|  | 266 | } else { | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 267 | memcpy(section_cper->Capability.PcieCap, decoded, decoded_len); | 
|  | 268 | free(decoded); | 
|  | 269 | } | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 270 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 271 | //AER capability structure. | 
|  | 272 | json_object *aer_info = json_object_object_get(section, "aerInfo"); | 
|  | 273 | encoded = json_object_object_get(aer_info, "data"); | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 274 | decoded_len = 0; | 
| Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 275 |  | 
|  | 276 | decoded = base64_decode(json_object_get_string(encoded), | 
|  | 277 | json_object_get_string_len(encoded), | 
|  | 278 | &decoded_len); | 
|  | 279 |  | 
|  | 280 | if (decoded == NULL) { | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 281 | printf("Failed to allocate decode output buffer. \n"); | 
|  | 282 | } else { | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 283 | memcpy(section_cper->AerInfo.PcieAer, decoded, decoded_len); | 
|  | 284 | free(decoded); | 
|  | 285 | } | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 286 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 287 | //Miscellaneous value fields. | 
|  | 288 | section_cper->PortType = (UINT32)readable_pair_to_integer( | 
|  | 289 | json_object_object_get(section, "portType")); | 
|  | 290 | section_cper->SerialNo = json_object_get_uint64( | 
|  | 291 | json_object_object_get(section, "deviceSerialNumber")); | 
| Lawrence Tang | 3b7f45b | 2022-07-14 14:14:30 +0100 | [diff] [blame] | 292 |  | 
| Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 293 | //Write out to stream, free resources. | 
|  | 294 | fwrite(section_cper, sizeof(EFI_PCIE_ERROR_DATA), 1, out); | 
|  | 295 | fflush(out); | 
|  | 296 | free(section_cper); | 
| John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 297 | } |