xref: /openbmc/libcper/cper-utils.c (revision 3c878352)
1 /**
2  * Describes utility functions for parsing CPER into JSON IR.
3  *
4  * Author: Lawrence.Tang@arm.com
5  **/
6 
7 #include <stdio.h>
8 #include "json.h"
9 #include "edk/Cper.h"
10 #include "cper-utils.h"
11 
12 //The available severity types for CPER.
13 const char* CPER_SEVERITY_TYPES[4] = {"Recoverable", "Fatal", "Corrected", "Informational"};
14 
15 //Converts the given generic CPER error status to JSON IR.
16 json_object* cper_generic_error_status_to_ir(EFI_GENERIC_ERROR_STATUS* error_status)
17 {
18     json_object* error_status_ir = json_object_new_object();
19 
20     //Error type.
21     json_object_object_add(error_status_ir, "errorType", integer_to_readable_pair_with_desc(error_status->Type, 18,
22         CPER_GENERIC_ERROR_TYPES_KEYS,
23         CPER_GENERIC_ERROR_TYPES_VALUES,
24         CPER_GENERIC_ERROR_TYPES_DESCRIPTIONS,
25         "Unknown (Reserved)"));
26 
27     //Boolean bit fields.
28     json_object_object_add(error_status_ir, "addressSignal", json_object_new_boolean(error_status->AddressSignal));
29     json_object_object_add(error_status_ir, "controlSignal", json_object_new_boolean(error_status->ControlSignal));
30     json_object_object_add(error_status_ir, "dataSignal", json_object_new_boolean(error_status->DataSignal));
31     json_object_object_add(error_status_ir, "detectedByResponder", json_object_new_boolean(error_status->DetectedByResponder));
32     json_object_object_add(error_status_ir, "detectedByRequester", json_object_new_boolean(error_status->DetectedByRequester));
33     json_object_object_add(error_status_ir, "firstError", json_object_new_boolean(error_status->FirstError));
34     json_object_object_add(error_status_ir, "overflowNotLogged", json_object_new_boolean(error_status->OverflowNotLogged));
35 
36     return error_status_ir;
37 }
38 
39 //Converts a single uniform struct of UINT64s into intermediate JSON IR format, given names for each field in byte order.
40 json_object* uniform_struct64_to_ir(UINT64* start, int len, const char* names[])
41 {
42     json_object* result = json_object_new_object();
43 
44     UINT64* cur = start;
45     for (int i=0; i<len; i++)
46     {
47         json_object_object_add(result, names[i], json_object_new_uint64(*cur));
48         cur++;
49     }
50 
51     return result;
52 }
53 
54 //Converts a single uniform struct of UINT32s into intermediate JSON IR format, given names for each field in byte order.
55 json_object* uniform_struct_to_ir(UINT32* start, int len, const char* names[])
56 {
57     json_object* result = json_object_new_object();
58 
59     UINT32* cur = start;
60     for (int i=0; i<len; i++)
61     {
62         json_object_object_add(result, names[i], json_object_new_uint64(*cur));
63         cur++;
64     }
65 
66     return result;
67 }
68 
69 //Converts a single integer value to an object containing a value, and a readable name if possible.
70 json_object* integer_to_readable_pair(UINT64 value, int len, int keys[], const char* values[], const char* default_value)
71 {
72     json_object* result = json_object_new_object();
73     json_object_object_add(result, "value", json_object_new_uint64(value));
74 
75     //Search for human readable name, add.
76     const char* name = default_value;
77     for (int i=0; i<len; i++)
78     {
79         if (keys[i] == value)
80             name = values[i];
81     }
82 
83     json_object_object_add(result, "name", json_object_new_string(name));
84     return result;
85 }
86 
87 //Converts a single integer value to an object containing a value, readable name and description if possible.
88 json_object* integer_to_readable_pair_with_desc(int value, int len, int keys[], const char* values[],
89     const char* descriptions[], const char* default_value)
90 {
91     json_object* result = json_object_new_object();
92     json_object_object_add(result, "value", json_object_new_int(value));
93 
94     //Search for human readable name, add.
95     const char* name = default_value;
96     for (int i=0; i<len; i++)
97     {
98         if (keys[i] == value)
99         {
100             name = values[i];
101             json_object_object_add(result, "description", json_object_new_string(descriptions[i]));
102         }
103     }
104 
105     json_object_object_add(result, "name", json_object_new_string(name));
106     return result;
107 }
108 
109 //Converts the given 64 bit bitfield to IR, assuming bit 0 starts on the left.
110 json_object* bitfield_to_ir(UINT64 bitfield, int num_fields, const char* names[])
111 {
112     json_object* result = json_object_new_object();
113     for (int i=0; i<num_fields; i++)
114     {
115         json_object_object_add(result, names[i], json_object_new_boolean((bitfield >> i) & 0b1));
116     }
117 
118     return result;
119 }
120 
121 //Converts the given UINT64 array into a JSON IR array, given the length.
122 json_object* uint64_array_to_ir_array(UINT64* array, int len)
123 {
124     json_object* array_ir = json_object_new_array();
125     for (int i=0; i<len; i++)
126         json_object_array_add(array_ir, json_object_new_uint64(array[i]));
127     return array_ir;
128 }
129 
130 //Converts a single UINT16 revision number into JSON IR representation.
131 json_object* revision_to_ir(UINT16 revision)
132 {
133     json_object* revision_info = json_object_new_object();
134     json_object_object_add(revision_info, "major", json_object_new_int(revision >> 8));
135     json_object_object_add(revision_info, "minor", json_object_new_int(revision & 0xFF));
136     return revision_info;
137 }
138 
139 //Returns the appropriate string for the given integer severity.
140 const char* severity_to_string(UINT8 severity)
141 {
142     return severity < 4 ? CPER_SEVERITY_TYPES[severity] : "Unknown";
143 }
144 
145 //Helper function to convert an EDK EFI GUID into a string for intermediate use.
146 void guid_to_string(char* out, EFI_GUID* guid)
147 {
148     sprintf(out, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
149         guid->Data1,
150         guid->Data2,
151         guid->Data3,
152         guid->Data4[0],
153         guid->Data4[1],
154         guid->Data4[2],
155         guid->Data4[3],
156         guid->Data4[4],
157         guid->Data4[5],
158         guid->Data4[6],
159         guid->Data4[7]);
160 }
161 
162 //Returns one if two EFI GUIDs are equal, zero otherwise.
163 int guid_equal(EFI_GUID* a, EFI_GUID* b)
164 {
165     //Check top base 3 components.
166     if (a->Data1 != b->Data1
167         || a->Data2 != b->Data2
168         || a->Data3 != b->Data3)
169     {
170         return 0;
171     }
172 
173     //Check Data4 array for equality.
174     for (int i=0; i<8; i++)
175     {
176         if (a->Data4[i] != b->Data4[i])
177             return 0;
178     }
179 
180     return 1;
181 }
182 
183 //Converts the given BCD byte to a standard integer.
184 int bcd_to_int(UINT8 bcd)
185 {
186     return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F);
187 }