xref: /openbmc/libcper/cper-utils.c (revision 4dbe3d72)
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(int 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_int(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 
122 //Converts a single UINT16 revision number into JSON IR representation.
123 json_object* revision_to_ir(UINT16 revision)
124 {
125     json_object* revision_info = json_object_new_object();
126     json_object_object_add(revision_info, "major", json_object_new_int(revision >> 8));
127     json_object_object_add(revision_info, "minor", json_object_new_int(revision & 0xFF));
128     return revision_info;
129 }
130 
131 //Returns the appropriate string for the given integer severity.
132 const char* severity_to_string(UINT8 severity)
133 {
134     return severity < 4 ? CPER_SEVERITY_TYPES[severity] : "Unknown";
135 }
136 
137 //Helper function to convert an EDK EFI GUID into a string for intermediate use.
138 void guid_to_string(char* out, EFI_GUID* guid)
139 {
140     sprintf(out, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
141         guid->Data1,
142         guid->Data2,
143         guid->Data3,
144         guid->Data4[0],
145         guid->Data4[1],
146         guid->Data4[2],
147         guid->Data4[3],
148         guid->Data4[4],
149         guid->Data4[5],
150         guid->Data4[6],
151         guid->Data4[7]);
152 }
153 
154 //Returns one if two EFI GUIDs are equal, zero otherwise.
155 int guid_equal(EFI_GUID* a, EFI_GUID* b)
156 {
157     //Check top base 3 components.
158     if (a->Data1 != b->Data1
159         || a->Data2 != b->Data2
160         || a->Data3 != b->Data3)
161     {
162         return 0;
163     }
164 
165     //Check Data4 array for equality.
166     for (int i=0; i<8; i++)
167     {
168         if (a->Data4[i] != b->Data4[i])
169             return 0;
170     }
171 
172     return 1;
173 }
174 
175 //Converts the given BCD byte to a standard integer.
176 int bcd_to_int(UINT8 bcd)
177 {
178     return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F);
179 }