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 }
1383b7f45b5SLawrence Tang 
1393b7f45b5SLawrence Tang //Converts a single Memory Error IR section into CPER binary, outputting to the provided stream.
1403b7f45b5SLawrence Tang void ir_section_memory_to_cper(json_object* section, FILE* out)
1413b7f45b5SLawrence Tang {
1423b7f45b5SLawrence Tang     EFI_PLATFORM_MEMORY_ERROR_DATA* section_cper =
1433b7f45b5SLawrence Tang         (EFI_PLATFORM_MEMORY_ERROR_DATA*)calloc(1, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA));
1443b7f45b5SLawrence Tang 
1453b7f45b5SLawrence Tang     //Validation bits.
1463b7f45b5SLawrence Tang     section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"),
1473b7f45b5SLawrence Tang         22, MEMORY_ERROR_VALID_BITFIELD_NAMES);
1483b7f45b5SLawrence Tang 
1493b7f45b5SLawrence Tang     //Error status.
1503b7f45b5SLawrence Tang     ir_generic_error_status_to_cper(json_object_object_get(section, "errorStatus"), &section_cper->ErrorStatus);
1513b7f45b5SLawrence Tang 
1523b7f45b5SLawrence Tang     //Bank.
1533b7f45b5SLawrence Tang     json_object* bank = json_object_object_get(section, "bank");
1543b7f45b5SLawrence Tang     if ((section_cper->ValidFields >> 5) & 0x1)
1553b7f45b5SLawrence Tang     {
1563b7f45b5SLawrence Tang         //Bank just uses simple address.
1573b7f45b5SLawrence Tang         section_cper->Bank = (UINT16)json_object_get_uint64(json_object_object_get(bank, "value"));
1583b7f45b5SLawrence Tang     }
1593b7f45b5SLawrence Tang     else
1603b7f45b5SLawrence Tang     {
1613b7f45b5SLawrence Tang         //Bank uses address/group style address.
1623b7f45b5SLawrence Tang         UINT16 address = (UINT8)json_object_get_uint64(json_object_object_get(bank, "address"));
1633b7f45b5SLawrence Tang         UINT16 group = (UINT8)json_object_get_uint64(json_object_object_get(bank, "group"));
1643b7f45b5SLawrence Tang         section_cper->Bank = address + (group << 8);
1653b7f45b5SLawrence Tang     }
1663b7f45b5SLawrence Tang 
1673b7f45b5SLawrence Tang     //"Extended" field.
1683b7f45b5SLawrence Tang     json_object* extended = json_object_object_get(section, "extended");
1693b7f45b5SLawrence Tang     section_cper->Extended = 0;
1703b7f45b5SLawrence Tang     section_cper->Extended |= json_object_get_boolean(json_object_object_get(extended, "rowBit16"));
1713b7f45b5SLawrence Tang     section_cper->Extended |= json_object_get_boolean(json_object_object_get(extended, "rowBit17")) << 1;
1723b7f45b5SLawrence Tang     section_cper->Extended |= json_object_get_int(json_object_object_get(extended, "chipIdentification")) << 5;
1733b7f45b5SLawrence Tang 
1743b7f45b5SLawrence Tang     //Miscellaneous value fields.
175*3ab351feSLawrence Tang     section_cper->ErrorType = (UINT8)readable_pair_to_integer(json_object_object_get(section, "memoryErrorType"));
1763b7f45b5SLawrence Tang     section_cper->PhysicalAddress = json_object_get_uint64(json_object_object_get(section, "physicalAddress"));
1773b7f45b5SLawrence Tang     section_cper->PhysicalAddressMask = json_object_get_uint64(json_object_object_get(section, "physicalAddressMask"));
1783b7f45b5SLawrence Tang     section_cper->Node = (UINT16)json_object_get_uint64(json_object_object_get(section, "node"));
1793b7f45b5SLawrence Tang     section_cper->Card = (UINT16)json_object_get_uint64(json_object_object_get(section, "card"));
1803b7f45b5SLawrence Tang     section_cper->ModuleRank = (UINT16)json_object_get_uint64(json_object_object_get(section, "moduleRank"));
1813b7f45b5SLawrence Tang     section_cper->Device = (UINT16)json_object_get_uint64(json_object_object_get(section, "device"));
1823b7f45b5SLawrence Tang     section_cper->Row = (UINT16)json_object_get_uint64(json_object_object_get(section, "row"));
1833b7f45b5SLawrence Tang     section_cper->Column = (UINT16)json_object_get_uint64(json_object_object_get(section, "column"));
1843b7f45b5SLawrence Tang     section_cper->BitPosition = (UINT16)json_object_get_uint64(json_object_object_get(section, "bitPosition"));
1853b7f45b5SLawrence Tang     section_cper->RequestorId = json_object_get_uint64(json_object_object_get(section, "requestorID"));
1863b7f45b5SLawrence Tang     section_cper->ResponderId = json_object_get_uint64(json_object_object_get(section, "responderID"));
1873b7f45b5SLawrence Tang     section_cper->TargetId = json_object_get_uint64(json_object_object_get(section, "targetID"));
1883b7f45b5SLawrence Tang     section_cper->RankNum = (UINT16)json_object_get_uint64(json_object_object_get(section, "rankNumber"));
1893b7f45b5SLawrence Tang     section_cper->CardHandle = (UINT16)json_object_get_uint64(json_object_object_get(section, "cardSmbiosHandle"));
1903b7f45b5SLawrence Tang     section_cper->ModuleHandle = (UINT16)json_object_get_uint64(json_object_object_get(section, "moduleSmbiosHandle"));
1913b7f45b5SLawrence Tang 
1923b7f45b5SLawrence Tang     //Write to stream, free up resources.
193*3ab351feSLawrence Tang     fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA), 1, out);
1943b7f45b5SLawrence Tang     fflush(out);
1953b7f45b5SLawrence Tang     free(section_cper);
1963b7f45b5SLawrence Tang }
1973b7f45b5SLawrence Tang 
1983b7f45b5SLawrence Tang //Converts a single Memory Error 2 IR section into CPER binary, outputting to the provided stream.
1993b7f45b5SLawrence Tang void ir_section_memory2_to_cper(json_object* section, FILE* out)
2003b7f45b5SLawrence Tang {
2013b7f45b5SLawrence Tang     EFI_PLATFORM_MEMORY2_ERROR_DATA* section_cper =
2023b7f45b5SLawrence Tang         (EFI_PLATFORM_MEMORY2_ERROR_DATA*)calloc(1, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA));
2033b7f45b5SLawrence Tang 
2043b7f45b5SLawrence Tang     //Validation bits.
2053b7f45b5SLawrence Tang     section_cper->ValidFields = ir_to_bitfield(json_object_object_get(section, "validationBits"),
2063b7f45b5SLawrence Tang         22, MEMORY_ERROR_2_VALID_BITFIELD_NAMES);
2073b7f45b5SLawrence Tang 
2083b7f45b5SLawrence Tang     //Error status.
2093b7f45b5SLawrence Tang     ir_generic_error_status_to_cper(json_object_object_get(section, "errorStatus"), &section_cper->ErrorStatus);
2103b7f45b5SLawrence Tang 
2113b7f45b5SLawrence Tang     //Bank.
2123b7f45b5SLawrence Tang     json_object* bank = json_object_object_get(section, "bank");
2133b7f45b5SLawrence Tang     if ((section_cper->ValidFields >> 5) & 0x1)
2143b7f45b5SLawrence Tang     {
2153b7f45b5SLawrence Tang         //Bank just uses simple address.
2163b7f45b5SLawrence Tang         section_cper->Bank = (UINT16)json_object_get_uint64(json_object_object_get(bank, "value"));
2173b7f45b5SLawrence Tang     }
2183b7f45b5SLawrence Tang     else
2193b7f45b5SLawrence Tang     {
2203b7f45b5SLawrence Tang         //Bank uses address/group style address.
2213b7f45b5SLawrence Tang         UINT16 address = (UINT8)json_object_get_uint64(json_object_object_get(bank, "address"));
2223b7f45b5SLawrence Tang         UINT16 group = (UINT8)json_object_get_uint64(json_object_object_get(bank, "group"));
2233b7f45b5SLawrence Tang         section_cper->Bank = address + (group << 8);
2243b7f45b5SLawrence Tang     }
2253b7f45b5SLawrence Tang 
2263b7f45b5SLawrence Tang     //Miscellaneous value fields.
2273b7f45b5SLawrence Tang     section_cper->MemErrorType = readable_pair_to_integer(json_object_object_get(section, "memoryErrorType"));
2283b7f45b5SLawrence Tang     section_cper->Status = (UINT8)readable_pair_to_integer(json_object_object_get(section, "status"));
2293b7f45b5SLawrence Tang     section_cper->PhysicalAddress = json_object_get_uint64(json_object_object_get(section, "physicalAddress"));
2303b7f45b5SLawrence Tang     section_cper->PhysicalAddressMask = json_object_get_uint64(json_object_object_get(section, "physicalAddressMask"));
2313b7f45b5SLawrence Tang     section_cper->Node = (UINT16)json_object_get_uint64(json_object_object_get(section, "node"));
2323b7f45b5SLawrence Tang     section_cper->Card = (UINT16)json_object_get_uint64(json_object_object_get(section, "card"));
2333b7f45b5SLawrence Tang     section_cper->Module = (UINT32)json_object_get_uint64(json_object_object_get(section, "module"));
2343b7f45b5SLawrence Tang     section_cper->Device = (UINT32)json_object_get_uint64(json_object_object_get(section, "device"));
2353b7f45b5SLawrence Tang     section_cper->Row = (UINT32)json_object_get_uint64(json_object_object_get(section, "row"));
2363b7f45b5SLawrence Tang     section_cper->Column = (UINT32)json_object_get_uint64(json_object_object_get(section, "column"));
2373b7f45b5SLawrence Tang     section_cper->Rank = (UINT32)json_object_get_uint64(json_object_object_get(section, "rank"));
2383b7f45b5SLawrence Tang     section_cper->BitPosition = (UINT32)json_object_get_uint64(json_object_object_get(section, "bitPosition"));
2393b7f45b5SLawrence Tang     section_cper->ChipId = (UINT8)json_object_get_uint64(json_object_object_get(section, "chipID"));
2403b7f45b5SLawrence Tang     section_cper->RequestorId = json_object_get_uint64(json_object_object_get(section, "requestorID"));
2413b7f45b5SLawrence Tang     section_cper->ResponderId = json_object_get_uint64(json_object_object_get(section, "responderID"));
2423b7f45b5SLawrence Tang     section_cper->TargetId = json_object_get_uint64(json_object_object_get(section, "targetID"));
2433b7f45b5SLawrence Tang     section_cper->CardHandle = (UINT32)json_object_get_uint64(json_object_object_get(section, "cardSmbiosHandle"));
2443b7f45b5SLawrence Tang     section_cper->ModuleHandle = (UINT32)json_object_get_uint64(json_object_object_get(section, "moduleSmbiosHandle"));
2453b7f45b5SLawrence Tang 
2463b7f45b5SLawrence Tang     //Write to stream, free up resources.
247*3ab351feSLawrence Tang     fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA), 1, out);
2483b7f45b5SLawrence Tang     fflush(out);
2493b7f45b5SLawrence Tang     free(section_cper);
2503b7f45b5SLawrence Tang }