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