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