Add support for AMPERE CPERs

Support Ampere CPER entries

Change-Id: I607a89209138fa53914c55c07aba8b7d6f382e5e
Signed-off-by: Dung Cao <dung@os.amperecomputing.com>
diff --git a/edk/Cper.c b/edk/Cper.c
index 218589b..a4d5713 100644
--- a/edk/Cper.c
+++ b/edk/Cper.c
@@ -215,3 +215,9 @@
 					0x11ec,
 					{ 0xbe, 0xa7, 0xcb, 0x3f, 0xdb, 0x95,
 					  0xc7, 0x86 } };
+
+EFI_GUID gEfiAmpereErrorSectionGuid = { 0x2826cc9f,
+					0x448c,
+					0x4c2b,
+					{ 0x86, 0xb6, 0xa9, 0x53, 0x94, 0xb7,
+					  0xef, 0x33 } };
diff --git a/edk/Cper.h b/edk/Cper.h
index 57e2657..a982d18 100644
--- a/edk/Cper.h
+++ b/edk/Cper.h
@@ -299,6 +299,13 @@
 			0xa7, 0x9e, 0x57, 0x5f, 0xdf, 0xaa, 0x84, 0xec         \
 		}                                                              \
 	}
+#define EFI_ERROR_SECTION_AMPERE_SPECIFIC_GUID                                 \
+	{                                                                      \
+		0x2826cc9f, 0x448c, 0x4c2b,                                    \
+		{                                                              \
+			0x86, 0xb6, 0xa9, 0x53, 0x94, 0xb7, 0xef, 0x33         \
+		}                                                              \
+	}
 ///@}
 
 ///
@@ -1414,6 +1421,18 @@
 } EFI_NVIDIA_ERROR_DATA;
 
 extern EFI_GUID gEfiNvidiaErrorSectionGuid;
+
+///
+/// Ampere Error Record Section
+///
+typedef struct {
+	UINT16 TypeId;
+	UINT16 SubtypeId;
+	UINT32 InstanceId;
+} __attribute__((packed)) EFI_AMPERE_ERROR_DATA;
+
+extern EFI_GUID gEfiAmpereErrorSectionGuid;
+
 #pragma pack(pop)
 
 #ifdef __cplusplus
diff --git a/generator/sections/gen-section-ampere.c b/generator/sections/gen-section-ampere.c
new file mode 100644
index 0000000..85fa765
--- /dev/null
+++ b/generator/sections/gen-section-ampere.c
@@ -0,0 +1,30 @@
+/**
+ * Functions for generating pseudo-random CPER AMPERE error sections.
+ *
+ **/
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "../../edk/BaseTypes.h"
+#include "../gen-utils.h"
+#include "gen-section.h"
+
+//Generates a single pseudo-random Ampere error section, saving the resulting address to the given
+//location. Returns the size of the newly created section.
+size_t generate_section_ampere(void **location)
+{
+	//Create random bytes.
+	size_t size = sizeof(EFI_AMPERE_ERROR_DATA);
+	UINT8 *section = generate_random_bytes(size);
+
+	//Reserved byte.
+	EFI_AMPERE_ERROR_DATA *ampere_error = (EFI_AMPERE_ERROR_DATA *)section;
+	ampere_error->TypeId = 10;
+	ampere_error->SubtypeId = 1;
+	ampere_error->InstanceId = 0;
+
+	//Set return values, exit.
+	*location = section;
+	return size;
+}
diff --git a/generator/sections/gen-section.c b/generator/sections/gen-section.c
index 819ebdb..56b6d84 100644
--- a/generator/sections/gen-section.c
+++ b/generator/sections/gen-section.c
@@ -43,6 +43,7 @@
 	{ &gEfiCxlMldPortErrorSectionGuid, "cxlcomponent-mld",
 	  generate_section_cxl_component },
 	{ &gEfiNvidiaErrorSectionGuid, "nvidia", generate_section_nvidia },
+	{ &gEfiAmpereErrorSectionGuid, "ampere", generate_section_ampere },
 };
 const size_t generator_definitions_len =
 	sizeof(generator_definitions) / sizeof(CPER_GENERATOR_DEFINITION);
diff --git a/generator/sections/gen-section.h b/generator/sections/gen-section.h
index d1987b9..1c6e227 100644
--- a/generator/sections/gen-section.h
+++ b/generator/sections/gen-section.h
@@ -25,6 +25,7 @@
 size_t generate_section_cxl_protocol(void **location);
 size_t generate_section_cxl_component(void **location);
 size_t generate_section_nvidia(void **location);
+size_t generate_section_ampere(void **location);
 
 //Definition structure for a single CPER section generator.
 typedef struct {
diff --git a/meson.build b/meson.build
index 10c05fe..1eee4ec 100644
--- a/meson.build
+++ b/meson.build
@@ -42,6 +42,7 @@
     'sections/cper-section-pci-dev.c',
     'sections/cper-section-pcie.c',
     'sections/cper-section.c',
+    'sections/cper-section-ampere.c',
 )
 
 edk_sources = files('edk/Cper.c')
@@ -61,6 +62,7 @@
     'generator/sections/gen-section-pci-dev.c',
     'generator/sections/gen-section-pcie.c',
     'generator/sections/gen-section.c',
+    'generator/sections/gen-section-ampere.c',
 )
 
 cc = meson.get_compiler('c')
