Add more detailed ARM error structures.
diff --git a/cper-utils.c b/cper-utils.c
index 00581e2..f70cf54 100644
--- a/cper-utils.c
+++ b/cper-utils.c
@@ -30,32 +30,8 @@
return result;
}
-//Converts the given uint8 bitfield to IR, assuming bit 0 starts on the left.
-json_object* bitfield8_to_ir(UINT8 bitfield, int num_fields, const char* names[])
-{
- json_object* result = json_object_new_object();
- for (int i=0; i<num_fields; i++)
- {
- json_object_object_add(result, names[i], json_object_new_boolean((bitfield >> i) & 0b1));
- }
-
- return result;
-}
-
-//Converts the given bitfield to IR, assuming bit 0 starts on the left.
-json_object* bitfield_to_ir(UINT32 bitfield, int num_fields, const char* names[])
-{
- json_object* result = json_object_new_object();
- for (int i=0; i<num_fields; i++)
- {
- json_object_object_add(result, names[i], json_object_new_boolean((bitfield >> i) & 0b1));
- }
-
- return result;
-}
-
//Converts the given 64 bit bitfield to IR, assuming bit 0 starts on the left.
-json_object* bitfield64_to_ir(UINT64 bitfield, int num_fields, const char* names[])
+json_object* bitfield_to_ir(UINT64 bitfield, int num_fields, const char* names[])
{
json_object* result = json_object_new_object();
for (int i=0; i<num_fields; i++)
diff --git a/cper-utils.h b/cper-utils.h
index 9446237..c38a4a8 100644
--- a/cper-utils.h
+++ b/cper-utils.h
@@ -5,9 +5,7 @@
#define TIMESTAMP_LENGTH 24
json_object* integer_to_readable_pair(int value, int len, int keys[], const char* values[], const char* default_value);
-json_object* bitfield8_to_ir(UINT8 bitfield, int num_fields, const char* names[]);
-json_object* bitfield_to_ir(UINT32 bitfield, int num_fields, const char* names[]);
-json_object* bitfield64_to_ir(UINT64 bitfield, int num_fields, const char* names[]);
+json_object* bitfield_to_ir(UINT64 bitfield, int num_fields, const char* names[]);
json_object* revision_to_ir(UINT16 revision);
const char* severity_to_string(UINT8 severity);
void guid_to_string(char* out, EFI_GUID* guid);
diff --git a/edk/Cper.h b/edk/Cper.h
index d8d0f41..7d14d23 100644
--- a/edk/Cper.h
+++ b/edk/Cper.h
@@ -741,7 +741,7 @@
///
-/// ARM Processor Error Structure
+/// ARM Processor Error Record
///
typedef struct {
UINT32 ValidFields;
@@ -756,6 +756,68 @@
} EFI_ARM_PROCESSOR_ERROR_RECORD;
///
+/// ARM Processor Error Information Structure
+///
+typedef struct {
+ UINT8 Version;
+ UINT8 Length;
+ UINT16 ValidationBits;
+ UINT8 Type;
+ UINT16 MultipleError;
+ UINT8 Flags;
+ EFI_ARM_PROCESSOR_ERROR_INFORMATION_STRUCTURE ErrorInformation;
+ UINT64 VirtualFaultAddress;
+ UINT64 PhysicalFaultAddress;
+} EFI_ARM_PROCESSOR_ERROR_INFORMATION_ENTRY;
+
+typedef union {
+ EFI_ARM_PROCESSOR_CACHE_ERROR_STRUCTURE CacheError;
+ EFI_ARM_PROCESSOR_TLB_ERROR_STRUCTURE TlbError;
+ EFI_ARM_PROCESSOR_BUS_ERROR_STRUCTURE BusError;
+} EFI_ARM_PROCESSOR_ERROR_INFORMATION_STRUCTURE;
+
+typedef struct {
+ UINT64 ValidationBits : 16;
+ UINT64 TransactionType : 2;
+ UINT64 Operation : 4;
+ UINT64 Level : 3;
+ UINT64 ProcessorContextInterrupt : 1;
+ UINT64 Corrected : 1;
+ UINT64 PrecisePC : 1;
+ UINT64 RestartablePC : 1;
+ UINT64 Reserved : 34;
+} EFI_ARM_PROCESSOR_CACHE_ERROR_STRUCTURE;
+
+typedef struct {
+ UINT64 ValidationBits : 16;
+ UINT64 TransactionType : 2;
+ UINT64 Operation : 4;
+ UINT64 Level : 3;
+ UINT64 ProcessorContextInterrupt : 1;
+ UINT64 Corrected : 1;
+ UINT64 PrecisePC : 1;
+ UINT64 RestartablePC : 1;
+ UINT64 Reserved : 34;
+} EFI_ARM_PROCESSOR_TLB_ERROR_STRUCTURE;
+
+typedef struct {
+ UINT64 ValidationBits : 16;
+ UINT64 TransactionType : 2;
+ UINT64 Operation : 4;
+ UINT64 Level : 3;
+ UINT64 ProcessorContextInterrupt : 1;
+ UINT64 Corrected : 1;
+ UINT64 PrecisePC : 1;
+ UINT64 RestartablePC : 1;
+ UINT64 ParticipationType : 2;
+ UINT64 TimeOut : 1;
+ UINT64 AddressSpace : 2;
+ UINT64 MemoryAddressAttributes : 8;
+ UINT64 AccessMode : 1;
+ UINT64 Reserved : 19;
+} EFI_ARM_PROCESSOR_BUS_ERROR_STRUCTURE;
+
+///
/// Error Status Fields
///
typedef struct {
diff --git a/sections/cper-section-arm.c b/sections/cper-section-arm.c
index 4dcb6c3..cda8252 100644
--- a/sections/cper-section-arm.c
+++ b/sections/cper-section-arm.c
@@ -11,6 +11,12 @@
#include "../cper-utils.h"
#include "cper-section-arm.h"
+//Private pre-definitions.
+json_object* cper_arm_error_info_to_ir(EFI_ARM_PROCESSOR_ERROR_INFORMATION_ENTRY* error_info, void** cur_pos);
+json_object* cper_arm_cache_error_to_ir(EFI_ARM_PROCESSOR_CACHE_ERROR_STRUCTURE* cache_error);
+json_object* cper_arm_tlb_error_to_ir(EFI_ARM_PROCESSOR_TLB_ERROR_STRUCTURE* tlb_error);
+json_object* cper_arm_bus_error_to_ir(EFI_ARM_PROCESSOR_BUS_ERROR_STRUCTURE* bus_error);
+
//Converts the given processor-generic CPER section into JSON IR.
json_object* cper_section_arm_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
{
@@ -39,10 +45,89 @@
//Whether the processor is running, and the state of it if so.
json_object_object_add(section_ir, "running", json_object_new_boolean(record->RunningState));
- if (record->RunningState)
+ if (record->RunningState >> 31)
{
- //...
+ //Bit 32 of running state is on, so PSCI state information is included.
+ //todo: Look at how to make this human readable from the ARM PSCI document.
+ json_object_object_add(section_ir, "psciState", json_object_new_int(record->PsciState));
}
+ //Processor error structures.
+ json_object* error_info_array = json_object_new_array();
+ EFI_ARM_PROCESSOR_ERROR_INFORMATION_ENTRY* cur_error = (EFI_ARM_PROCESSOR_ERROR_INFORMATION_ENTRY*)(record + 1);
+ for (int i=0; i<record->ErrInfoNum; i++)
+ {
+ json_object_array_add(error_info_array, cper_arm_error_info_to_ir(cur_error, (void*)&cur_error));
+ //Dynamically sized structure, so pointer is controlled within the above function.
+ }
return section_ir;
+}
+
+//Converts a single ARM Process Error Information structure into JSON IR.
+json_object* cper_arm_error_info_to_ir(EFI_ARM_PROCESSOR_ERROR_INFORMATION_ENTRY* error_info, void** cur_pos)
+{
+ json_object* error_info_ir = json_object_new_object();
+
+ //Version, length.
+ json_object_object_add(error_info_ir, "version", json_object_new_int(error_info->Version));
+ json_object_object_add(error_info_ir, "version", json_object_new_int(error_info->Length));
+
+ //Validation bitfield.
+ json_object* validation = bitfield_to_ir(error_info->ValidationBits, 5, ARM_PROCESSOR_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES);
+ json_object_object_add(error_info_ir, "validationBits", validation);
+
+ //The type of error information in this log.
+ //todo: The UEFI spec is ambiguous, what are the values for these??
+ json_object* error_type = integer_to_readable_pair(error_info->Type, 4,
+ ARM_PROCESSOR_ERROR_INFO_ENTRY_INFO_TYPES_KEYS,
+ ARM_PROCESSOR_ERROR_INFO_ENTRY_INFO_TYPES_VALUES,
+ "Unknown (Reserved)");
+ json_object_object_add(error_info_ir, "errorType", error_type);
+
+ //Multiple error count.
+ json_object* multiple_error = json_object_object_create();
+ json_object_object_add(multiple_error, "value", json_object_new_int(error_info->MultipleError));
+ json_object_object_add(multiple_error, "type",
+ json_object_new_string(error_info->MultipleError < 1 ? "Single Error" : "Multiple Errors"));
+ json_object_object_add(error_info_ir, "multipleError", multiple_error);
+
+ //Flags.
+ json_object* flags = bitfield_to_ir(error_info->Flags, 4, ARM_PROCESSOR_ERROR_INFO_ENTRY_FLAGS_NAMES);
+ json_object_object_add(error_info_ir, "flags", flags);
+
+ //Error information, split by type.
+ json_object* error_subinfo = NULL;
+ switch (error_info->Type)
+ {
+ case 0: //Cache
+ error_subinfo = cper_arm_cache_error_to_ir((EFI_ARM_PROCESSOR_CACHE_ERROR_STRUCTURE*)error_info->ErrorInformation);
+ break;
+ case 1: //TLB
+ error_subinfo = cper_arm_tlb_error_to_ir((EFI_ARM_PROCESSOR_TLB_ERROR_STRUCTURE*)error_info->ErrorInformation);
+ break;
+ case 2: //Bus
+ error_subinfo = cper_arm_bus_error_to_ir((EFI_ARM_PROCESSOR_BUS_ERROR_STRUCTURE*)error_info->ErrorInformation);
+ break;
+ }
+ json_object_object_add(error_info_ir, "errorInformation", error_subinfo);
+
+ return error_info_ir;
+}
+
+//Converts a single ARM cache error information structure into JSON IR format.
+json_object* cper_arm_cache_error_to_ir(EFI_ARM_PROCESSOR_CACHE_ERROR_STRUCTURE* cache_error)
+{
+ //todo
+}
+
+//Converts a single ARM TLB error information structure into JSON IR format.
+json_object* cper_arm_tlb_error_to_ir(EFI_ARM_PROCESSOR_TLB_ERROR_STRUCTURE* tlb_error)
+{
+ //todo
+}
+
+//Converts a single ARM bus error information structure into JSON IR format.
+json_object* cper_arm_bus_error_to_ir(EFI_ARM_PROCESSOR_BUS_ERROR_STRUCTURE* bus_error)
+{
+ //todo
}
\ No newline at end of file
diff --git a/sections/cper-section-arm.h b/sections/cper-section-arm.h
index 2112442..98dd36c 100644
--- a/sections/cper-section-arm.h
+++ b/sections/cper-section-arm.h
@@ -6,7 +6,14 @@
#define ARM_PROCESSOR_ERROR_VALID_BITFIELD_NAMES (const char*[]) \
{"mpidrValid", "errorAffinityLevelValid", "runningStateValid", "vendorSpecificInfoValid"}
-
+#define ARM_PROCESSOR_ERROR_INFO_ENTRY_VALID_BITFIELD_NAMES (const char*[]) \
+ {"multipleErrorValid", "flagsValid", "errorInformationValid", "virtualFaultAddressValid", "physicalFaultAddressValid"}
+#define ARM_PROCESSOR_ERROR_INFO_ENTRY_FLAGS_NAMES (const char*[]) \
+ {"firstErrorCaptured", "lastErrorCaptured", "propagated", "overflow"}
+#define ARM_PROCESSOR_ERROR_INFO_ENTRY_INFO_TYPES_KEYS (int []){0, 1, 2, 3}
+#define ARM_PROCESSOR_ERROR_INFO_ENTRY_INFO_TYPES_VALUES (const char*[]){"Cache Error", "TLB Error", \
+ "Bus Error", "Micro-Architectural Error"}
+
json_object* cper_section_arm_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor);
#endif
\ No newline at end of file