Lawrence Tang | d7e8ca3 | 2022-07-07 10:25:53 +0100 | [diff] [blame] | 1 | /** |
| 2 | * Describes functions for converting CXL component error 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 | d7e8ca3 | 2022-07-07 10:25:53 +0100 | [diff] [blame] | 5 | * Author: Lawrence.Tang@arm.com |
| 6 | **/ |
| 7 | #include <stdio.h> |
Lawrence Tang | 5202bbb | 2022-08-12 14:54:36 +0100 | [diff] [blame] | 8 | #include <json.h> |
Thu Nguyen | e42fb48 | 2024-10-15 14:43:11 +0000 | [diff] [blame] | 9 | #include <libcper/base64.h> |
| 10 | #include <libcper/Cper.h> |
| 11 | #include <libcper/cper-utils.h> |
| 12 | #include <libcper/sections/cper-section-cxl-component.h> |
Lawrence Tang | d7e8ca3 | 2022-07-07 10:25:53 +0100 | [diff] [blame] | 13 | |
| 14 | //Converts a single CXL component error CPER section into JSON IR. |
Ed Tanous | 12dbd4f | 2025-03-08 19:05:01 -0800 | [diff] [blame^] | 15 | json_object *cper_section_cxl_component_to_ir(const UINT8 *section, UINT32 size) |
Lawrence Tang | d7e8ca3 | 2022-07-07 10:25:53 +0100 | [diff] [blame] | 16 | { |
Ed Tanous | 12dbd4f | 2025-03-08 19:05:01 -0800 | [diff] [blame^] | 17 | if (size < sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)) { |
| 18 | return NULL; |
| 19 | } |
| 20 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 21 | EFI_CXL_COMPONENT_EVENT_HEADER *cxl_error = |
| 22 | (EFI_CXL_COMPONENT_EVENT_HEADER *)section; |
Ed Tanous | 12dbd4f | 2025-03-08 19:05:01 -0800 | [diff] [blame^] | 23 | if (cxl_error->Length < sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)) { |
| 24 | return NULL; |
| 25 | } |
| 26 | if (size < cxl_error->Length) { |
| 27 | return NULL; |
| 28 | } |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 29 | json_object *section_ir = json_object_new_object(); |
Lawrence Tang | 2721739 | 2022-07-07 11:55:39 +0100 | [diff] [blame] | 30 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 31 | //Length (bytes) for the entire structure. |
| 32 | json_object_object_add(section_ir, "length", |
| 33 | json_object_new_uint64(cxl_error->Length)); |
Lawrence Tang | 2721739 | 2022-07-07 11:55:39 +0100 | [diff] [blame] | 34 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 35 | //Validation bits. |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 36 | ValidationTypes ui64Type = { UINT_64T, |
| 37 | .value.ui64 = cxl_error->ValidBits }; |
Lawrence Tang | 2721739 | 2022-07-07 11:55:39 +0100 | [diff] [blame] | 38 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 39 | //Device ID. |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 40 | if (isvalid_prop_to_ir(&ui64Type, 0)) { |
| 41 | json_object *device_id = json_object_new_object(); |
| 42 | json_object_object_add( |
| 43 | device_id, "vendorID", |
| 44 | json_object_new_int(cxl_error->DeviceId.VendorId)); |
| 45 | json_object_object_add( |
| 46 | device_id, "deviceID", |
| 47 | json_object_new_int(cxl_error->DeviceId.DeviceId)); |
| 48 | json_object_object_add( |
| 49 | device_id, "functionNumber", |
| 50 | json_object_new_int( |
| 51 | cxl_error->DeviceId.FunctionNumber)); |
| 52 | json_object_object_add( |
| 53 | device_id, "deviceNumber", |
| 54 | json_object_new_int(cxl_error->DeviceId.DeviceNumber)); |
| 55 | json_object_object_add( |
| 56 | device_id, "busNumber", |
| 57 | json_object_new_int(cxl_error->DeviceId.BusNumber)); |
| 58 | json_object_object_add( |
| 59 | device_id, "segmentNumber", |
| 60 | json_object_new_int(cxl_error->DeviceId.SegmentNumber)); |
| 61 | json_object_object_add( |
| 62 | device_id, "slotNumber", |
| 63 | json_object_new_int(cxl_error->DeviceId.SlotNumber)); |
| 64 | json_object_object_add(section_ir, "deviceID", device_id); |
| 65 | } |
Lawrence Tang | 2721739 | 2022-07-07 11:55:39 +0100 | [diff] [blame] | 66 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 67 | //Device serial. |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 68 | if (isvalid_prop_to_ir(&ui64Type, 1)) { |
| 69 | json_object_object_add( |
| 70 | section_ir, "deviceSerial", |
| 71 | json_object_new_uint64(cxl_error->DeviceSerial)); |
| 72 | } |
Lawrence Tang | d7e8ca3 | 2022-07-07 10:25:53 +0100 | [diff] [blame] | 73 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 74 | //The specification for this is defined within the CXL Specification Section 8.2.9.1. |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 75 | if (isvalid_prop_to_ir(&ui64Type, 2)) { |
Ed Tanous | 12dbd4f | 2025-03-08 19:05:01 -0800 | [diff] [blame^] | 76 | const UINT8 *cur_pos = (const UINT8 *)(cxl_error + 1); |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 77 | int remaining_len = cxl_error->Length - |
| 78 | sizeof(EFI_CXL_COMPONENT_EVENT_HEADER); |
| 79 | if (remaining_len > 0) { |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 80 | int32_t encoded_len = 0; |
Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 81 | |
Ed Tanous | 12dbd4f | 2025-03-08 19:05:01 -0800 | [diff] [blame^] | 82 | char *encoded = base64_encode(cur_pos, remaining_len, |
| 83 | &encoded_len); |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 84 | if (encoded == NULL) { |
| 85 | printf("Failed to allocate encode output buffer. \n"); |
Ed Tanous | 12dbd4f | 2025-03-08 19:05:01 -0800 | [diff] [blame^] | 86 | json_object_put(section_ir); |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 87 | return NULL; |
| 88 | } |
Ed Tanous | 12dbd4f | 2025-03-08 19:05:01 -0800 | [diff] [blame^] | 89 | json_object *event_log = json_object_new_object(); |
| 90 | |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 91 | json_object_object_add(event_log, "data", |
| 92 | json_object_new_string_len( |
| 93 | encoded, encoded_len)); |
| 94 | |
| 95 | free(encoded); |
| 96 | json_object_object_add( |
| 97 | section_ir, "cxlComponentEventLog", event_log); |
John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 98 | } |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 99 | } |
| 100 | |
| 101 | return section_ir; |
Lawrence Tang | aec8390 | 2022-07-18 09:41:08 +0100 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | //Converts a single given CXL Component CPER-JSON section into CPER binary, outputting to the |
| 105 | //given stream. |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 106 | void ir_section_cxl_component_to_cper(json_object *section, FILE *out) |
Lawrence Tang | aec8390 | 2022-07-18 09:41:08 +0100 | [diff] [blame] | 107 | { |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 108 | EFI_CXL_COMPONENT_EVENT_HEADER *section_cper = |
| 109 | (EFI_CXL_COMPONENT_EVENT_HEADER *)calloc( |
| 110 | 1, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)); |
Lawrence Tang | aec8390 | 2022-07-18 09:41:08 +0100 | [diff] [blame] | 111 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 112 | //Length of the structure. |
| 113 | section_cper->Length = json_object_get_uint64( |
| 114 | json_object_object_get(section, "length")); |
Lawrence Tang | aec8390 | 2022-07-18 09:41:08 +0100 | [diff] [blame] | 115 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 116 | //Validation bits. |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 117 | ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 }; |
| 118 | struct json_object *obj = NULL; |
Lawrence Tang | aec8390 | 2022-07-18 09:41:08 +0100 | [diff] [blame] | 119 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 120 | //Device ID information. |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 121 | if (json_object_object_get_ex(section, "deviceID", &obj)) { |
| 122 | json_object *device_id = obj; |
| 123 | section_cper->DeviceId.VendorId = json_object_get_uint64( |
| 124 | json_object_object_get(device_id, "vendorID")); |
| 125 | section_cper->DeviceId.DeviceId = json_object_get_uint64( |
| 126 | json_object_object_get(device_id, "deviceID")); |
| 127 | section_cper->DeviceId.FunctionNumber = json_object_get_uint64( |
| 128 | json_object_object_get(device_id, "functionNumber")); |
| 129 | section_cper->DeviceId.DeviceNumber = json_object_get_uint64( |
| 130 | json_object_object_get(device_id, "deviceNumber")); |
| 131 | section_cper->DeviceId.BusNumber = json_object_get_uint64( |
| 132 | json_object_object_get(device_id, "busNumber")); |
| 133 | section_cper->DeviceId.SegmentNumber = json_object_get_uint64( |
| 134 | json_object_object_get(device_id, "segmentNumber")); |
| 135 | section_cper->DeviceId.SlotNumber = json_object_get_uint64( |
| 136 | json_object_object_get(device_id, "slotNumber")); |
| 137 | add_to_valid_bitfield(&ui64Type, 0); |
| 138 | } |
Lawrence Tang | aec8390 | 2022-07-18 09:41:08 +0100 | [diff] [blame] | 139 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 140 | //Device serial number. |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 141 | if (json_object_object_get_ex(section, "deviceSerial", &obj)) { |
| 142 | section_cper->DeviceSerial = json_object_get_uint64(obj); |
| 143 | add_to_valid_bitfield(&ui64Type, 1); |
| 144 | } |
| 145 | |
| 146 | //CXL component event log, decoded from base64. |
| 147 | json_object *event_log = NULL; |
| 148 | if (json_object_object_get_ex(section, "cxlComponentEventLog", &obj)) { |
| 149 | event_log = obj; |
| 150 | add_to_valid_bitfield(&ui64Type, 2); |
| 151 | } |
| 152 | section_cper->ValidBits = ui64Type.value.ui64; |
Lawrence Tang | aec8390 | 2022-07-18 09:41:08 +0100 | [diff] [blame] | 153 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 154 | //Write header out to stream. |
| 155 | fwrite(section_cper, sizeof(EFI_CXL_COMPONENT_EVENT_HEADER), 1, out); |
| 156 | fflush(out); |
Lawrence Tang | aec8390 | 2022-07-18 09:41:08 +0100 | [diff] [blame] | 157 | |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 158 | if (event_log != NULL) { |
| 159 | json_object *encoded = |
| 160 | json_object_object_get(event_log, "data"); |
Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 161 | |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 162 | int32_t decoded_len = 0; |
Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 163 | |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 164 | UINT8 *decoded = base64_decode( |
| 165 | json_object_get_string(encoded), |
| 166 | json_object_get_string_len(encoded), &decoded_len); |
Ed Tanous | a7d2cdd | 2024-07-15 11:07:27 -0700 | [diff] [blame] | 167 | |
Aushim Nagarkatti | ae8f6d9 | 2025-01-29 17:34:44 -0800 | [diff] [blame] | 168 | if (decoded == NULL) { |
| 169 | printf("Failed to allocate decode output buffer. \n"); |
| 170 | } else { |
| 171 | fwrite(decoded, decoded_len, 1, out); |
| 172 | fflush(out); |
| 173 | free(decoded); |
| 174 | } |
John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 175 | } |
Lawrence Tang | aec8390 | 2022-07-18 09:41:08 +0100 | [diff] [blame] | 176 | |
Lawrence Tang | e407b4c | 2022-07-21 13:54:01 +0100 | [diff] [blame] | 177 | free(section_cper); |
John Chung | f8fc705 | 2024-05-03 20:05:29 +0800 | [diff] [blame] | 178 | } |