Nvidia add cmet-info

Add decoding of more specific Error codes.

Unit tests pass.

Change-Id: Ia0ca0dfdf550381da435b0fb9041b664784f7476
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/examples/nvidia_cmet_info.cperhex b/examples/nvidia_cmet_info.cperhex
new file mode 100644
index 0000000..c643086
--- /dev/null
+++ b/examples/nvidia_cmet_info.cperhex
@@ -0,0 +1,27 @@
+435045520000ffffffff0100030000000200000028030000195023002103
+252000000000000000000000000000000000000000000000000000000000
+0000000078e401a97311ef1196a85fa6bef5eea4acd5a9090452144296e5
+94992e752bcd040000000000000000000000000000000000000000000000
+0000000000000000c8000000600200000000010000000000f244526d1227
+ec11bea7cb3fdb95c7864a334fcc63c5eb118f889f7ac76c6f0c03000000
+0000000000000000000000000000000000000000434d45542d494e464f00
+000000000000000000000300240000000000000000000000000001000080
+000000000400070001000000010000800000000001000000020000000100
+008000000000010004000300000001000080000000000100000004000000
+010000800000000001000400050000000100008000000000010000000600
+000001000080000000000100040007000000010000800000000001000000
+080000000100008000000000010004000900000001000080000000000100
+00000a0000000100008000000000010004000b0000000100008000000000
+010000000c0000000100008000000000010004000d000000010000800000
+0000010000000e0000000100008000000000010004000f00000001000080
+000000000100000010000000010000800000000001000c00110000000100
+0080000000000100080012000000010000800000000001000c0013000000
+01000080000000000100080014000000010000800000000001000c001500
+000001000080000000000100080016000000010000800000000001000c00
+170000000100008000000000010008001800000001000080000000000100
+0c00190000000100008000000000010008001a0000000100008000000000
+01000c001b0000000100008000000000010008001c000000010000800000
+000001000c001d0000000100008000000000010008001e00000001000080
+0000000001000c001f000000010000800000000001000800000000000200
+008047de1f0300000000010000000200008047de1f030000000002000000
+0200008047de1f0300000000030000000200008047de1f0300000000
\ No newline at end of file
diff --git a/examples/nvidia_cmet_info.json b/examples/nvidia_cmet_info.json
new file mode 100644
index 0000000..4c3c892
--- /dev/null
+++ b/examples/nvidia_cmet_info.json
@@ -0,0 +1,434 @@
+{
+    "header": {
+        "revision": {
+            "major": 0,
+            "minor": 0
+        },
+        "sectionCount": 1,
+        "severity": {
+            "code": 3,
+            "name": "Informational"
+        },
+        "recordLength": 808,
+        "timestamp": "2025-03-21T23:50:19+00:00",
+        "timestampIsPrecise": false,
+        "creatorID": "a901e478-1173-11ef-96a8-5fa6bef5eea4",
+        "notificationType": {
+            "guid": "09a9d5ac-5204-4214-96e5-94992e752bcd",
+            "type": "PEI"
+        },
+        "recordID": 4,
+        "flags": {
+            "value": 0,
+            "name": "Unknown"
+        },
+        "persistenceInfo": 0
+    },
+    "sectionDescriptors": [
+        {
+            "sectionOffset": 200,
+            "sectionLength": 608,
+            "revision": {
+                "major": 0,
+                "minor": 0
+            },
+            "flags": {
+                "primary": false,
+                "containmentWarning": false,
+                "reset": false,
+                "errorThresholdExceeded": false,
+                "resourceNotAccessible": false,
+                "latentError": false,
+                "propagated": false,
+                "overflow": false
+            },
+            "sectionType": {
+                "data": "6d5244f2-2712-11ec-bea7-cb3fdb95c786",
+                "type": "NVIDIA"
+            },
+            "fruID": "cc4f334a-c563-11eb-8f88-9f7ac76c6f0c",
+            "severity": {
+                "code": 3,
+                "name": "Informational"
+            }
+        }
+    ],
+    "sections": [
+        {
+            "Nvidia": {
+                "signature": "CMET-INFO",
+                "severity": {
+                    "code": 3,
+                    "name": "Informational"
+                },
+                "errorType": 0,
+                "errorInstance": 0,
+                "socket": 0,
+                "registerCount": 36,
+                "instanceBase": 0,
+                "CMETInfo": [
+                    {
+                        "ChannelAddress": "0x8000000100000000",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": false,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000001",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000002",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000003",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000004",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000005",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000006",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000007",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000008",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000009",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000000A",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000000B",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000000C",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000000D",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000000E",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000000F",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000010",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000011",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000012",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000013",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000014",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000015",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000016",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000017",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000018",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000100000019",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000001A",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000001B",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000001C",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000001D",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000001E",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x800000010000001F",
+                        "ErrorCount": 0,
+                        "ChannelEnabled": true,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000200000000",
+                        "ErrorCount": 52420167,
+                        "ChannelEnabled": false,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000200000001",
+                        "ErrorCount": 52420167,
+                        "ChannelEnabled": false,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000200000002",
+                        "ErrorCount": 52420167,
+                        "ChannelEnabled": false,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    },
+                    {
+                        "ChannelAddress": "0x8000000200000003",
+                        "ErrorCount": 52420167,
+                        "ChannelEnabled": false,
+                        "ChannelIsSpare": false,
+                        "DisabledReason": {
+                            "raw": 0,
+                            "value": "Alias Checker Failed"
+                        }
+                    }
+                ]
+            }
+        }
+    ]
+}
diff --git a/generator/sections/gen-section-nvidia.c b/generator/sections/gen-section-nvidia.c
index 83b8845..5f2fda3 100644
--- a/generator/sections/gen-section-nvidia.c
+++ b/generator/sections/gen-section-nvidia.c
@@ -24,6 +24,7 @@
 		"SOCHUB",    "CCPLEXSCF",     "CMET-NULL",     "CMET-SHA256",
 		"CMET-FULL", "DRAM-CHANNELS", "PAGES-RETIRED", "CCPLEXGIC",
 		"MCF",	     "GPU-STATUS",    "GPU-CONTNMT",   "SMMU",
