xref: /openbmc/libcper/sections/cper-section-generic.c (revision ae8f6d9aaeaf37332e8924dd2c0b6f320335548c)
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