blob: 1d077a99df9304730069cc89f4f714c164521577 [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.
4 *
5 * 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>
John Chungf8fc7052024-05-03 20:05:29 +080010#include "libbase64.h"
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010011#include "../edk/Cper.h"
12#include "../cper-utils.h"
13#include "cper-section-dmar-iommu.h"
14
15//Converts a single IOMMU specific DMAr CPER section into JSON IR.
John Chungf8fc7052024-05-03 20:05:29 +080016json_object *cper_section_dmar_iommu_to_ir(void *section)
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010017{
Lawrence Tange407b4c2022-07-21 13:54:01 +010018 EFI_IOMMU_DMAR_ERROR_DATA *iommu_error =
19 (EFI_IOMMU_DMAR_ERROR_DATA *)section;
20 json_object *section_ir = json_object_new_object();
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010021
Lawrence Tange407b4c2022-07-21 13:54:01 +010022 //Revision.
23 json_object_object_add(section_ir, "revision",
24 json_object_new_int(iommu_error->Revision));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010025
Lawrence Tange407b4c2022-07-21 13:54:01 +010026 //IOMMU registers.
27 json_object_object_add(section_ir, "controlRegister",
28 json_object_new_uint64(iommu_error->Control));
29 json_object_object_add(section_ir, "statusRegister",
30 json_object_new_uint64(iommu_error->Status));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010031
Lawrence Tange407b4c2022-07-21 13:54:01 +010032 //IOMMU event log entry.
33 //The format of these entries differ widely by the type of error.
John Chungf8fc7052024-05-03 20:05:29 +080034 char *encoded = malloc(2 * 16);
35 size_t encoded_len = 0;
36 if (!encoded) {
37 printf("Failed to allocate encode output buffer. \n");
38 } else {
39 base64_encode((const char *)iommu_error->EventLogEntry, 16,
40 encoded, &encoded_len, 0);
41 json_object_object_add(section_ir, "eventLogEntry",
42 json_object_new_string_len(encoded,
43 encoded_len));
44 free(encoded);
45 }
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010046
Lawrence Tange407b4c2022-07-21 13:54:01 +010047 //Device table entry (as base64).
John Chungf8fc7052024-05-03 20:05:29 +080048 encoded = malloc(2 * 32);
49 encoded_len = 0;
50 if (!encoded) {
51 printf("Failed to allocate encode output buffer. \n");
52 } else {
53 base64_encode((const char *)iommu_error->DeviceTableEntry, 32,
54 encoded, &encoded_len, 0);
55 json_object_object_add(section_ir, "deviceTableEntry",
56 json_object_new_string_len(encoded,
57 encoded_len));
58 free(encoded);
59 }
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010060
Lawrence Tange407b4c2022-07-21 13:54:01 +010061 //Page table entries.
62 json_object_object_add(section_ir, "pageTableEntry_Level6",
63 json_object_new_uint64(iommu_error->PteL6));
64 json_object_object_add(section_ir, "pageTableEntry_Level5",
65 json_object_new_uint64(iommu_error->PteL5));
66 json_object_object_add(section_ir, "pageTableEntry_Level4",
67 json_object_new_uint64(iommu_error->PteL4));
68 json_object_object_add(section_ir, "pageTableEntry_Level3",
69 json_object_new_uint64(iommu_error->PteL3));
70 json_object_object_add(section_ir, "pageTableEntry_Level2",
71 json_object_new_uint64(iommu_error->PteL2));
72 json_object_object_add(section_ir, "pageTableEntry_Level1",
73 json_object_new_uint64(iommu_error->PteL1));
Lawrence Tangdb1b7ce2022-07-06 15:40:26 +010074
Lawrence Tange407b4c2022-07-21 13:54:01 +010075 return section_ir;
Lawrence Tang205dd1d2022-07-14 16:23:38 +010076}
77
78//Converts a single DMAR IOMMU CPER-JSON section into CPER binary, outputting to the given stream.
Lawrence Tange407b4c2022-07-21 13:54:01 +010079void ir_section_dmar_iommu_to_cper(json_object *section, FILE *out)
Lawrence Tang205dd1d2022-07-14 16:23:38 +010080{
Lawrence Tange407b4c2022-07-21 13:54:01 +010081 EFI_IOMMU_DMAR_ERROR_DATA *section_cper =
82 (EFI_IOMMU_DMAR_ERROR_DATA *)calloc(
83 1, sizeof(EFI_IOMMU_DMAR_ERROR_DATA));
Lawrence Tang205dd1d2022-07-14 16:23:38 +010084
Lawrence Tange407b4c2022-07-21 13:54:01 +010085 //Revision, registers.
86 section_cper->Revision = (UINT8)json_object_get_int(
87 json_object_object_get(section, "revision"));
88 section_cper->Control = json_object_get_uint64(
89 json_object_object_get(section, "controlRegister"));
90 section_cper->Status = json_object_get_uint64(
91 json_object_object_get(section, "statusRegister"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +010092
Lawrence Tange407b4c2022-07-21 13:54:01 +010093 //IOMMU event log entry.
94 json_object *encoded = json_object_object_get(section, "eventLogEntry");
John Chungf8fc7052024-05-03 20:05:29 +080095 char *decoded = malloc(json_object_get_string_len(encoded));
96 size_t decoded_len = 0;
97 if (!decoded) {
98 printf("Failed to allocate decode output buffer. \n");
99 } else {
100 base64_decode(json_object_get_string(encoded),
101 json_object_get_string_len(encoded), decoded,
102 &decoded_len, 0);
103 memcpy(section_cper->EventLogEntry, decoded, decoded_len);
104 free(decoded);
105 }
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100106
Lawrence Tange407b4c2022-07-21 13:54:01 +0100107 //Device table entry.
108 encoded = json_object_object_get(section, "deviceTableEntry");
John Chungf8fc7052024-05-03 20:05:29 +0800109 decoded = malloc(json_object_get_string_len(encoded));
110 decoded_len = 0;
111 if (!decoded) {
112 printf("Failed to allocate decode output buffer. \n");
113 } else {
114 base64_decode(json_object_get_string(encoded),
115 json_object_get_string_len(encoded), decoded,
116 &decoded_len, 0);
117 memcpy(section_cper->DeviceTableEntry, decoded, decoded_len);
118 free(decoded);
119 }
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100120
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121 //Page table entries.
122 section_cper->PteL1 = json_object_get_uint64(
123 json_object_object_get(section, "pageTableEntry_Level1"));
124 section_cper->PteL2 = json_object_get_uint64(
125 json_object_object_get(section, "pageTableEntry_Level2"));
126 section_cper->PteL3 = json_object_get_uint64(
127 json_object_object_get(section, "pageTableEntry_Level3"));
128 section_cper->PteL4 = json_object_get_uint64(
129 json_object_object_get(section, "pageTableEntry_Level4"));
130 section_cper->PteL5 = json_object_get_uint64(
131 json_object_object_get(section, "pageTableEntry_Level5"));
132 section_cper->PteL6 = json_object_get_uint64(
133 json_object_object_get(section, "pageTableEntry_Level6"));
Lawrence Tang205dd1d2022-07-14 16:23:38 +0100134
Lawrence Tange407b4c2022-07-21 13:54:01 +0100135 //Write to stream, free resources.
136 fwrite(section_cper, sizeof(EFI_IOMMU_DMAR_ERROR_DATA), 1, out);
137 fflush(out);
138 free(section_cper);
John Chungf8fc7052024-05-03 20:05:29 +0800139}