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 "../edk/Cper.h"
12 #include "../cper-utils.h"
13 #include "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 	//Validation bits.
23 	json_object *validation =
24 		bitfield_to_ir(section_generic->ValidFields, 13,
25 			       GENERIC_VALIDATION_BITFIELD_NAMES);
26 	json_object_object_add(section_ir, "validationBits", validation);
27 
28 	//Processor type, with human readable name if possible.
29 	json_object *processor_type = integer_to_readable_pair(
30 		section_generic->Type,
31 		sizeof(GENERIC_PROC_TYPES_KEYS) / sizeof(int),
32 		GENERIC_PROC_TYPES_KEYS, GENERIC_PROC_TYPES_VALUES,
33 		"Unknown (Reserved)");
34 	json_object_object_add(section_ir, "processorType", processor_type);
35 
36 	//Processor ISA, with human readable name if possible.
37 	json_object *processor_isa = integer_to_readable_pair(
38 		section_generic->Isa,
39 		sizeof(GENERIC_ISA_TYPES_KEYS) / sizeof(int),
40 		GENERIC_ISA_TYPES_KEYS, GENERIC_ISA_TYPES_VALUES,
41 		"Unknown (Reserved)");
42 	json_object_object_add(section_ir, "processorISA", processor_isa);
43 
44 	//Processor error type, with human readable name if possible.
45 	json_object *processor_error_type = integer_to_readable_pair(
46 		section_generic->ErrorType,
47 		sizeof(GENERIC_ERROR_TYPES_KEYS) / sizeof(int),
48 		GENERIC_ERROR_TYPES_KEYS, GENERIC_ERROR_TYPES_VALUES,
49 		"Unknown (Reserved)");
50 	json_object_object_add(section_ir, "errorType", processor_error_type);
51 
52 	//The operation performed, with a human readable name if possible.
53 	json_object *operation = integer_to_readable_pair(
54 		section_generic->Operation,
55 		sizeof(GENERIC_OPERATION_TYPES_KEYS) / sizeof(int),
56 		GENERIC_OPERATION_TYPES_KEYS, GENERIC_OPERATION_TYPES_VALUES,
57 		"Unknown (Reserved)");
58 	json_object_object_add(section_ir, "operation", operation);
59 
60 	//Flags, additional information about the error.
61 	json_object *flags = bitfield_to_ir(section_generic->Flags, 4,
62 					    GENERIC_FLAGS_BITFIELD_NAMES);
63 	json_object_object_add(section_ir, "flags", flags);
64 
65 	//The level of the error.
66 	json_object_object_add(section_ir, "level",
67 			       json_object_new_int(section_generic->Level));
68 
69 	//CPU version information.
70 	json_object_object_add(
71 		section_ir, "cpuVersionInfo",
72 		json_object_new_uint64(section_generic->VersionInfo));
73 
74 	//CPU brand string. May not exist if on ARM.
75 	json_object_object_add(
76 		section_ir, "cpuBrandString",
77 		json_object_new_string(section_generic->BrandString));
78 
79 	//Remaining 64-bit fields.
80 	json_object_object_add(section_ir, "processorID",
81 			       json_object_new_uint64(section_generic->ApicId));
82 	json_object_object_add(
83 		section_ir, "targetAddress",
84 		json_object_new_uint64(section_generic->TargetAddr));
85 	json_object_object_add(
86 		section_ir, "requestorID",
87 		json_object_new_uint64(section_generic->RequestorId));
88 	json_object_object_add(
89 		section_ir, "responderID",
90 		json_object_new_uint64(section_generic->ResponderId));
91 	json_object_object_add(
92 		section_ir, "instructionIP",
93 		json_object_new_uint64(section_generic->InstructionIP));
94 
95 	return section_ir;
96 }
97 
98 //Converts the given CPER-JSON processor-generic error section into CPER binary,
99 //outputting to the provided stream.
ir_section_generic_to_cper(json_object * section,FILE * out)100 void ir_section_generic_to_cper(json_object *section, FILE *out)
101 {
102 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_cper =
103 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)calloc(
104 			1, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA));
105 
106 	//Validation bits.
107 	section_cper->ValidFields = ir_to_bitfield(
108 		json_object_object_get(section, "validationBits"), 13,
109 		GENERIC_VALIDATION_BITFIELD_NAMES);
110 
111 	//Various name/value pair fields.
112 	section_cper->Type = (UINT8)readable_pair_to_integer(
113 		json_object_object_get(section, "processorType"));
114 	section_cper->Isa = (UINT8)readable_pair_to_integer(
115 		json_object_object_get(section, "processorISA"));
116 	section_cper->ErrorType = (UINT8)readable_pair_to_integer(
117 		json_object_object_get(section, "errorType"));
118 	section_cper->Operation = (UINT8)readable_pair_to_integer(
119 		json_object_object_get(section, "operation"));
120 
121 	//Flags.
122 	section_cper->Flags =
123 		(UINT8)ir_to_bitfield(json_object_object_get(section, "flags"),
124 				      4, GENERIC_FLAGS_BITFIELD_NAMES);
125 
126 	//Various numeric/string fields.
127 	section_cper->Level = (UINT8)json_object_get_int(
128 		json_object_object_get(section, "level"));
129 	section_cper->VersionInfo = json_object_get_uint64(
130 		json_object_object_get(section, "cpuVersionInfo"));
131 	section_cper->ApicId = json_object_get_uint64(
132 		json_object_object_get(section, "processorID"));
133 	section_cper->TargetAddr = json_object_get_uint64(
134 		json_object_object_get(section, "targetAddress"));
135 	section_cper->RequestorId = json_object_get_uint64(
136 		json_object_object_get(section, "requestorID"));
137 	section_cper->ResponderId = json_object_get_uint64(
138 		json_object_object_get(section, "responderID"));
139 	section_cper->InstructionIP = json_object_get_uint64(
140 		json_object_object_get(section, "instructionIP"));
141 
142 	//CPU brand string.
143 	const char *brand_string = json_object_get_string(
144 		json_object_object_get(section, "cpuBrandString"));
145 	if (brand_string != NULL) {
146 		strncpy(section_cper->BrandString, brand_string,
147 			sizeof(section_cper->BrandString) - 1);
148 		section_cper
149 			->BrandString[sizeof(section_cper->BrandString) - 1] =
150 			'\0';
151 	}
152 
153 	//Write & flush out to file, free memory.
154 	fwrite(section_cper, sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA), 1, out);
155 	fflush(out);
156 	free(section_cper);
157 }
158