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