| /** |
| * Describes functions for converting memory error CPER sections from binary and JSON format |
| * into an intermediate format. |
| * |
| * Author: Lawrence.Tang@arm.com |
| **/ |
| #include <stdio.h> |
| #include <json.h> |
| #include <libcper/Cper.h> |
| #include <libcper/cper-utils.h> |
| #include <libcper/sections/cper-section-memory.h> |
| |
| //Converts a single memory error CPER section into JSON IR. |
| json_object *cper_section_platform_memory_to_ir(void *section) |
| { |
| EFI_PLATFORM_MEMORY_ERROR_DATA *memory_error = |
| (EFI_PLATFORM_MEMORY_ERROR_DATA *)section; |
| json_object *section_ir = json_object_new_object(); |
| |
| //Validation bitfield. |
| json_object *validation = |
| bitfield_to_ir(memory_error->ValidFields, 22, |
| MEMORY_ERROR_VALID_BITFIELD_NAMES); |
| json_object_object_add(section_ir, "validationBits", validation); |
| |
| //Error status. |
| json_object *error_status = |
| cper_generic_error_status_to_ir(&memory_error->ErrorStatus); |
| json_object_object_add(section_ir, "errorStatus", error_status); |
| |
| //Bank. |
| json_object *bank = json_object_new_object(); |
| if ((memory_error->ValidFields >> 5) & 0x1) { |
| //Entire bank address mode. |
| json_object_object_add( |
| bank, "value", |
| json_object_new_uint64(memory_error->Bank)); |
| } else { |
| //Address/group address mode. |
| json_object_object_add( |
| bank, "address", |
| json_object_new_uint64(memory_error->Bank & 0xFF)); |
| json_object_object_add( |
| bank, "group", |
| json_object_new_uint64(memory_error->Bank >> 8)); |
| } |
| json_object_object_add(section_ir, "bank", bank); |
| |
| //Memory error type. |
| json_object *memory_error_type = integer_to_readable_pair( |
| memory_error->ErrorType, 16, MEMORY_ERROR_TYPES_KEYS, |
| MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)"); |
| json_object_object_add(section_ir, "memoryErrorType", |
| memory_error_type); |
| |
| //"Extended" row/column indication field + misc. |
| json_object *extended = json_object_new_object(); |
| json_object_object_add(extended, "rowBit16", |
| json_object_new_boolean(memory_error->Extended & |
| 0x1)); |
| json_object_object_add( |
| extended, "rowBit17", |
| json_object_new_boolean((memory_error->Extended >> 1) & 0x1)); |
| json_object_object_add(extended, "chipIdentification", |
| json_object_new_int(memory_error->Extended >> |
| 5)); |
| json_object_object_add(section_ir, "extended", extended); |
| |
| //Miscellaneous numeric fields. |
| json_object_object_add( |
| section_ir, "physicalAddress", |
| json_object_new_uint64(memory_error->PhysicalAddress)); |
| |
| char hexstring_buf[EFI_UINT64_HEX_STRING_LEN]; |
| snprintf(hexstring_buf, EFI_UINT64_HEX_STRING_LEN, "0x%016llX", |
| memory_error->PhysicalAddress); |
| json_object_object_add(section_ir, "physicalAddressHex", |
| json_object_new_string(hexstring_buf)); |
| |
| json_object_object_add( |
| section_ir, "physicalAddressMask", |
| json_object_new_uint64(memory_error->PhysicalAddressMask)); |
| json_object_object_add(section_ir, "node", |
| json_object_new_uint64(memory_error->Node)); |
| json_object_object_add(section_ir, "card", |
| json_object_new_uint64(memory_error->Card)); |
| json_object_object_add( |
| section_ir, "moduleRank", |
| json_object_new_uint64(memory_error->ModuleRank)); |
| json_object_object_add(section_ir, "device", |
| json_object_new_uint64(memory_error->Device)); |
| json_object_object_add(section_ir, "row", |
| json_object_new_uint64(memory_error->Row)); |
| json_object_object_add(section_ir, "column", |
| json_object_new_uint64(memory_error->Column)); |
| json_object_object_add( |
| section_ir, "bitPosition", |
| json_object_new_uint64(memory_error->BitPosition)); |
| json_object_object_add( |
| section_ir, "requestorID", |
| json_object_new_uint64(memory_error->RequestorId)); |
| json_object_object_add( |
| section_ir, "responderID", |
| json_object_new_uint64(memory_error->ResponderId)); |
| json_object_object_add(section_ir, "targetID", |
| json_object_new_uint64(memory_error->TargetId)); |
| json_object_object_add(section_ir, "rankNumber", |
| json_object_new_uint64(memory_error->RankNum)); |
| json_object_object_add( |
| section_ir, "cardSmbiosHandle", |
| json_object_new_uint64(memory_error->CardHandle)); |
| json_object_object_add( |
| section_ir, "moduleSmbiosHandle", |
| json_object_new_uint64(memory_error->ModuleHandle)); |
| |
| return section_ir; |
| } |
| |
| //Converts a single memory error 2 CPER section into JSON IR. |
| json_object *cper_section_platform_memory2_to_ir(void *section) |
| { |
| EFI_PLATFORM_MEMORY2_ERROR_DATA *memory_error = |
| (EFI_PLATFORM_MEMORY2_ERROR_DATA *)section; |
| json_object *section_ir = json_object_new_object(); |
| |
| //Validation bits. |
| json_object *validation = |
| bitfield_to_ir(memory_error->ValidFields, 22, |
| MEMORY_ERROR_2_VALID_BITFIELD_NAMES); |
| json_object_object_add(section_ir, "validationBits", validation); |
| |
| //Error status. |
| json_object *error_status = |
| cper_generic_error_status_to_ir(&memory_error->ErrorStatus); |
| json_object_object_add(section_ir, "errorStatus", error_status); |
| |
| //Bank. |
| json_object *bank = json_object_new_object(); |
| if ((memory_error->ValidFields >> 5) & 0x1) { |
| //Entire bank address mode. |
| json_object_object_add( |
| bank, "value", |
| json_object_new_uint64(memory_error->Bank)); |
| } else { |
| //Address/group address mode. |
| json_object_object_add( |
| bank, "address", |
| json_object_new_uint64(memory_error->Bank & 0xFF)); |
| json_object_object_add( |
| bank, "group", |
| json_object_new_uint64(memory_error->Bank >> 8)); |
| } |
| json_object_object_add(section_ir, "bank", bank); |
| |
| //Memory error type. |
| json_object *memory_error_type = integer_to_readable_pair( |
| memory_error->MemErrorType, 16, MEMORY_ERROR_TYPES_KEYS, |
| MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)"); |
| json_object_object_add(section_ir, "memoryErrorType", |
| memory_error_type); |
| |
| //Status. |
| json_object *status = json_object_new_object(); |
| json_object_object_add(status, "value", |
| json_object_new_int(memory_error->Status)); |
| json_object_object_add( |
| status, "state", |
| json_object_new_string((memory_error->Status & 0x1) == 0 ? |
| "Corrected" : |
| "Uncorrected")); |
| json_object_object_add(section_ir, "status", status); |
| |
| //Miscellaneous numeric fields. |
| json_object_object_add( |
| section_ir, "physicalAddress", |
| json_object_new_uint64(memory_error->PhysicalAddress)); |
| |
| char hexstring_buf[EFI_UINT64_HEX_STRING_LEN]; |
| snprintf(hexstring_buf, EFI_UINT64_HEX_STRING_LEN, "0x%016llX", |
| memory_error->PhysicalAddress); |
| json_object_object_add(section_ir, "physicalAddressHex", |
| json_object_new_string(hexstring_buf)); |
| |
| json_object_object_add( |
| section_ir, "physicalAddressMask", |
| json_object_new_uint64(memory_error->PhysicalAddressMask)); |
| json_object_object_add(section_ir, "node", |
| json_object_new_uint64(memory_error->Node)); |
| json_object_object_add(section_ir, "card", |
| json_object_new_uint64(memory_error->Card)); |
| json_object_object_add(section_ir, "module", |
| json_object_new_uint64(memory_error->Module)); |
| json_object_object_add(section_ir, "device", |
| json_object_new_uint64(memory_error->Device)); |
| json_object_object_add(section_ir, "row", |
| json_object_new_uint64(memory_error->Row)); |
| json_object_object_add(section_ir, "column", |
| json_object_new_uint64(memory_error->Column)); |
| json_object_object_add(section_ir, "rank", |
| json_object_new_uint64(memory_error->Rank)); |
| json_object_object_add( |
| section_ir, "bitPosition", |
| json_object_new_uint64(memory_error->BitPosition)); |
| json_object_object_add(section_ir, "chipID", |
| json_object_new_uint64(memory_error->ChipId)); |
| json_object_object_add( |
| section_ir, "requestorID", |
| json_object_new_uint64(memory_error->RequestorId)); |
| json_object_object_add( |
| section_ir, "responderID", |
| json_object_new_uint64(memory_error->ResponderId)); |
| json_object_object_add(section_ir, "targetID", |
| json_object_new_uint64(memory_error->TargetId)); |
| json_object_object_add( |
| section_ir, "cardSmbiosHandle", |
| json_object_new_uint64(memory_error->CardHandle)); |
| json_object_object_add( |
| section_ir, "moduleSmbiosHandle", |
| json_object_new_uint64(memory_error->ModuleHandle)); |
| |
| return section_ir; |
| } |
| |
| //Converts a single Memory Error IR section into CPER binary, outputting to the provided stream. |
| void ir_section_memory_to_cper(json_object *section, FILE *out) |
| { |
| EFI_PLATFORM_MEMORY_ERROR_DATA *section_cper = |
| (EFI_PLATFORM_MEMORY_ERROR_DATA *)calloc( |
| 1, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA)); |
| |
| //Validation bits. |
| section_cper->ValidFields = ir_to_bitfield( |
| json_object_object_get(section, "validationBits"), 22, |
| MEMORY_ERROR_VALID_BITFIELD_NAMES); |
| |
| //Error status. |
| ir_generic_error_status_to_cper(json_object_object_get(section, |
| "errorStatus"), |
| §ion_cper->ErrorStatus); |
| |
| //Bank. |
| json_object *bank = json_object_object_get(section, "bank"); |
| if ((section_cper->ValidFields >> 5) & 0x1) { |
| //Bank just uses simple address. |
| section_cper->Bank = (UINT16)json_object_get_uint64( |
| json_object_object_get(bank, "value")); |
| } else { |
| //Bank uses address/group style address. |
| UINT16 address = (UINT8)json_object_get_uint64( |
| json_object_object_get(bank, "address")); |
| UINT16 group = (UINT8)json_object_get_uint64( |
| json_object_object_get(bank, "group")); |
| section_cper->Bank = address + (group << 8); |
| } |
| |
| //"Extended" field. |
| json_object *extended = json_object_object_get(section, "extended"); |
| section_cper->Extended = 0; |
| section_cper->Extended |= json_object_get_boolean( |
| json_object_object_get(extended, "rowBit16")); |
| section_cper->Extended |= |
| json_object_get_boolean( |
| json_object_object_get(extended, "rowBit17")) |
| << 1; |
| section_cper->Extended |= json_object_get_int(json_object_object_get( |
| extended, "chipIdentification")) |
| << 5; |
| |
| //Miscellaneous value fields. |
| section_cper->ErrorType = (UINT8)readable_pair_to_integer( |
| json_object_object_get(section, "memoryErrorType")); |
| section_cper->PhysicalAddress = json_object_get_uint64( |
| json_object_object_get(section, "physicalAddress")); |
| section_cper->PhysicalAddressMask = json_object_get_uint64( |
| json_object_object_get(section, "physicalAddressMask")); |
| section_cper->Node = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "node")); |
| section_cper->Card = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "card")); |
| section_cper->ModuleRank = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "moduleRank")); |
| section_cper->Device = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "device")); |
| section_cper->Row = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "row")); |
| section_cper->Column = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "column")); |
| section_cper->BitPosition = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "bitPosition")); |
| section_cper->RequestorId = json_object_get_uint64( |
| json_object_object_get(section, "requestorID")); |
| section_cper->ResponderId = json_object_get_uint64( |
| json_object_object_get(section, "responderID")); |
| section_cper->TargetId = json_object_get_uint64( |
| json_object_object_get(section, "targetID")); |
| section_cper->RankNum = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "rankNumber")); |
| section_cper->CardHandle = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "cardSmbiosHandle")); |
| section_cper->ModuleHandle = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "moduleSmbiosHandle")); |
| |
| //Write to stream, free up resources. |
| fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA), 1, out); |
| fflush(out); |
| free(section_cper); |
| } |
| |
| //Converts a single Memory Error 2 IR section into CPER binary, outputting to the provided stream. |
| void ir_section_memory2_to_cper(json_object *section, FILE *out) |
| { |
| EFI_PLATFORM_MEMORY2_ERROR_DATA *section_cper = |
| (EFI_PLATFORM_MEMORY2_ERROR_DATA *)calloc( |
| 1, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA)); |
| |
| //Validation bits. |
| section_cper->ValidFields = ir_to_bitfield( |
| json_object_object_get(section, "validationBits"), 22, |
| MEMORY_ERROR_2_VALID_BITFIELD_NAMES); |
| |
| //Error status. |
| ir_generic_error_status_to_cper(json_object_object_get(section, |
| "errorStatus"), |
| §ion_cper->ErrorStatus); |
| |
| //Bank. |
| json_object *bank = json_object_object_get(section, "bank"); |
| if ((section_cper->ValidFields >> 5) & 0x1) { |
| //Bank just uses simple address. |
| section_cper->Bank = (UINT16)json_object_get_uint64( |
| json_object_object_get(bank, "value")); |
| } else { |
| //Bank uses address/group style address. |
| UINT16 address = (UINT8)json_object_get_uint64( |
| json_object_object_get(bank, "address")); |
| UINT16 group = (UINT8)json_object_get_uint64( |
| json_object_object_get(bank, "group")); |
| section_cper->Bank = address + (group << 8); |
| } |
| |
| //Miscellaneous value fields. |
| section_cper->MemErrorType = readable_pair_to_integer( |
| json_object_object_get(section, "memoryErrorType")); |
| section_cper->Status = (UINT8)readable_pair_to_integer( |
| json_object_object_get(section, "status")); |
| section_cper->PhysicalAddress = json_object_get_uint64( |
| json_object_object_get(section, "physicalAddress")); |
| section_cper->PhysicalAddressMask = json_object_get_uint64( |
| json_object_object_get(section, "physicalAddressMask")); |
| section_cper->Node = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "node")); |
| section_cper->Card = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "card")); |
| section_cper->Module = (UINT32)json_object_get_uint64( |
| json_object_object_get(section, "module")); |
| section_cper->Device = (UINT32)json_object_get_uint64( |
| json_object_object_get(section, "device")); |
| section_cper->Row = (UINT32)json_object_get_uint64( |
| json_object_object_get(section, "row")); |
| section_cper->Column = (UINT32)json_object_get_uint64( |
| json_object_object_get(section, "column")); |
| section_cper->Rank = (UINT32)json_object_get_uint64( |
| json_object_object_get(section, "rank")); |
| section_cper->BitPosition = (UINT32)json_object_get_uint64( |
| json_object_object_get(section, "bitPosition")); |
| section_cper->ChipId = (UINT8)json_object_get_uint64( |
| json_object_object_get(section, "chipID")); |
| section_cper->RequestorId = json_object_get_uint64( |
| json_object_object_get(section, "requestorID")); |
| section_cper->ResponderId = json_object_get_uint64( |
| json_object_object_get(section, "responderID")); |
| section_cper->TargetId = json_object_get_uint64( |
| json_object_object_get(section, "targetID")); |
| section_cper->CardHandle = (UINT32)json_object_get_uint64( |
| json_object_object_get(section, "cardSmbiosHandle")); |
| section_cper->ModuleHandle = (UINT32)json_object_get_uint64( |
| json_object_object_get(section, "moduleSmbiosHandle")); |
| |
| //Write to stream, free up resources. |
| fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA), 1, out); |
| fflush(out); |
| free(section_cper); |
| } |