blob: e0823b29b264d8538f01ce181b294bd1d686c1ba [file] [log] [blame]
Lawrence Tang1b0b00e2022-07-05 10:33:10 +01001/**
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.
13const char* CPER_SEVERITY_TYPES[4] = {"Recoverable", "Fatal", "Corrected", "Informational"};
14
Lawrence Tanga0865e32022-07-06 11:59:52 +010015//Converts the given generic CPER error status to JSON IR.
16json_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
Lawrence Tang7f21db62022-07-06 11:09:39 +010039//Converts a single uniform struct of UINT64s into intermediate JSON IR format, given names for each field in byte order.
40json_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.
55json_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
Lawrence Tang3c43f742022-07-05 11:37:17 +010069//Converts a single integer value to an object containing a value, and a readable name if possible.
70json_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.
Lawrence Tang794312c2022-07-05 14:46:10 +010076 const char* name = default_value;
Lawrence Tang3c43f742022-07-05 11:37:17 +010077 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
Lawrence Tang7f21db62022-07-06 11:09:39 +010087//Converts a single integer value to an object containing a value, readable name and description if possible.
88json_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
Lawrence Tang794312c2022-07-05 14:46:10 +0100109//Converts the given 64 bit bitfield to IR, assuming bit 0 starts on the left.
Lawrence Tang3d0e4f22022-07-05 17:17:41 +0100110json_object* bitfield_to_ir(UINT64 bitfield, int num_fields, const char* names[])
Lawrence Tang794312c2022-07-05 14:46:10 +0100111{
112 json_object* result = json_object_new_object();
113 for (int i=0; i<num_fields; i++)
114 {
Lawrence Tang2800cd82022-07-05 16:08:20 +0100115 json_object_object_add(result, names[i], json_object_new_boolean((bitfield >> i) & 0b1));
Lawrence Tang794312c2022-07-05 14:46:10 +0100116 }
117
118 return result;
119}
120
121
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100122//Converts a single UINT16 revision number into JSON IR representation.
123json_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.
132const 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.
138void 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.
155int 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;
Lawrence Tang4dbe3d72022-07-06 13:51:01 +0100173}
174
175//Converts the given BCD byte to a standard integer.
176int bcd_to_int(UINT8 bcd)
177{
178 return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100179}