+		"CMET-INFO",
 	};
 
 	//Create random bytes.
diff --git a/include/libcper/Cper.h b/include/libcper/Cper.h
index 29012ef..c4643c6 100644
--- a/include/libcper/Cper.h
+++ b/include/libcper/Cper.h
@@ -1344,8 +1344,37 @@
 /// NVIDIA Error Record Section
 ///
 typedef struct {
+	UINT32 ErrorCount;
+	UINT32 ChannelEnabled : 1;
+	UINT32 ChannelIsSpare : 1;
+	UINT32 ChannelPermanentlyDisabled : 1;
+	UINT32 DisabledReason : 2;
+	UINT32 Reserved : 27;
+} EFI_NVIDIA_CMET_CHANNEL_INFO;
+
+typedef struct {
+	CHAR8 initiating_firmware[8];
+	UINT64 task_checkpoint;
+	UINT64 mb1_error_code;
+	CHAR8 mb1_version_string[8];
+	UINT64 bad_pages_retired_mask;
+	UINT64 training_or_alias_check_retired_mask;
+	UINT32 worst_bad_pages_channel_number;
+	UINT32 worst_bad_pages_bad_page_count;
+	UINT32 second_worst_bad_pages_channel_number;
+	UINT32 second_worst_bad_pages_bad_page_count;
+	UINT32 third_worst_bad_pages_channel_number;
+	UINT32 third_worst_bad_pages_bad_page_count;
+	UINT64 mss_aon_cfg_scratch_register_0;
+	UINT64 scratch_dram_disable;
+} EFI_NVIDIA_FWERROR;
+
+typedef struct {
 	UINT64 Address;
-	UINT64 Value;
+	union {
+		UINT64 Value;
+		EFI_NVIDIA_CMET_CHANNEL_INFO CmetInfo;
+	};
 } EFI_NVIDIA_REGISTER_DATA;
 
 typedef struct {
diff --git a/include/libcper/cper-utils.h b/include/libcper/cper-utils.h
index a079900..07a961f 100644
--- a/include/libcper/cper-utils.h
+++ b/include/libcper/cper-utils.h
@@ -77,6 +77,8 @@
 		    UINT16 value);
 void add_int_hex_24(json_object *register_ir, const char *field_name,
 		    UINT64 value);
