1 /**
2 * Describes functions for converting processor-generic CPER sections from binary and JSON format
3 * into an intermediate format.
4 *
5 * Author: Lawrence.Tang@arm.com
6 **/
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <json.h>
11 #include <libcper/Cper.h>
12 #include <libcper/cper-utils.h>
13 #include <libcper/sections/cper-section-generic.h>
14 #include <libcper/log.h>
15 #include <string.h>
16
17 //Converts the given processor-generic CPER section into JSON IR.
cper_section_generic_to_ir(const UINT8 * section,UINT32 size,char ** desc_string)18 json_object *cper_section_generic_to_ir(const UINT8 *section, UINT32 size,
19 char **desc_string)
20 {
21 int outstr_len = 0;
22
23 *desc_string = NULL;
24 if (size < sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA)) {
25 cper_print_log("Error: Generic Processor section too small\n");
26 return NULL;
27 }
28
29 *desc_string = calloc(1, SECTION_DESC_STRING_SIZE);
30 if (*desc_string == NULL) {
31 cper_print_log(
32 "Error: Failed to allocate Generic Processor desc string\n");
33 return NULL;
34 }
35 outstr_len = snprintf(*desc_string, SECTION_DESC_STRING_SIZE,
36 "A Generic Processor Error occurred");
37 if (outstr_len < 0) {
38 cper_print_log(
39 "Error: Could not write to Generic description string\n");
40 } else if (outstr_len > SECTION_DESC_STRING_SIZE) {
41 cper_print_log("Error: Generic description string truncated\n");
42 }
43
44 EFI_PROCESSOR_GENERIC_ERROR_DATA *section_generic =
45 (EFI_PROCESSOR_GENERIC_ERROR_DATA *)section;
46 json_object *section_ir = json_object_new_object();
47
48 ValidationTypes ui64Type = {
49 UINT_64T, .value.ui64 = section_generic->ValidFields
50 };
51
52 if (isvalid_prop_to_ir(&ui64Type, 0)) {
53 //Processor type, with human readable name if possible.
54 json_object *processor_type = integer_to_readable_pair(
55 section_generic->Type,
56 sizeof(GENERIC_PROC_TYPES_KEYS) / sizeof(int),
57 GENERIC_PROC_TYPES_KEYS, GENERIC_PROC_TYPES_VALUES,
58 "Unknown (Reserved)");
59 json_object_object_add(section_ir, "processorType",
60 processor_type);
61 }
62
63 if (isvalid_prop_to_ir(&ui64Type, 1)) {
64 //Processor ISA, with human readable name if possible.
65 json_object *processor_isa = integer_to_readable_pair(
66 section_generic->Isa,
67 sizeof(GENERIC_ISA_TYPES_KEYS) / sizeof(int),
68 GENERIC_ISA_TYPES_KEYS, GENERIC_ISA_TYPES_VALUES,
69 "Unknown (Reserved)");
70 json_object_object_add(section_ir, "processorISA",
71 processor_isa);
72 }
73
74 if (isvalid_prop_to_ir(&ui64Type, 2)) {
75 //Processor error type, with human readable name if possible.
76 json_object *processor_error_type = integer_to_readable_pair(
77 section_generic->ErrorType,
78 sizeof(GENERIC_ERROR_TYPES_KEYS) / sizeof(int),
79 GENERIC_ERROR_TYPES_KEYS, GENERIC_ERROR_TYPES_VALUES,
80 "Unknown (Reserved)");
81 json_object_object_add(section_ir, "errorType",
82 processor_error_type);
83 }
84
85 if (isvalid_prop_to_ir(&ui64Type, 3)) {
86 //The operation performed, with a human readable name if possible.
87 json_object *operation = integer_to_readable_pair(
88 section_generic->Operation,
89 sizeof(GENERIC_OPERATION_TYPES_KEYS) / sizeof(int),
90 GENERIC_OPERATION_TYPES_KEYS,
91 GENERIC_OPERATION_TYPES_VALUES, "Unknown (Reserved)");
92 json_object_object_add(section_ir, "operation", operation);
93 }
94
95 if (isvalid_prop_to_ir(&ui64Type, 4)) {
96 //Flags, additional information about the error.
97 json_object *flags =
98 bitfield_to_ir(section_generic->Flags, 4,
99 GENERIC_FLAGS_BITFIELD_NAMES);
100 json_object_object_add(section_ir, "flags", flags);
101 }
102
103 if (isvalid_prop_to_ir(&ui64Type, 5)) {
104 //The level of the error.
105 json_object_object_add(
106 section_ir, "level",
107 json_object_new_int(section_generic->Level));
108 }
109
110 if (isvalid_prop_to_ir(&ui64Type, 6)) {
111 //CPU version information.
112 json_object_object_add(
113 section_ir, "cpuVersionInfo",
114 json_object_new_uint64(section_generic->VersionInfo));
115 }
116
117 if (isvalid_prop_to_ir(&ui64Type, 7)) {
118 //CPU brand string. May not exist if on ARM.
119 add_untrusted_string(section_ir, "cpuBrandString",
120 section_generic->BrandString,
121 sizeof(section_generic->BrandString));
122 }
123
124 if (isvalid_prop_to_ir(&ui64Type, 8)) {
125 //Remaining 64-bit fields.
126 json_object_object_add(
127 section_ir, "processorID",
128 json_object_new_uint64(section_generic->ApicId));
129 }
130
131 if (isvalid_prop_to_ir(&ui64Type, 9)) {
132 json_object_object_add(
133 section_ir, "targetAddress",
134 json_object_new_uint64(section_generic->TargetAddr));
135 }
136
137 if (isvalid_prop_to_ir(&ui64Type, 10)) {
138 json_object_object_add(
139 section_ir, "requestorID",
140 json_object_new_uint64(section_generic->RequestorId));
141 }
142
143 if (isvalid_prop_to_ir(&ui64Type, 11)) {
144 json_object_object_add(
145 section_ir, "responderID",
146 json_object_new_uint64(section_generic->ResponderId));
147 }
148
149 if (isvalid_prop_to_ir(&ui64Type, 12)) {
150 json_object_object_add(
151 section_ir, "instructionIP",
152 json_object_new_uint64(section_generic->InstructionIP));
153 }
154
155 return section_ir;
156 }
157
158 //Converts the given CPER-JSON processor-generic error section into CPER binary,
159 //outputting to the provided stream.
ir_section_generic_to_cper(json_object * section,FILE * out)160 void ir_section_generic_to_cper(json_object *section, FILE *out)
161 {
162 EFI_PROCESSOR_GENERIC_ERROR_DATA *section_cper =
163 (EFI_PROCESSOR_GENERIC_ERROR_DATA *)calloc(
164 1, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA));
165
166 //Validation bits.
167 //Remove
168 // section_cper->ValidFields = ir_to_bitfield(
169 // json_object_object_get(section, "validationBits"), 13,
170 // GENERIC_VALIDATION_BITFIELD_NAMES);
171 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 };
172 struct json_object *obj = NULL;
173 //Various name/value pair fields.
174 if (json_object_object_get_ex(section, "processorType", &obj)) {
175 section_cper->Type = (UINT8)readable_pair_to_integer(obj);
176 add_to_valid_bitfield(&ui64Type, 0);
177 }
178 if (json_object_object_get_ex(section, "processorISA", &obj)) {
179 section_cper->Isa = (UINT8)readable_pair_to_integer(obj);
180 add_to_valid_bitfield(&ui64Type, 1);
181 }
182 if (json_object_object_get_ex(section, "errorType", &obj)) {
183 section_cper->ErrorType = (UINT8)readable_pair_to_integer(obj);
184 add_to_valid_bitfield(&ui64Type, 2);
185 }
186 if (json_object_object_get_ex(section, "operation", &obj)) {
187 section_cper->Operation = (UINT8)readable_pair_to_integer(obj);
188 add_to_valid_bitfield(&ui64Type, 3);
189 }
190 //Flags.
191 if (json_object_object_get_ex(section, "flags", &obj)) {
192 section_cper->Flags = (UINT8)ir_to_bitfield(
193 obj, 4, GENERIC_FLAGS_BITFIELD_NAMES);
194 add_to_valid_bitfield(&ui64Type, 4);
195 }
196
197 //Various numeric/string fields.
198 if (json_object_object_get_ex(section, "level", &obj)) {
199 section_cper->Level = (UINT8)json_object_get_int(obj);
200 add_to_valid_bitfield(&ui64Type, 5);
201 }
202 if (json_object_object_get_ex(section, "cpuVersionInfo", &obj)) {
203 section_cper->VersionInfo = json_object_get_uint64(obj);
204 add_to_valid_bitfield(&ui64Type, 6);
205 }
206 if (json_object_object_get_ex(section, "processorID", &obj)) {
207 section_cper->ApicId = json_object_get_uint64(obj);
208 add_to_valid_bitfield(&ui64Type, 8);
209 }
210 if (json_object_object_get_ex(section, "targetAddress", &obj)) {
211 section_cper->TargetAddr = json_object_get_uint64(obj);
212 add_to_valid_bitfield(&ui64Type, 9);
213 }
214 if (json_object_object_get_ex(section, "requestorID", &obj)) {
215 section_cper->RequestorId = json_object_get_uint64(obj);
216 add_to_valid_bitfield(&ui64Type, 10);
217 }
218 if (json_object_object_get_ex(section, "responderID", &obj)) {
219 section_cper->ResponderId = json_object_get_uint64(obj);
220 add_to_valid_bitfield(&ui64Type, 11);
221 }
222 if (json_object_object_get_ex(section, "instructionIP", &obj)) {
223 section_cper->InstructionIP = json_object_get_uint64(obj);
224 add_to_valid_bitfield(&ui64Type, 12);
225 }
226
227 //CPU brand string.
228 if (json_object_object_get_ex(section, "cpuBrandString", &obj)) {
229 const char *brand_string = json_object_get_string(obj);
230 if (brand_string != NULL) {
231 strncpy(section_cper->BrandString, brand_string,
232 sizeof(section_cper->BrandString) - 1);
233 section_cper
234 ->BrandString[sizeof(section_cper->BrandString) -
235 1] = '\0';
236 }
237 add_to_valid_bitfield(&ui64Type, 7);
238 }
239 section_cper->ValidFields = ui64Type.value.ui64;
240
241 //Write & flush out to file, free memory.
242 fwrite(section_cper, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA), 1, out);
243 fflush(out);
244 free(section_cper);
245 }
246