blob: 88d7aad58cf95003ea98aec234f9f8a2b046d9b8 [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));
Lawrence Tang583cdee2022-07-11 14:31:11 +010034 json_object_object_add(error_status_ir, "overflowDroppedLogs", json_object_new_boolean(error_status->OverflowNotLogged));
Lawrence Tanga0865e32022-07-06 11:59:52 +010035
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.
Lawrence Tang3c878352022-07-08 14:04:50 +010070json_object* integer_to_readable_pair(UINT64 value, int len, int keys[], const char* values[], const char* default_value)
Lawrence Tang3c43f742022-07-05 11:37:17 +010071{
72 json_object* result = json_object_new_object();
Lawrence Tang3c878352022-07-08 14:04:50 +010073 json_object_object_add(result, "value", json_object_new_uint64(value));
Lawrence Tang3c43f742022-07-05 11:37:17 +010074
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
Lawrence Tange18aaee2022-07-07 09:01:30 +0100121//Converts the given UINT64 array into a JSON IR array, given the length.
122json_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}
Lawrence Tang794312c2022-07-05 14:46:10 +0100129
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100130//Converts a single UINT16 revision number into JSON IR representation.
131json_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.
140const 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.
146void 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.
163int 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;
Lawrence Tang4dbe3d72022-07-06 13:51:01 +0100181}
182
183//Converts the given BCD byte to a standard integer.
184int bcd_to_int(UINT8 bcd)
185{
186 return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F);
Lawrence Tang1b0b00e2022-07-05 10:33:10 +0100187}