+void add_int_hex_64(json_object *register_ir, const char *field_name,
+		    UINT64 value);
 
 void add_bool(json_object *register_ir, const char *field_name, UINT64 value);
 
diff --git a/include/libcper/sections/cper-section-nvidia.h b/include/libcper/sections/cper-section-nvidia.h
index cca9097..59ac492 100644
--- a/include/libcper/sections/cper-section-nvidia.h
+++ b/include/libcper/sections/cper-section-nvidia.h
@@ -9,6 +9,17 @@
 #include <json.h>
 #include <libcper/Cper.h>
 
+static const char *channel_disable_reason_dict[] = {
+	"Alias Checker Failed",		     // 0x0
+	"Training at POR frequency failed",  // 0x1
+	"Training at boot frequency failed", // 0x2
+	"Threshold of bad pages exceeded"    // 0x3
+};
+
+static const size_t channel_disable_reason_dict_size =
+	sizeof(channel_disable_reason_dict) /
+	sizeof(channel_disable_reason_dict[0]);
+
 json_object *cper_section_nvidia_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_nvidia_to_cper(json_object *section, FILE *out);
 
diff --git a/sections/cper-section-nvidia.c b/sections/cper-section-nvidia.c
index 7cb2e87..b633396 100644
--- a/sections/cper-section-nvidia.c
+++ b/sections/cper-section-nvidia.c
@@ -12,6 +12,103 @@
 #include <libcper/sections/cper-section-nvidia.h>
 #include <libcper/log.h>
 
+void parse_cmet_info(EFI_NVIDIA_REGISTER_DATA *regPtr, UINT8 NumberRegs,
+		     size_t size, json_object *section_ir)
+{
+	json_object *regarr = json_object_new_array();
+	for (int i = 0; i < NumberRegs; i++, regPtr++) {
+		json_object *reg = NULL;
+		if (sizeof(EFI_NVIDIA_ERROR_DATA) +
+			    i * sizeof(EFI_NVIDIA_REGISTER_DATA) <
+		    size) {
+			reg = json_object_new_object();
+			add_int_hex_64(reg, "ChannelAddress", regPtr->Address);
+			add_int(reg, "ErrorCount", regPtr->CmetInfo.ErrorCount);
+			add_bool(reg, "ChannelEnabled",
+				 regPtr->CmetInfo.ChannelEnabled);
+			add_bool(reg, "ChannelIsSpare",
+				 regPtr->CmetInfo.ChannelIsSpare);
+			add_dict(reg, "DisabledReason",
+				 regPtr->CmetInfo.DisabledReason,
+				 channel_disable_reason_dict,
+				 channel_disable_reason_dict_size);
+		} else {
+			reg = json_object_new_null();
+		}
+
+		json_object_array_add(regarr, reg);
+	}
+
+	json_object_object_add(section_ir, "CMETInfo", regarr);
+}
+
+void parse_fwerror(EFI_NVIDIA_REGISTER_DATA *regPtr, UINT8 NumberRegs,
+		   size_t size, json_object *section_ir)
+{
+	(void)NumberRegs;
+	json_object *fwinfo;
+	if (sizeof(EFI_NVIDIA_ERROR_DATA) + sizeof(EFI_NVIDIA_FWERROR) > size) {
+		fwinfo = json_object_new_null();
+	} else {
+		fwinfo = json_object_new_object();
+		EFI_NVIDIA_FWERROR *fwerror = (EFI_NVIDIA_FWERROR *)regPtr;
+		add_untrusted_string(fwinfo, "initiating_firmware",
+				     fwerror->initiating_firmware,
+				     sizeof(fwerror->initiating_firmware));
+		add_int_hex_64(fwinfo, "task_checkpoint",
+			       fwerror->task_checkpoint);
+		add_int_hex_64(fwinfo, "mb1_error_code",
+			       fwerror->mb1_error_code);
+		add_untrusted_string(fwinfo, "mb1_version_string",
+				     fwerror->mb1_version_string,
+				     sizeof(fwerror->mb1_version_string));
+		add_int_hex_64(fwinfo, "bad_pages_retired_mask",
+			       fwerror->bad_pages_retired_mask);
+		add_int_hex_64(fwinfo, "training_or_alias_check_retired_mask",
+			       fwerror->training_or_alias_check_retired_mask);
+	}
+
+	json_object_object_add(section_ir, "FWErrorInfo", fwinfo);
+}
+
+void parse_registers(EFI_NVIDIA_REGISTER_DATA *regPtr, UINT8 NumberRegs,
+		     size_t size, json_object *section_ir)
+{
+	// Registers (Address Value pairs).
+	json_object *regarr = json_object_new_array();
+	for (int i = 0; i < NumberRegs; i++, regPtr++) {
+		json_object *reg = NULL;
+		if (sizeof(EFI_NVIDIA_ERROR_DATA) +
+			    i * sizeof(EFI_NVIDIA_REGISTER_DATA) <
+		    size) {
+			reg = json_object_new_object();
+			json_object_object_add(
+				reg, "address",
+				json_object_new_uint64(regPtr->Address));
+			json_object_object_add(
+				reg, "value",
+				json_object_new_uint64(regPtr->Value));
+		} else {
+			reg = json_object_new_null();
+		}
+
+		json_object_array_add(regarr, reg);
+	}
+	json_object_object_add(section_ir, "registers", regarr);
+}
+
+typedef struct {
+	const char *ip_signature;
+	void (*callback)(EFI_NVIDIA_REGISTER_DATA *, UINT8, size_t,
+			 json_object *);
+} NV_SECTION_CALLBACKS;
+
+NV_SECTION_CALLBACKS section_handlers[] = {
+	{ "CMET-INFO\0", &parse_cmet_info },
+	{ "FWERROR\0", &parse_fwerror },
+	{ "", &parse_registers },
+};
+
 //Converts a single NVIDIA CPER section into JSON IR.
 json_object *cper_section_nvidia_to_ir(const UINT8 *section, UINT32 size)
 {
@@ -47,29 +144,17 @@
 		section_ir, "instanceBase",
 		json_object_new_uint64(nvidia_error->InstanceBase));
 
