1 /**
2  * Describes functions for converting memory error CPER sections from binary and JSON format
3  * into an intermediate format.
4  *
5  * Author: Lawrence.Tang@arm.com
6  **/
7 #include <stdio.h>
8 #include "json.h"
9 #include "../edk/Cper.h"
10 #include "../cper-utils.h"
11 #include "cper-section-memory.h"
12 
13 //Converts a single memory error CPER section into JSON IR.
14 json_object* cper_section_platform_memory_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
15 {
16     EFI_PLATFORM_MEMORY_ERROR_DATA* memory_error = (EFI_PLATFORM_MEMORY_ERROR_DATA*)section;
17     json_object* section_ir = json_object_new_object();
18 
19     //Validation bitfield.
20     json_object* validation = bitfield_to_ir(memory_error->ValidFields, 22, MEMORY_ERROR_VALID_BITFIELD_NAMES);
21     json_object_object_add(section_ir, "validationBits", validation);
22 
23     //Error status.
24     json_object* error_status = cper_generic_error_status_to_ir(&memory_error->ErrorStatus);
25     json_object_object_add(section_ir, "errorStatus", error_status);
26 
27     //Bank.
28     json_object* bank = json_object_new_object();
29     if ((memory_error->ValidFields >> 5) & 0x1)
30     {
31         //Entire bank address mode.
32         json_object_object_add(bank, "value", json_object_new_uint64(memory_error->Bank));
33     }
34     else
35     {
36         //Address/group address mode.
37         json_object_object_add(bank, "address", json_object_new_uint64(memory_error->Bank & 0xFF));
38         json_object_object_add(bank, "group", json_object_new_uint64(memory_error->Bank >> 8));
39     }
40     json_object_object_add(section_ir, "bank", bank);
41 
42     //Memory error type.
43     json_object* memory_error_type = integer_to_readable_pair(memory_error->ErrorType, 16,
44         MEMORY_ERROR_TYPES_KEYS,
45         MEMORY_ERROR_TYPES_VALUES,
46         "Unknown (Reserved)");
47     json_object_object_add(section_ir, "memoryErrorType", memory_error_type);
48 
49     //"Extended" row/column indication field + misc.
50     json_object* extended = json_object_new_object();
51     json_object_object_add(extended, "rowBit16", json_object_new_boolean(memory_error->Extended & 0b1));
52     json_object_object_add(extended, "rowBit17", json_object_new_boolean((memory_error->Extended >> 1) & 0b1));
53     json_object_object_add(extended, "chipIdentification", json_object_new_int(memory_error->Extended >> 5));
54     json_object_object_add(section_ir, "extended", extended);
55 
56     //Miscellaneous numeric fields.
57     json_object_object_add(section_ir, "physicalAddress", json_object_new_uint64(memory_error->PhysicalAddress));
58     json_object_object_add(section_ir, "physicalAddressMask", json_object_new_uint64(memory_error->PhysicalAddressMask));
59     json_object_object_add(section_ir, "node", json_object_new_uint64(memory_error->Node));
60     json_object_object_add(section_ir, "card", json_object_new_uint64(memory_error->Card));
61     json_object_object_add(section_ir, "moduleRank", json_object_new_uint64(memory_error->ModuleRank));
62     json_object_object_add(section_ir, "device", json_object_new_uint64(memory_error->Device));
63     json_object_object_add(section_ir, "row", json_object_new_uint64(memory_error->Row));
64     json_object_object_add(section_ir, "column", json_object_new_uint64(memory_error->Column));
65     json_object_object_add(section_ir, "bitPosition", json_object_new_uint64(memory_error->BitPosition));
66     json_object_object_add(section_ir, "requestorID", json_object_new_uint64(memory_error->RequestorId));
67     json_object_object_add(section_ir, "responderID", json_object_new_uint64(memory_error->ResponderId));
68     json_object_object_add(section_ir, "targetID", json_object_new_uint64(memory_error->TargetId));
69     json_object_object_add(section_ir, "rankNumber", json_object_new_uint64(memory_error->RankNum));
70     json_object_object_add(section_ir, "cardSmbiosHandle", json_object_new_uint64(memory_error->CardHandle));
71     json_object_object_add(section_ir, "moduleSmbiosHandle", json_object_new_uint64(memory_error->ModuleHandle));
72 
73     return section_ir;
74 }
75 
76 //Converts a single memory error 2 CPER section into JSON IR.
77 json_object* cper_section_platform_memory2_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
78 {
79     EFI_PLATFORM_MEMORY2_ERROR_DATA* memory_error = (EFI_PLATFORM_MEMORY2_ERROR_DATA*)section;
80     json_object* section_ir = json_object_new_object();
81 
82     //Validation bits.
83     json_object* validation = bitfield_to_ir(memory_error->ValidFields, 22, MEMORY_ERROR_2_VALID_BITFIELD_NAMES);
84     json_object_object_add(section_ir, "validationBits", validation);
85 
86     //Error status.
87     json_object* error_status = cper_generic_error_status_to_ir(&memory_error->ErrorStatus);
88     json_object_object_add(section_ir, "errorStatus", error_status);
89 
90     //Bank.
91     json_object* bank = json_object_new_object();
92     if ((memory_error->ValidFields >> 5) & 0x1)
93     {
94         //Entire bank address mode.
95         json_object_object_add(bank, "value", json_object_new_uint64(memory_error->Bank));
96     }
97     else
98     {
99         //Address/group address mode.
100         json_object_object_add(bank, "address", json_object_new_uint64(memory_error->Bank & 0xFF));
101         json_object_object_add(bank, "group", json_object_new_uint64(memory_error->Bank >> 8));
102     }
103     json_object_object_add(section_ir, "bank", bank);
104 
105     //Memory error type.
106     json_object* memory_error_type = integer_to_readable_pair(memory_error->MemErrorType, 16,
107         MEMORY_ERROR_TYPES_KEYS,
108         MEMORY_ERROR_TYPES_VALUES,
109         "Unknown (Reserved)");
110     json_object_object_add(section_ir, "memoryErrorType", memory_error_type);
111 
112     //Status.
113     json_object* status = json_object_new_object();
114     json_object_object_add(status, "value", json_object_new_int(memory_error->Status));
115     json_object_object_add(status, "state", json_object_new_string(memory_error->Status & 0b1 == 0 ? "Corrected" : "Uncorrected"));
116     json_object_object_add(section_ir, "status", status);
117 
118     //Miscellaneous numeric fields.
119     json_object_object_add(section_ir, "physicalAddress", json_object_new_uint64(memory_error->PhysicalAddress));
120     json_object_object_add(section_ir, "physicalAddressMask", json_object_new_uint64(memory_error->PhysicalAddressMask));
121     json_object_object_add(section_ir, "node", json_object_new_uint64(memory_error->Node));
122     json_object_object_add(section_ir, "card", json_object_new_uint64(memory_error->Card));
123     json_object_object_add(section_ir, "module", json_object_new_uint64(memory_error->Module));
124     json_object_object_add(section_ir, "device", json_object_new_uint64(memory_error->Device));
125     json_object_object_add(section_ir, "row", json_object_new_uint64(memory_error->Row));
126     json_object_object_add(section_ir, "column", json_object_new_uint64(memory_error->Column));
127     json_object_object_add(section_ir, "rank", json_object_new_uint64(memory_error->Rank));
128     json_object_object_add(section_ir, "bitPosition", json_object_new_uint64(memory_error->BitPosition));
129     json_object_object_add(section_ir, "chipID", json_object_new_uint64(memory_error->ChipId));
130     json_object_object_add(section_ir, "requestorID", json_object_new_uint64(memory_error->RequestorId));
131     json_object_object_add(section_ir, "responderID", json_object_new_uint64(memory_error->ResponderId));
132     json_object_object_add(section_ir, "targetID", json_object_new_uint64(memory_error->TargetId));
133     json_object_object_add(section_ir, "cardSmbiosHandle", json_object_new_uint64(memory_error->CardHandle));
134     json_object_object_add(section_ir, "moduleSmbiosHandle", json_object_new_uint64(memory_error->ModuleHandle));
135 
136     return section_ir;
137 }
138 
139 //Converts a single Memory Error IR section into CPER binary, outputting to the provided stream.
140 void ir_section_memory_to_cper(json_object* section, FILE* out)
141 {
142     EFI_PLATFORM_MEMORY_ERROR_DATA* section_cper =
143         (EFI_PLATFORM_MEMORY_ERROR_DATA*)calloc(1, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA));
144 
145     //Validation bits.
146     section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"),
147         22, MEMORY_ERROR_VALID_BITFIELD_NAMES);
148 
149     //Error status.
150     ir_generic_error_status_to_cper(json_object_object_get(section, "errorStatus"), &section_cper->ErrorStatus);
151 
152     //Bank.
153     json_object* bank = json_object_object_get(section, "bank");
154     if ((section_cper->ValidFields >> 5) & 0x1)
155     {
156         //Bank just uses simple address.
157         section_cper->Bank = (UINT16)json_object_get_uint64(json_object_object_get(bank, "value"));
158     }
159     else
160     {
161         //Bank uses address/group style address.
162         UINT16 address = (UINT8)json_object_get_uint64(json_object_object_get(bank, "address"));
163         UINT16 group = (UINT8)json_object_get_uint64(json_object_object_get(bank, "group"));
164         section_cper->Bank = address + (group << 8);
165     }
166 
167     //"Extended" field.
168     json_object* extended = json_object_object_get(section, "extended");
169     section_cper->Extended = 0;
170     section_cper->Extended |= json_object_get_boolean(json_object_object_get(extended, "rowBit16"));
171     section_cper->Extended |= json_object_get_boolean(json_object_object_get(extended, "rowBit17")) << 1;
172     section_cper->Extended |= json_object_get_int(json_object_object_get(extended, "chipIdentification")) << 5;
173 
174     //Miscellaneous value fields.
175     section_cper->ErrorType = readable_pair_to_integer(json_object_object_get(section, "memoryErrorType"));
176     section_cper->PhysicalAddress = json_object_get_uint64(json_object_object_get(section, "physicalAddress"));
177     section_cper->PhysicalAddressMask = json_object_get_uint64(json_object_object_get(section, "physicalAddressMask"));
178     section_cper->Node = (UINT16)json_object_get_uint64(json_object_object_get(section, "node"));
179     section_cper->Card = (UINT16)json_object_get_uint64(json_object_object_get(section, "card"));
180     section_cper->ModuleRank = (UINT16)json_object_get_uint64(json_object_object_get(section, "moduleRank"));
181     section_cper->Device = (UINT16)json_object_get_uint64(json_object_object_get(section, "device"));
182     section_cper->Row = (UINT16)json_object_get_uint64(json_object_object_get(section, "row"));
183     section_cper->Column = (UINT16)json_object_get_uint64(json_object_object_get(section, "column"));
184     section_cper->BitPosition = (UINT16)json_object_get_uint64(json_object_object_get(section, "bitPosition"));
185     section_cper->RequestorId = json_object_get_uint64(json_object_object_get(section, "requestorID"));
186     section_cper->ResponderId = json_object_get_uint64(json_object_object_get(section, "responderID"));
187     section_cper->TargetId = json_object_get_uint64(json_object_object_get(section, "targetID"));
188     section_cper->RankNum = (UINT16)json_object_get_uint64(json_object_object_get(section, "rankNumber"));
189     section_cper->CardHandle = (UINT16)json_object_get_uint64(json_object_object_get(section, "cardSmbiosHandle"));
190     section_cper->ModuleHandle = (UINT16)json_object_get_uint64(json_object_object_get(section, "moduleSmbiosHandle"));
191 
192     //Write to stream, free up resources.
193     fwrite(&section_cper, sizeof(section_cper), 1, out);
194     fflush(out);
195     free(section_cper);
196 }
197 
198 //Converts a single Memory Error 2 IR section into CPER binary, outputting to the provided stream.
199 void ir_section_memory2_to_cper(json_object* section, FILE* out)
200 {
201     EFI_PLATFORM_MEMORY2_ERROR_DATA* section_cper =
202         (EFI_PLATFORM_MEMORY2_ERROR_DATA*)calloc(1, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA));
203 
204     //Validation bits.
205     section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"),
206         22, MEMORY_ERROR_2_VALID_BITFIELD_NAMES);
207 
208     //Error status.
209     ir_generic_error_status_to_cper(json_object_object_get(section, "errorStatus"), &section_cper->ErrorStatus);
210 
211     //Bank.
212     json_object* bank = json_object_object_get(section, "bank");
213     if ((section_cper->ValidFields >> 5) & 0x1)
214     {
215         //Bank just uses simple address.
216         section_cper->Bank = (UINT16)json_object_get_uint64(json_object_object_get(bank, "value"));
217     }
218     else
219     {
220         //Bank uses address/group style address.
221         UINT16 address = (UINT8)json_object_get_uint64(json_object_object_get(bank, "address"));
222         UINT16 group = (UINT8)json_object_get_uint64(json_object_object_get(bank, "group"));
223         section_cper->Bank = address + (group << 8);
224     }
225 
226     //Miscellaneous value fields.
227     section_cper->MemErrorType = readable_pair_to_integer(json_object_object_get(section, "memoryErrorType"));
228     section_cper->Status = (UINT8)readable_pair_to_integer(json_object_object_get(section, "status"));
229     section_cper->PhysicalAddress = json_object_get_uint64(json_object_object_get(section, "physicalAddress"));
230     section_cper->PhysicalAddressMask = json_object_get_uint64(json_object_object_get(section, "physicalAddressMask"));
231     section_cper->Node = (UINT16)json_object_get_uint64(json_object_object_get(section, "node"));
232     section_cper->Card = (UINT16)json_object_get_uint64(json_object_object_get(section, "card"));
233     section_cper->Module = (UINT32)json_object_get_uint64(json_object_object_get(section, "module"));
234     section_cper->Device = (UINT32)json_object_get_uint64(json_object_object_get(section, "device"));
235     section_cper->Row = (UINT32)json_object_get_uint64(json_object_object_get(section, "row"));
236     section_cper->Column = (UINT32)json_object_get_uint64(json_object_object_get(section, "column"));
237     section_cper->Rank = (UINT32)json_object_get_uint64(json_object_object_get(section, "rank"));
238     section_cper->BitPosition = (UINT32)json_object_get_uint64(json_object_object_get(section, "bitPosition"));
239     section_cper->ChipId = (UINT8)json_object_get_uint64(json_object_object_get(section, "chipID"));
240     section_cper->RequestorId = json_object_get_uint64(json_object_object_get(section, "requestorID"));
241     section_cper->ResponderId = json_object_get_uint64(json_object_object_get(section, "responderID"));
242     section_cper->TargetId = json_object_get_uint64(json_object_object_get(section, "targetID"));
243     section_cper->CardHandle = (UINT32)json_object_get_uint64(json_object_object_get(section, "cardSmbiosHandle"));
244     section_cper->ModuleHandle = (UINT32)json_object_get_uint64(json_object_object_get(section, "moduleSmbiosHandle"));
245 
246     //Write to stream, free up resources.
247     fwrite(&section_cper, sizeof(section_cper), 1, out);
248     fflush(out);
249     free(section_cper);
250 }