17f21db6cSLawrence Tang /**
27f21db6cSLawrence Tang  * Describes functions for converting memory error CPER sections from binary and JSON format
37f21db6cSLawrence Tang  * into an intermediate format.
47f21db6cSLawrence Tang  *
57f21db6cSLawrence Tang  * Author: Lawrence.Tang@arm.com
67f21db6cSLawrence Tang  **/
77f21db6cSLawrence Tang #include <stdio.h>
87f21db6cSLawrence Tang #include "json.h"
97f21db6cSLawrence Tang #include "../edk/Cper.h"
107f21db6cSLawrence Tang #include "../cper-utils.h"
117f21db6cSLawrence Tang #include "cper-section-memory.h"
127f21db6cSLawrence Tang 
137f21db6cSLawrence Tang //Converts a single memory error CPER section into JSON IR.
14a0865e38SLawrence Tang json_object* cper_section_platform_memory_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
157f21db6cSLawrence Tang {
167f21db6cSLawrence Tang     EFI_PLATFORM_MEMORY_ERROR_DATA* memory_error = (EFI_PLATFORM_MEMORY_ERROR_DATA*)section;
177f21db6cSLawrence Tang     json_object* section_ir = json_object_new_object();
187f21db6cSLawrence Tang 
197f21db6cSLawrence Tang     //Validation bitfield.
207f21db6cSLawrence Tang     json_object* validation = bitfield_to_ir(memory_error->ValidFields, 22, MEMORY_ERROR_VALID_BITFIELD_NAMES);
217f21db6cSLawrence Tang     json_object_object_add(section_ir, "validationBits", validation);
227f21db6cSLawrence Tang 
237f21db6cSLawrence Tang     //Error status.
24a0865e38SLawrence Tang     json_object* error_status = cper_generic_error_status_to_ir(&memory_error->ErrorStatus);
25a0865e38SLawrence Tang     json_object_object_add(section_ir, "errorStatus", error_status);
26a0865e38SLawrence Tang 
27a0865e38SLawrence Tang     //Bank.
28a0865e38SLawrence Tang     json_object* bank = json_object_new_object();
29583cdeeeSLawrence Tang     if ((memory_error->ValidFields >> 5) & 0x1)
30583cdeeeSLawrence Tang     {
31583cdeeeSLawrence Tang         //Entire bank address mode.
32583cdeeeSLawrence Tang         json_object_object_add(bank, "value", json_object_new_uint64(memory_error->Bank));
33583cdeeeSLawrence Tang     }
34583cdeeeSLawrence Tang     else
35583cdeeeSLawrence Tang     {
36583cdeeeSLawrence Tang         //Address/group address mode.
37a0865e38SLawrence Tang         json_object_object_add(bank, "address", json_object_new_uint64(memory_error->Bank & 0xFF));
38a0865e38SLawrence Tang         json_object_object_add(bank, "group", json_object_new_uint64(memory_error->Bank >> 8));
39583cdeeeSLawrence Tang     }
40a0865e38SLawrence Tang     json_object_object_add(section_ir, "bank", bank);
41a0865e38SLawrence Tang 
42a0865e38SLawrence Tang     //Memory error type.
43a0865e38SLawrence Tang     json_object* memory_error_type = integer_to_readable_pair(memory_error->ErrorType, 16,
44a0865e38SLawrence Tang         MEMORY_ERROR_TYPES_KEYS,
45a0865e38SLawrence Tang         MEMORY_ERROR_TYPES_VALUES,
46a0865e38SLawrence Tang         "Unknown (Reserved)");
47a0865e38SLawrence Tang     json_object_object_add(section_ir, "memoryErrorType", memory_error_type);
48a0865e38SLawrence Tang 
49a0865e38SLawrence Tang     //"Extended" row/column indication field + misc.
50a0865e38SLawrence Tang     json_object* extended = json_object_new_object();
51a0865e38SLawrence Tang     json_object_object_add(extended, "rowBit16", json_object_new_boolean(memory_error->Extended & 0b1));
52a0865e38SLawrence Tang     json_object_object_add(extended, "rowBit17", json_object_new_boolean((memory_error->Extended >> 1) & 0b1));
53a0865e38SLawrence Tang     json_object_object_add(extended, "chipIdentification", json_object_new_int(memory_error->Extended >> 5));
54a0865e38SLawrence Tang     json_object_object_add(section_ir, "extended", extended);
55a0865e38SLawrence Tang 
5654da4414SLawrence Tang     //Miscellaneous numeric fields.
5754da4414SLawrence Tang     json_object_object_add(section_ir, "physicalAddress", json_object_new_uint64(memory_error->PhysicalAddress));
5854da4414SLawrence Tang     json_object_object_add(section_ir, "physicalAddressMask", json_object_new_uint64(memory_error->PhysicalAddressMask));
5954da4414SLawrence Tang     json_object_object_add(section_ir, "node", json_object_new_uint64(memory_error->Node));
6054da4414SLawrence Tang     json_object_object_add(section_ir, "card", json_object_new_uint64(memory_error->Card));
6154da4414SLawrence Tang     json_object_object_add(section_ir, "moduleRank", json_object_new_uint64(memory_error->ModuleRank));
6254da4414SLawrence Tang     json_object_object_add(section_ir, "device", json_object_new_uint64(memory_error->Device));
6354da4414SLawrence Tang     json_object_object_add(section_ir, "row", json_object_new_uint64(memory_error->Row));
6454da4414SLawrence Tang     json_object_object_add(section_ir, "column", json_object_new_uint64(memory_error->Column));
6554da4414SLawrence Tang     json_object_object_add(section_ir, "bitPosition", json_object_new_uint64(memory_error->BitPosition));
6654da4414SLawrence Tang     json_object_object_add(section_ir, "requestorID", json_object_new_uint64(memory_error->RequestorId));
6754da4414SLawrence Tang     json_object_object_add(section_ir, "responderID", json_object_new_uint64(memory_error->ResponderId));
6854da4414SLawrence Tang     json_object_object_add(section_ir, "targetID", json_object_new_uint64(memory_error->TargetId));
6954da4414SLawrence Tang     json_object_object_add(section_ir, "rankNumber", json_object_new_uint64(memory_error->RankNum));
7054da4414SLawrence Tang     json_object_object_add(section_ir, "cardSmbiosHandle", json_object_new_uint64(memory_error->CardHandle));
7154da4414SLawrence Tang     json_object_object_add(section_ir, "moduleSmbiosHandle", json_object_new_uint64(memory_error->ModuleHandle));
7254da4414SLawrence Tang 
73a0865e38SLawrence Tang     return section_ir;
74a0865e38SLawrence Tang }
75a0865e38SLawrence Tang 
76a0865e38SLawrence Tang //Converts a single memory error 2 CPER section into JSON IR.
77a0865e38SLawrence Tang json_object* cper_section_platform_memory2_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
78a0865e38SLawrence Tang {
79a0865e38SLawrence Tang     EFI_PLATFORM_MEMORY2_ERROR_DATA* memory_error = (EFI_PLATFORM_MEMORY2_ERROR_DATA*)section;
80a0865e38SLawrence Tang     json_object* section_ir = json_object_new_object();
81a0865e38SLawrence Tang 
8254da4414SLawrence Tang     //Validation bits.
8354da4414SLawrence Tang     json_object* validation = bitfield_to_ir(memory_error->ValidFields, 22, MEMORY_ERROR_2_VALID_BITFIELD_NAMES);
8454da4414SLawrence Tang     json_object_object_add(section_ir, "validationBits", validation);
8554da4414SLawrence Tang 
8654da4414SLawrence Tang     //Error status.
8754da4414SLawrence Tang     json_object* error_status = cper_generic_error_status_to_ir(&memory_error->ErrorStatus);
8854da4414SLawrence Tang     json_object_object_add(section_ir, "errorStatus", error_status);
8954da4414SLawrence Tang 
9054da4414SLawrence Tang     //Bank.
9154da4414SLawrence Tang     json_object* bank = json_object_new_object();
92583cdeeeSLawrence Tang     if ((memory_error->ValidFields >> 5) & 0x1)
93583cdeeeSLawrence Tang     {
94583cdeeeSLawrence Tang         //Entire bank address mode.
95583cdeeeSLawrence Tang         json_object_object_add(bank, "value", json_object_new_uint64(memory_error->Bank));
96583cdeeeSLawrence Tang     }
97583cdeeeSLawrence Tang     else
98583cdeeeSLawrence Tang     {
99583cdeeeSLawrence Tang         //Address/group address mode.
10054da4414SLawrence Tang         json_object_object_add(bank, "address", json_object_new_uint64(memory_error->Bank & 0xFF));
10154da4414SLawrence Tang         json_object_object_add(bank, "group", json_object_new_uint64(memory_error->Bank >> 8));
102583cdeeeSLawrence Tang     }
10354da4414SLawrence Tang     json_object_object_add(section_ir, "bank", bank);
10454da4414SLawrence Tang 
10554da4414SLawrence Tang     //Memory error type.
10654da4414SLawrence Tang     json_object* memory_error_type = integer_to_readable_pair(memory_error->MemErrorType, 16,
10754da4414SLawrence Tang         MEMORY_ERROR_TYPES_KEYS,
10854da4414SLawrence Tang         MEMORY_ERROR_TYPES_VALUES,
10954da4414SLawrence Tang         "Unknown (Reserved)");
11054da4414SLawrence Tang     json_object_object_add(section_ir, "memoryErrorType", memory_error_type);
11154da4414SLawrence Tang 
11254da4414SLawrence Tang     //Status.
11354da4414SLawrence Tang     json_object* status = json_object_new_object();
11454da4414SLawrence Tang     json_object_object_add(status, "value", json_object_new_int(memory_error->Status));
11554da4414SLawrence Tang     json_object_object_add(status, "state", json_object_new_string(memory_error->Status & 0b1 == 0 ? "Corrected" : "Uncorrected"));
11654da4414SLawrence Tang     json_object_object_add(section_ir, "status", status);
11754da4414SLawrence Tang 
11854da4414SLawrence Tang     //Miscellaneous numeric fields.
11954da4414SLawrence Tang     json_object_object_add(section_ir, "physicalAddress", json_object_new_uint64(memory_error->PhysicalAddress));
12054da4414SLawrence Tang     json_object_object_add(section_ir, "physicalAddressMask", json_object_new_uint64(memory_error->PhysicalAddressMask));
12154da4414SLawrence Tang     json_object_object_add(section_ir, "node", json_object_new_uint64(memory_error->Node));
12254da4414SLawrence Tang     json_object_object_add(section_ir, "card", json_object_new_uint64(memory_error->Card));
12354da4414SLawrence Tang     json_object_object_add(section_ir, "module", json_object_new_uint64(memory_error->Module));
12454da4414SLawrence Tang     json_object_object_add(section_ir, "device", json_object_new_uint64(memory_error->Device));
12554da4414SLawrence Tang     json_object_object_add(section_ir, "row", json_object_new_uint64(memory_error->Row));
12654da4414SLawrence Tang     json_object_object_add(section_ir, "column", json_object_new_uint64(memory_error->Column));
12754da4414SLawrence Tang     json_object_object_add(section_ir, "rank", json_object_new_uint64(memory_error->Rank));
12854da4414SLawrence Tang     json_object_object_add(section_ir, "bitPosition", json_object_new_uint64(memory_error->BitPosition));
12954da4414SLawrence Tang     json_object_object_add(section_ir, "chipID", json_object_new_uint64(memory_error->ChipId));
13054da4414SLawrence Tang     json_object_object_add(section_ir, "requestorID", json_object_new_uint64(memory_error->RequestorId));
13154da4414SLawrence Tang     json_object_object_add(section_ir, "responderID", json_object_new_uint64(memory_error->ResponderId));
13254da4414SLawrence Tang     json_object_object_add(section_ir, "targetID", json_object_new_uint64(memory_error->TargetId));
13354da4414SLawrence Tang     json_object_object_add(section_ir, "cardSmbiosHandle", json_object_new_uint64(memory_error->CardHandle));
13454da4414SLawrence Tang     json_object_object_add(section_ir, "moduleSmbiosHandle", json_object_new_uint64(memory_error->ModuleHandle));
135a0865e38SLawrence Tang 
136a0865e38SLawrence Tang     return section_ir;
1377f21db6cSLawrence Tang }
138*3b7f45b5SLawrence Tang 
139*3b7f45b5SLawrence Tang //Converts a single Memory Error IR section into CPER binary, outputting to the provided stream.
140*3b7f45b5SLawrence Tang void ir_section_memory_to_cper(json_object* section, FILE* out)
141*3b7f45b5SLawrence Tang {
142*3b7f45b5SLawrence Tang     EFI_PLATFORM_MEMORY_ERROR_DATA* section_cper =
143*3b7f45b5SLawrence Tang         (EFI_PLATFORM_MEMORY_ERROR_DATA*)calloc(1, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA));
144*3b7f45b5SLawrence Tang 
145*3b7f45b5SLawrence Tang     //Validation bits.
146*3b7f45b5SLawrence Tang     section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"),
147*3b7f45b5SLawrence Tang         22, MEMORY_ERROR_VALID_BITFIELD_NAMES);
148*3b7f45b5SLawrence Tang 
149*3b7f45b5SLawrence Tang     //Error status.
150*3b7f45b5SLawrence Tang     ir_generic_error_status_to_cper(json_object_object_get(section, "errorStatus"), &section_cper->ErrorStatus);
151*3b7f45b5SLawrence Tang 
152*3b7f45b5SLawrence Tang     //Bank.
153*3b7f45b5SLawrence Tang     json_object* bank = json_object_object_get(section, "bank");
154*3b7f45b5SLawrence Tang     if ((section_cper->ValidFields >> 5) & 0x1)
155*3b7f45b5SLawrence Tang     {
156*3b7f45b5SLawrence Tang         //Bank just uses simple address.
157*3b7f45b5SLawrence Tang         section_cper->Bank = (UINT16)json_object_get_uint64(json_object_object_get(bank, "value"));
158*3b7f45b5SLawrence Tang     }
159*3b7f45b5SLawrence Tang     else
160*3b7f45b5SLawrence Tang     {
161*3b7f45b5SLawrence Tang         //Bank uses address/group style address.
162*3b7f45b5SLawrence Tang         UINT16 address = (UINT8)json_object_get_uint64(json_object_object_get(bank, "address"));
163*3b7f45b5SLawrence Tang         UINT16 group = (UINT8)json_object_get_uint64(json_object_object_get(bank, "group"));
164*3b7f45b5SLawrence Tang         section_cper->Bank = address + (group << 8);
165*3b7f45b5SLawrence Tang     }
166*3b7f45b5SLawrence Tang 
167*3b7f45b5SLawrence Tang     //"Extended" field.
168*3b7f45b5SLawrence Tang     json_object* extended = json_object_object_get(section, "extended");
169*3b7f45b5SLawrence Tang     section_cper->Extended = 0;
170*3b7f45b5SLawrence Tang     section_cper->Extended |= json_object_get_boolean(json_object_object_get(extended, "rowBit16"));
171*3b7f45b5SLawrence Tang     section_cper->Extended |= json_object_get_boolean(json_object_object_get(extended, "rowBit17")) << 1;
172*3b7f45b5SLawrence Tang     section_cper->Extended |= json_object_get_int(json_object_object_get(extended, "chipIdentification")) << 5;
173*3b7f45b5SLawrence Tang 
174*3b7f45b5SLawrence Tang     //Miscellaneous value fields.
175*3b7f45b5SLawrence Tang     section_cper->ErrorType = readable_pair_to_integer(json_object_object_get(section, "memoryErrorType"));
176*3b7f45b5SLawrence Tang     section_cper->PhysicalAddress = json_object_get_uint64(json_object_object_get(section, "physicalAddress"));
177*3b7f45b5SLawrence Tang     section_cper->PhysicalAddressMask = json_object_get_uint64(json_object_object_get(section, "physicalAddressMask"));
178*3b7f45b5SLawrence Tang     section_cper->Node = (UINT16)json_object_get_uint64(json_object_object_get(section, "node"));
179*3b7f45b5SLawrence Tang     section_cper->Card = (UINT16)json_object_get_uint64(json_object_object_get(section, "card"));
180*3b7f45b5SLawrence Tang     section_cper->ModuleRank = (UINT16)json_object_get_uint64(json_object_object_get(section, "moduleRank"));
181*3b7f45b5SLawrence Tang     section_cper->Device = (UINT16)json_object_get_uint64(json_object_object_get(section, "device"));
182*3b7f45b5SLawrence Tang     section_cper->Row = (UINT16)json_object_get_uint64(json_object_object_get(section, "row"));
183*3b7f45b5SLawrence Tang     section_cper->Column = (UINT16)json_object_get_uint64(json_object_object_get(section, "column"));
184*3b7f45b5SLawrence Tang     section_cper->BitPosition = (UINT16)json_object_get_uint64(json_object_object_get(section, "bitPosition"));
185*3b7f45b5SLawrence Tang     section_cper->RequestorId = json_object_get_uint64(json_object_object_get(section, "requestorID"));
186*3b7f45b5SLawrence Tang     section_cper->ResponderId = json_object_get_uint64(json_object_object_get(section, "responderID"));
187*3b7f45b5SLawrence Tang     section_cper->TargetId = json_object_get_uint64(json_object_object_get(section, "targetID"));
188*3b7f45b5SLawrence Tang     section_cper->RankNum = (UINT16)json_object_get_uint64(json_object_object_get(section, "rankNumber"));
189*3b7f45b5SLawrence Tang     section_cper->CardHandle = (UINT16)json_object_get_uint64(json_object_object_get(section, "cardSmbiosHandle"));
190*3b7f45b5SLawrence Tang     section_cper->ModuleHandle = (UINT16)json_object_get_uint64(json_object_object_get(section, "moduleSmbiosHandle"));
191*3b7f45b5SLawrence Tang 
192*3b7f45b5SLawrence Tang     //Write to stream, free up resources.
193*3b7f45b5SLawrence Tang     fwrite(&section_cper, sizeof(section_cper), 1, out);
194*3b7f45b5SLawrence Tang     fflush(out);
195*3b7f45b5SLawrence Tang     free(section_cper);
196*3b7f45b5SLawrence Tang }
197*3b7f45b5SLawrence Tang 
198*3b7f45b5SLawrence Tang //Converts a single Memory Error 2 IR section into CPER binary, outputting to the provided stream.
199*3b7f45b5SLawrence Tang void ir_section_memory2_to_cper(json_object* section, FILE* out)
200*3b7f45b5SLawrence Tang {
201*3b7f45b5SLawrence Tang     EFI_PLATFORM_MEMORY2_ERROR_DATA* section_cper =
202*3b7f45b5SLawrence Tang         (EFI_PLATFORM_MEMORY2_ERROR_DATA*)calloc(1, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA));
203*3b7f45b5SLawrence Tang 
204*3b7f45b5SLawrence Tang     //Validation bits.
205*3b7f45b5SLawrence Tang     section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"),
206*3b7f45b5SLawrence Tang         22, MEMORY_ERROR_2_VALID_BITFIELD_NAMES);
207*3b7f45b5SLawrence Tang 
208*3b7f45b5SLawrence Tang     //Error status.
209*3b7f45b5SLawrence Tang     ir_generic_error_status_to_cper(json_object_object_get(section, "errorStatus"), &section_cper->ErrorStatus);
210*3b7f45b5SLawrence Tang 
211*3b7f45b5SLawrence Tang     //Bank.
212*3b7f45b5SLawrence Tang     json_object* bank = json_object_object_get(section, "bank");
213*3b7f45b5SLawrence Tang     if ((section_cper->ValidFields >> 5) & 0x1)
214*3b7f45b5SLawrence Tang     {
215*3b7f45b5SLawrence Tang         //Bank just uses simple address.
216*3b7f45b5SLawrence Tang         section_cper->Bank = (UINT16)json_object_get_uint64(json_object_object_get(bank, "value"));
217*3b7f45b5SLawrence Tang     }
218*3b7f45b5SLawrence Tang     else
219*3b7f45b5SLawrence Tang     {
220*3b7f45b5SLawrence Tang         //Bank uses address/group style address.
221*3b7f45b5SLawrence Tang         UINT16 address = (UINT8)json_object_get_uint64(json_object_object_get(bank, "address"));
222*3b7f45b5SLawrence Tang         UINT16 group = (UINT8)json_object_get_uint64(json_object_object_get(bank, "group"));
223*3b7f45b5SLawrence Tang         section_cper->Bank = address + (group << 8);
224*3b7f45b5SLawrence Tang     }
225*3b7f45b5SLawrence Tang 
226*3b7f45b5SLawrence Tang     //Miscellaneous value fields.
227*3b7f45b5SLawrence Tang     section_cper->MemErrorType = readable_pair_to_integer(json_object_object_get(section, "memoryErrorType"));
228*3b7f45b5SLawrence Tang     section_cper->Status = (UINT8)readable_pair_to_integer(json_object_object_get(section, "status"));
229*3b7f45b5SLawrence Tang     section_cper->PhysicalAddress = json_object_get_uint64(json_object_object_get(section, "physicalAddress"));
230*3b7f45b5SLawrence Tang     section_cper->PhysicalAddressMask = json_object_get_uint64(json_object_object_get(section, "physicalAddressMask"));
231*3b7f45b5SLawrence Tang     section_cper->Node = (UINT16)json_object_get_uint64(json_object_object_get(section, "node"));
232*3b7f45b5SLawrence Tang     section_cper->Card = (UINT16)json_object_get_uint64(json_object_object_get(section, "card"));
233*3b7f45b5SLawrence Tang     section_cper->Module = (UINT32)json_object_get_uint64(json_object_object_get(section, "module"));
234*3b7f45b5SLawrence Tang     section_cper->Device = (UINT32)json_object_get_uint64(json_object_object_get(section, "device"));
235*3b7f45b5SLawrence Tang     section_cper->Row = (UINT32)json_object_get_uint64(json_object_object_get(section, "row"));
236*3b7f45b5SLawrence Tang     section_cper->Column = (UINT32)json_object_get_uint64(json_object_object_get(section, "column"));
237*3b7f45b5SLawrence Tang     section_cper->Rank = (UINT32)json_object_get_uint64(json_object_object_get(section, "rank"));
238*3b7f45b5SLawrence Tang     section_cper->BitPosition = (UINT32)json_object_get_uint64(json_object_object_get(section, "bitPosition"));
239*3b7f45b5SLawrence Tang     section_cper->ChipId = (UINT8)json_object_get_uint64(json_object_object_get(section, "chipID"));
240*3b7f45b5SLawrence Tang     section_cper->RequestorId = json_object_get_uint64(json_object_object_get(section, "requestorID"));
241*3b7f45b5SLawrence Tang     section_cper->ResponderId = json_object_get_uint64(json_object_object_get(section, "responderID"));
242*3b7f45b5SLawrence Tang     section_cper->TargetId = json_object_get_uint64(json_object_object_get(section, "targetID"));
243*3b7f45b5SLawrence Tang     section_cper->CardHandle = (UINT32)json_object_get_uint64(json_object_object_get(section, "cardSmbiosHandle"));
244*3b7f45b5SLawrence Tang     section_cper->ModuleHandle = (UINT32)json_object_get_uint64(json_object_object_get(section, "moduleSmbiosHandle"));
245*3b7f45b5SLawrence Tang 
246*3b7f45b5SLawrence Tang     //Write to stream, free up resources.
247*3b7f45b5SLawrence Tang     fwrite(&section_cper, sizeof(section_cper), 1, out);
248*3b7f45b5SLawrence Tang     fflush(out);
249*3b7f45b5SLawrence Tang     free(section_cper);
250*3b7f45b5SLawrence Tang }