-	// Registers (Address Value pairs).
-	json_object *regarr = json_object_new_array();
-	EFI_NVIDIA_REGISTER_DATA *regPtr = nvidia_error->Register;
-	for (int i = 0; i < nvidia_error->NumberRegs; i++, regPtr++) {
-		json_object *reg = NULL;
-		if (sizeof(EFI_NVIDIA_ERROR_DATA) +
-			    i * sizeof(EFI_NVIDIA_REGISTER_DATA) <
-		    size) {
-			reg = json_object_new_object();
-			json_object_object_add(
-				reg, "address",
-				json_object_new_uint64(regPtr->Address));
-			json_object_object_add(
-				reg, "value",
-				json_object_new_uint64(regPtr->Value));
-		} else {
-			reg = json_object_new_null();
+	for (long unsigned int i = 0;
+	     i < sizeof(section_handlers) / sizeof(section_handlers[0]); i++) {
+		const char *ip_signature = section_handlers[i].ip_signature;
+		if (strncmp(nvidia_error->Signature, ip_signature,
+			    strlen(ip_signature)) == 0) {
+			section_handlers[i].callback(&nvidia_error->Register[0],
+						     nvidia_error->NumberRegs,
+						     size, section_ir);
+			break;
 		}
-
-		json_object_array_add(regarr, reg);
 	}
-	json_object_object_add(section_ir, "registers", regarr);
-
 	return section_ir;
 }
 
diff --git a/tests/ir-tests.c b/tests/ir-tests.c
index cfbaffb..170ead4 100644
--- a/tests/ir-tests.c
+++ b/tests/ir-tests.c
@@ -599,6 +599,11 @@
 	cper_log_section_dual_binary_test("nvidia");
 }
 
+void NVIDIACMETSectionTests_IRValid()
+{
+	cper_example_section_ir_test("nvidia_cmet_info");
+}
+
 //Unknown section tests.
 void UnknownSectionTests_IRValid()
 {
@@ -664,6 +669,7 @@
 	CXLComponentTests_BinaryEqual();
 	NVIDIASectionTests_IRValid();
 	NVIDIASectionTests_BinaryEqual();
+	NVIDIACMETSectionTests_IRValid();
 	UnknownSectionTests_IRValid();
 	UnknownSectionTests_BinaryEqual();
 	CompileTimeAssertions_TwoWayConversion();