| /** |
| * 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(); |
| |
| ValidationTypes ui64Type = { UINT_64T, |
| .value.ui64 = memory_error->ValidFields }; |
| |
| //Error status. |
| if (isvalid_prop_to_ir(&ui64Type, 0)) { |
| 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 (isvalid_prop_to_ir(&ui64Type, 6)) { |
| //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. |
| if (isvalid_prop_to_ir(&ui64Type, 14)) { |
| 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. |
| // Review this |
| if (isvalid_prop_to_ir(&ui64Type, 18)) { |
| 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)); |
| if (isvalid_prop_to_ir(&ui64Type, 21)) { |
| json_object_object_add( |
| extended, "chipIdentification", |
| json_object_new_int(memory_error->Extended >> |
| 5)); |
| } |
| json_object_object_add(section_ir, "extended", extended); |
| |
| //bit 16 and 17 are valid only if extended is valid |
| if (isvalid_prop_to_ir(&ui64Type, 16)) { |
| json_object_object_add( |
| section_ir, "cardSmbiosHandle", |
| json_object_new_uint64( |
| memory_error->CardHandle)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 17)) { |
| json_object_object_add( |
| section_ir, "moduleSmbiosHandle", |
| json_object_new_uint64( |
| memory_error->ModuleHandle)); |
| } |
| } |
| |
| //Miscellaneous numeric fields. |
| if (isvalid_prop_to_ir(&ui64Type, 1)) { |
| 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)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 2)) { |
| json_object_object_add( |
| section_ir, "physicalAddressMask", |
| json_object_new_uint64( |
| memory_error->PhysicalAddressMask)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 3)) { |
| json_object_object_add( |
| section_ir, "node", |
| json_object_new_uint64(memory_error->Node)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 4)) { |
| json_object_object_add( |
| section_ir, "card", |
| json_object_new_uint64(memory_error->Card)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 5)) { |
| json_object_object_add( |
| section_ir, "moduleRank", |
| json_object_new_uint64(memory_error->ModuleRank)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 7)) { |
| json_object_object_add( |
| section_ir, "device", |
| json_object_new_uint64(memory_error->Device)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 8)) { |
| json_object_object_add( |
| section_ir, "row", |
| json_object_new_uint64(memory_error->Row)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 9)) { |
| json_object_object_add( |
| section_ir, "column", |
| json_object_new_uint64(memory_error->Column)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 10)) { |
| json_object_object_add( |
| section_ir, "bitPosition", |
| json_object_new_uint64(memory_error->BitPosition)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 11)) { |
| json_object_object_add( |
| section_ir, "requestorID", |
| json_object_new_uint64(memory_error->RequestorId)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 12)) { |
| json_object_object_add( |
| section_ir, "responderID", |
| json_object_new_uint64(memory_error->ResponderId)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 13)) { |
| json_object_object_add( |
| section_ir, "targetID", |
| json_object_new_uint64(memory_error->TargetId)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 15)) { |
| json_object_object_add( |
| section_ir, "rankNumber", |
| json_object_new_uint64(memory_error->RankNum)); |
| } |
| |
| 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(); |
| |
| ValidationTypes ui64Type = { UINT_64T, |
| .value.ui64 = memory_error->ValidFields }; |
| |
| //Error status. |
| if (isvalid_prop_to_ir(&ui64Type, 0)) { |
| 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 (isvalid_prop_to_ir(&ui64Type, 6)) { |
| //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. |
| if (isvalid_prop_to_ir(&ui64Type, 13)) { |
| 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. |
| if (isvalid_prop_to_ir(&ui64Type, 14)) { |
| 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. |
| if (isvalid_prop_to_ir(&ui64Type, 0)) { |
| 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)); |
| |
| if (isvalid_prop_to_ir(&ui64Type, 2)) { |
| json_object_object_add( |
| section_ir, "physicalAddressMask", |
| json_object_new_uint64( |
| memory_error->PhysicalAddressMask)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 3)) { |
| json_object_object_add( |
| section_ir, "node", |
| json_object_new_uint64(memory_error->Node)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 4)) { |
| json_object_object_add( |
| section_ir, "card", |
| json_object_new_uint64(memory_error->Card)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 5)) { |
| json_object_object_add( |
| section_ir, "module", |
| json_object_new_uint64(memory_error->Module)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 7)) { |
| json_object_object_add( |
| section_ir, "device", |
| json_object_new_uint64(memory_error->Device)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 8)) { |
| json_object_object_add( |
| section_ir, "row", |
| json_object_new_uint64(memory_error->Row)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 9)) { |
| json_object_object_add( |
| section_ir, "column", |
| json_object_new_uint64(memory_error->Column)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 10)) { |
| json_object_object_add( |
| section_ir, "rank", |
| json_object_new_uint64(memory_error->Rank)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 11)) { |
| json_object_object_add( |
| section_ir, "bitPosition", |
| json_object_new_uint64(memory_error->BitPosition)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 12)) { |
| json_object_object_add( |
| section_ir, "chipID", |
| json_object_new_uint64(memory_error->ChipId)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 15)) { |
| json_object_object_add( |
| section_ir, "requestorID", |
| json_object_new_uint64(memory_error->RequestorId)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 16)) { |
| json_object_object_add( |
| section_ir, "responderID", |
| json_object_new_uint64(memory_error->ResponderId)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 17)) { |
| json_object_object_add( |
| section_ir, "targetID", |
| json_object_new_uint64(memory_error->TargetId)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 18)) { |
| json_object_object_add( |
| section_ir, "cardSmbiosHandle", |
| json_object_new_uint64(memory_error->CardHandle)); |
| } |
| if (isvalid_prop_to_ir(&ui64Type, 19)) { |
| 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)); |
| |
| ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 }; |
| struct json_object *obj = NULL; |
| |
| //Error status. |
| if (json_object_object_get_ex(section, "errorStatus", &obj)) { |
| ir_generic_error_status_to_cper(obj, |
| §ion_cper->ErrorStatus); |
| add_to_valid_bitfield(&ui64Type, 0); |
| } |
| |
| //Bank. |
| if (json_object_object_get_ex(section, "bank", &obj)) { |
| json_object *bank = obj; |
| if (json_object_object_get_ex(bank, "value", &obj)) { |
| //Bank just uses simple address. |
| section_cper->Bank = |
| (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 6); |
| } 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); |
| add_to_valid_bitfield(&ui64Type, 19); |
| add_to_valid_bitfield(&ui64Type, 20); |
| } |
| } |
| |
| //"Extended" field. |
| if (json_object_object_get_ex(section, "extended", &obj)) { |
| json_object *extended = obj; |
| 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; |
| if (json_object_object_get_ex(extended, "chipIdentification", |
| &obj)) { |
| section_cper->Extended |= json_object_get_int(obj) << 5; |
| add_to_valid_bitfield(&ui64Type, 21); |
| } |
| add_to_valid_bitfield(&ui64Type, 18); |
| } |
| |
| //Miscellaneous value fields. |
| if (json_object_object_get_ex(section, "memoryErrorType", &obj)) { |
| section_cper->ErrorType = (UINT8)readable_pair_to_integer(obj); |
| add_to_valid_bitfield(&ui64Type, 14); |
| } |
| if (json_object_object_get_ex(section, "physicalAddress", &obj)) { |
| section_cper->PhysicalAddress = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 1); |
| } |
| if (json_object_object_get_ex(section, "physicalAddressMask", &obj)) { |
| section_cper->PhysicalAddressMask = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 2); |
| } |
| if (json_object_object_get_ex(section, "node", &obj)) { |
| section_cper->Node = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 3); |
| } |
| if (json_object_object_get_ex(section, "card", &obj)) { |
| section_cper->Card = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 4); |
| } |
| if (json_object_object_get_ex(section, "moduleRank", &obj)) { |
| section_cper->ModuleRank = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 5); |
| } |
| if (json_object_object_get_ex(section, "device", &obj)) { |
| section_cper->Device = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 7); |
| } |
| if (json_object_object_get_ex(section, "row", &obj)) { |
| section_cper->Row = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 8); |
| } |
| if (json_object_object_get_ex(section, "column", &obj)) { |
| section_cper->Column = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 9); |
| } |
| if (json_object_object_get_ex(section, "bitPosition", &obj)) { |
| section_cper->BitPosition = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 10); |
| } |
| if (json_object_object_get_ex(section, "requestorID", &obj)) { |
| section_cper->RequestorId = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 11); |
| } |
| if (json_object_object_get_ex(section, "responderID", &obj)) { |
| section_cper->ResponderId = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 12); |
| } |
| if (json_object_object_get_ex(section, "targetID", &obj)) { |
| section_cper->TargetId = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 13); |
| } |
| if (json_object_object_get_ex(section, "rankNumber", &obj)) { |
| section_cper->RankNum = (UINT16)json_object_get_uint64( |
| json_object_object_get(section, "rankNumber")); |
| add_to_valid_bitfield(&ui64Type, 15); |
| } |
| if (json_object_object_get_ex(section, "cardSmbiosHandle", &obj)) { |
| section_cper->CardHandle = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 16); |
| } |
| if (json_object_object_get_ex(section, "moduleSmbiosHandle", &obj)) { |
| section_cper->ModuleHandle = |
| (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 17); |
| } |
| section_cper->ValidFields = ui64Type.value.ui64; |
| |
| //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. |
| ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 }; |
| struct json_object *obj = NULL; |
| |
| //Error status. |
| if (json_object_object_get_ex(section, "errorStatus", &obj)) { |
| ir_generic_error_status_to_cper(obj, |
| §ion_cper->ErrorStatus); |
| add_to_valid_bitfield(&ui64Type, 0); |
| } |
| |
| //Bank. |
| json_object *bank = json_object_object_get(section, "bank"); |
| if (json_object_object_get_ex(bank, "value", &obj)) { |
| //Bank just uses simple address. |
| section_cper->Bank = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 6); |
| } 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); |
| add_to_valid_bitfield(&ui64Type, 20); |
| add_to_valid_bitfield(&ui64Type, 21); |
| } |
| |
| //Miscellaneous value fields. |
| if (json_object_object_get_ex(section, "memoryErrorType", &obj)) { |
| section_cper->MemErrorType = readable_pair_to_integer(obj); |
| add_to_valid_bitfield(&ui64Type, 13); |
| } |
| if (json_object_object_get_ex(section, "status", &obj)) { |
| section_cper->Status = (UINT8)readable_pair_to_integer(obj); |
| add_to_valid_bitfield(&ui64Type, 14); |
| } |
| if (json_object_object_get_ex(section, "physicalAddress", &obj)) { |
| section_cper->PhysicalAddress = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 1); |
| } |
| if (json_object_object_get_ex(section, "physicalAddressMask", &obj)) { |
| section_cper->PhysicalAddressMask = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 2); |
| } |
| if (json_object_object_get_ex(section, "node", &obj)) { |
| section_cper->Node = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 3); |
| } |
| if (json_object_object_get_ex(section, "card", &obj)) { |
| section_cper->Card = (UINT16)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 4); |
| } |
| if (json_object_object_get_ex(section, "module", &obj)) { |
| section_cper->Module = (UINT32)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 5); |
| } |
| if (json_object_object_get_ex(section, "device", &obj)) { |
| section_cper->Device = (UINT32)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 7); |
| } |
| if (json_object_object_get_ex(section, "row", &obj)) { |
| section_cper->Row = (UINT32)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 8); |
| } |
| if (json_object_object_get_ex(section, "column", &obj)) { |
| section_cper->Column = (UINT32)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 9); |
| } |
| if (json_object_object_get_ex(section, "rank", &obj)) { |
| section_cper->Rank = (UINT32)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 10); |
| } |
| if (json_object_object_get_ex(section, "bitPosition", &obj)) { |
| section_cper->BitPosition = (UINT32)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 11); |
| } |
| if (json_object_object_get_ex(section, "chipID", &obj)) { |
| section_cper->ChipId = (UINT8)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 12); |
| } |
| if (json_object_object_get_ex(section, "requestorID", &obj)) { |
| section_cper->RequestorId = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 15); |
| } |
| if (json_object_object_get_ex(section, "responderID", &obj)) { |
| section_cper->ResponderId = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 16); |
| } |
| if (json_object_object_get_ex(section, "targetID", &obj)) { |
| section_cper->TargetId = json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 17); |
| } |
| if (json_object_object_get_ex(section, "cardSmbiosHandle", &obj)) { |
| section_cper->CardHandle = (UINT32)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 18); |
| } |
| if (json_object_object_get_ex(section, "moduleSmbiosHandle", &obj)) { |
| section_cper->ModuleHandle = |
| (UINT32)json_object_get_uint64(obj); |
| add_to_valid_bitfield(&ui64Type, 19); |
| } |
| |
| section_cper->ValidFields = ui64Type.value.ui64; |
| |
| //Write to stream, free up resources. |
| fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA), 1, out); |
| fflush(out); |
| free(section_cper); |
| } |