blob: c411cf2a1f9502c4c3541d25dc212d8ecf718de4 [file] [log] [blame]
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +01001/**
2 * Describes functions for converting IOMMU specific DMAr CPER sections from binary and JSON format
3 * into an intermediate format.
Ed Tanousfedd4572024-07-12 13:56:00 -07004 *
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +01005 * Author: Lawrence.Tang@arm.com
6 **/
7#include <stdio.h>
Lawrence Tang205dd1d2022-07-14 16:23:38 +01008#include <string.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +01009#include <json.h>
Thu Nguyene42fb482024-10-15 14:43:11 +000010#include <libcper/base64.h>
11#include <libcper/Cper.h>
12#include <libcper/cper-utils.h>
13#include <libcper/sections/cper-section-dmar-iommu.h>
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010014
15//Converts a single IOMMU specific DMAr CPER section into JSON IR.
Ed Tanous12dbd4f2025-03-08 19:05:01 -080016json_object *cper_section_dmar_iommu_to_ir(const UINT8 *section, UINT32 size)
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010017{
Ed Tanous12dbd4f2025-03-08 19:05:01 -080018 if (size < sizeof(EFI_IOMMU_DMAR_ERROR_DATA)) {
19 return NULL;
20 }
21
Lawrence Tange407b4c2022-07-21 13:54:01 +010022 EFI_IOMMU_DMAR_ERROR_DATA *iommu_error =
23 (EFI_IOMMU_DMAR_ERROR_DATA *)section;
24 json_object *section_ir = json_object_new_object();
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010025
Lawrence Tange407b4c2022-07-21 13:54:01 +010026 //Revision.
27 json_object_object_add(section_ir, "revision",
28 json_object_new_int(iommu_error->Revision));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010029
Lawrence Tange407b4c2022-07-21 13:54:01 +010030 //IOMMU registers.
31 json_object_object_add(section_ir, "controlRegister",
32 json_object_new_uint64(iommu_error->Control));
33 json_object_object_add(section_ir, "statusRegister",
34 json_object_new_uint64(iommu_error->Status));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010035
Lawrence Tange407b4c2022-07-21 13:54:01 +010036 //IOMMU event log entry.
37 //The format of these entries differ widely by the type of error.
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070038 int32_t encoded_len = 0;
39
40 char *encoded = base64_encode((UINT8 *)iommu_error->EventLogEntry, 16,
41 &encoded_len);
42 if (encoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +080043 printf("Failed to allocate encode output buffer. \n");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070044
45 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +080046 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070047 json_object_object_add(section_ir, "eventLogEntry",
48 json_object_new_string_len(encoded,
49 encoded_len));
50 free(encoded);
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010051
Lawrence Tange407b4c2022-07-21 13:54:01 +010052 //Device table entry (as base64).
John Chungf8fc7052024-05-03 20:05:29 +080053 encoded_len = 0;
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070054
55 encoded = base64_encode((UINT8 *)iommu_error->DeviceTableEntry, 32,
56 &encoded_len);
57 if (encoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +080058 printf("Failed to allocate encode output buffer. \n");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070059 return NULL;
John Chungf8fc7052024-05-03 20:05:29 +080060 }
Ed Tanousa7d2cdd2024-07-15 11:07:27 -070061 json_object_object_add(section_ir, "deviceTableEntry",
62 json_object_new_string_len(encoded,
63 encoded_len));
64 free(encoded);
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010065
Lawrence Tange407b4c2022-07-21 13:54:01 +010066 //Page table entries.
67 json_object_object_add(section_ir, "pageTableEntry_Level6",
68 json_object_new_uint64(iommu_error->PteL6));
69 json_object_object_add(section_ir, "pageTableEntry_Level5",
70 json_object_new_uint64(iommu_error->PteL5));
71 json_object_object_add(section_ir, "pageTableEntry_Level4",
72 json_object_new_uint64(iommu_error->PteL4));
73 json_object_object_add(section_ir, "pageTableEntry_Level3",
74 json_object_new_uint64(iommu_error->PteL3));
75 json_object_object_add(section_ir, "pageTableEntry_Level2",
76 json_object_new_uint64(iommu_error->PteL2));
77 json_object_object_add(section_ir, "pageTableEntry_Level1",
78 json_object_new_uint64(iommu_error->PteL1));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010079
Lawrence Tange407b4c2022-07-21 13:54:01 +010080 return section_ir;
Lawrence Tang205dd1d2022-07-14 16:23:38 +010081}
82
83//Converts a single DMAR IOMMU CPER-JSON section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +010084void ir_section_dmar_iommu_to_cper(json_object *section, FILE *out)
Lawrence Tang205dd1d2022-07-14 16:23:38 +010085{
Lawrence Tange407b4c2022-07-21 13:54:01 +010086 EFI_IOMMU_DMAR_ERROR_DATA *section_cper =
87 (EFI_IOMMU_DMAR_ERROR_DATA *)calloc(
88 1, sizeof(EFI_IOMMU_DMAR_ERROR_DATA));
Lawrence Tang205dd1d2022-07-14 16:23:38 +010089
Lawrence Tange407b4c2022-07-21 13:54:01 +010090 //Revision, registers.
91 section_cper->Revision = (UINT8)json_object_get_int(
92 json_object_object_get(section, "revision"));
93 section_cper->Control = json_object_get_uint64(
94 json_object_object_get(section, "controlRegister"));
95 section_cper->Status = json_object_get_uint64(
96 json_object_object_get(section, "statusRegister"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +010097
Lawrence Tange407b4c2022-07-21 13:54:01 +010098 //IOMMU event log entry.
99 json_object *encoded = json_object_object_get(section, "eventLogEntry");
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700100 int32_t decoded_len = 0;
101
102 UINT8 *decoded = base64_decode(json_object_get_string(encoded),
103 json_object_get_string_len(encoded),
104 &decoded_len);
105 if (decoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800106 printf("Failed to allocate decode output buffer. \n");
107 } else {
John Chungf8fc7052024-05-03 20:05:29 +0800108 memcpy(section_cper->EventLogEntry, decoded, decoded_len);
109 free(decoded);
110 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100111 //Device table entry.
112 encoded = json_object_object_get(section, "deviceTableEntry");
John Chungf8fc7052024-05-03 20:05:29 +0800113 decoded_len = 0;
Ed Tanousa7d2cdd2024-07-15 11:07:27 -0700114
115 decoded = base64_decode(json_object_get_string(encoded),
116 json_object_get_string_len(encoded),
117 &decoded_len);
118 if (decoded == NULL) {
John Chungf8fc7052024-05-03 20:05:29 +0800119 printf("Failed to allocate decode output buffer. \n");
120 } else {
John Chungf8fc7052024-05-03 20:05:29 +0800121 memcpy(section_cper->DeviceTableEntry, decoded, decoded_len);
122 free(decoded);
123 }
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100124
Lawrence Tange407b4c2022-07-21 13:54:01 +0100125 //Page table entries.
126 section_cper->PteL1 = json_object_get_uint64(
127 json_object_object_get(section, "pageTableEntry_Level1"));
128 section_cper->PteL2 = json_object_get_uint64(
129 json_object_object_get(section, "pageTableEntry_Level2"));
130 section_cper->PteL3 = json_object_get_uint64(
131 json_object_object_get(section, "pageTableEntry_Level3"));
132 section_cper->PteL4 = json_object_get_uint64(
133 json_object_object_get(section, "pageTableEntry_Level4"));
134 section_cper->PteL5 = json_object_get_uint64(
135 json_object_object_get(section, "pageTableEntry_Level5"));
136 section_cper->PteL6 = json_object_get_uint64(
137 json_object_object_get(section, "pageTableEntry_Level6"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100138
Lawrence Tange407b4c2022-07-21 13:54:01 +0100139 //Write to stream, free resources.
140 fwrite(section_cper, sizeof(EFI_IOMMU_DMAR_ERROR_DATA), 1, out);
141 fflush(out);
142 free(section_cper);
John Chungf8fc7052024-05-03 20:05:29 +0800143}