diff --git a/sections/cper-section-ampere.c b/sections/cper-section-ampere.c
new file mode 100644
index 0000000..264c2f6
--- /dev/null
+++ b/sections/cper-section-ampere.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+#include <json.h>
+#include "../edk/Cper.h"
+#include "../cper-utils.h"
+#include "cper-section-ampere.h"
+
+//Converts the given processor-generic CPER section into JSON IR.
+json_object *cper_section_ampere_to_ir(void *section)
+{
+	EFI_AMPERE_ERROR_DATA *record = (EFI_AMPERE_ERROR_DATA *)section;
+	json_object *section_ir = json_object_new_object();
+
+	json_object_object_add(section_ir, "typeId",
+			       json_object_new_int(record->TypeId));
+	json_object_object_add(section_ir, "subTypeId",
+			       json_object_new_int(record->SubtypeId));
+	json_object_object_add(section_ir, "instanceId",
+			       json_object_new_int(record->InstanceId));
+
+	return section_ir;
+}
+
+//Converts a single CPER-JSON ARM error section into CPER binary, outputting to the given stream.
+void ir_section_ampere_to_cper(json_object *section, FILE *out)
+{
+	EFI_AMPERE_ERROR_DATA *section_cper = (EFI_AMPERE_ERROR_DATA *)calloc(
+		1, sizeof(EFI_AMPERE_ERROR_DATA));
+
+	//Count of error/context info structures.
+	section_cper->TypeId =
+		json_object_get_int(json_object_object_get(section, "typeId"));
+	section_cper->SubtypeId = json_object_get_int(
+		json_object_object_get(section, "subTypeId"));
+	section_cper->InstanceId = json_object_get_int(
+		json_object_object_get(section, "instanceId"));
+
+	//Flush header to stream.
+	fwrite(section_cper, sizeof(EFI_AMPERE_ERROR_DATA), 1, out);
+	fflush(out);
+	free(section_cper);
+}
diff --git a/sections/cper-section-ampere.h b/sections/cper-section-ampere.h
new file mode 100644
index 0000000..9264098
--- /dev/null
+++ b/sections/cper-section-ampere.h
@@ -0,0 +1,10 @@
+#ifndef CPER_SECTION_AMPERE_H
+#define CPER_SECTION_AMPERE_H
+
+#include <json.h>
+#include "../edk/Cper.h"
+
+json_object *cper_section_ampere_to_ir(void *section);
+void ir_section_ampere_to_cper(json_object *section, FILE *out);
+
+#endif
diff --git a/sections/cper-section.c b/sections/cper-section.c
index 1845118..defecf6 100644
--- a/sections/cper-section.c
+++ b/sections/cper-section.c
@@ -21,6 +21,7 @@
 #include "cper-section-cxl-protocol.h"
 #include "cper-section-cxl-component.h"
 #include "cper-section-nvidia.h"
+#include "cper-section-ampere.h"
 
 //Definitions of all sections available to the CPER parser.
 CPER_SECTION_DEFINITION section_definitions[] = {
@@ -72,6 +73,8 @@
 	  cper_section_cxl_component_to_ir, ir_section_cxl_component_to_cper },
 	{ &gEfiNvidiaErrorSectionGuid, "NVIDIA", cper_section_nvidia_to_ir,
 	  ir_section_nvidia_to_cper },
+	{ &gEfiAmpereErrorSectionGuid, "Ampere", cper_section_ampere_to_ir,
+	  ir_section_ampere_to_cper },
 };
 const size_t section_definitions_len =
 	sizeof(section_definitions) / sizeof(CPER_SECTION_DEFINITION);
diff --git a/specification/json/cper-json-full-log.json b/specification/json/cper-json-full-log.json
index 029ce2f..b4dd875 100644
--- a/specification/json/cper-json-full-log.json
+++ b/specification/json/cper-json-full-log.json
@@ -34,6 +34,7 @@
                     { "$ref": "./sections/cper-cxl-protocol.json" },
                     { "$ref": "./sections/cper-cxl-component.json" },
                     { "$ref": "./sections/cper-nvidia.json" },
+                    { "$ref": "./sections/cper-ampere.json" },
                     { "$ref": "./sections/cper-unknown.json" }
                 ]
             }
diff --git a/specification/json/cper-json-section-log.json b/specification/json/cper-json-section-log.json
index 4287316..0909197 100644
--- a/specification/json/cper-json-section-log.json
+++ b/specification/json/cper-json-section-log.json
@@ -28,6 +28,7 @@
                 { "$ref": "./sections/cper-cxl-protocol.json" },
                 { "$ref": "./sections/cper-cxl-component.json" },
                 { "$ref": "./sections/cper-nvidia.json" },
+                { "$ref": "./sections/cper-ampere.json" },
                 { "$ref": "./sections/cper-unknown.json" }
             ]
         }
diff --git a/specification/json/sections/cper-ampere.json b/specification/json/sections/cper-ampere.json
new file mode 100644
index 0000000..64d1d3f
--- /dev/null
+++ b/specification/json/sections/cper-ampere.json
@@ -0,0 +1,18 @@
+{
+    "$id": "cper-json-ampere-section",
+    "$schema": "https://json-schema.org/draft/2020-12/schema",
+    "type": "object",
+    "required": ["typeId", "subTypeId", "instanceId"],
+    "additionalProperties": false,
+    "properties": {
+        "typeId": {
+            "type": "integer"
+        },
+        "subTypeId": {
+            "type": "integer"
+        },
+        "instanceId": {
+            "type": "integer"
+        }
+    }
+}