1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 #include <stdlib.h>
4 #include <stddef.h>
5 #include <string.h>
6 #include <stdio.h>
7 #include <libcper/BaseTypes.h>
8 #include <libcper/Cper.h>
9 #include <libcper/generator/gen-utils.h>
10 #include <libcper/generator/sections/gen-section.h>
11 #include <libcper/sections/cper-section-nvidia-events.h>
12 #include <libcper/log.h>
13
14 // Context data format types
15 #define NVIDIA_CTX_TYPE_OPAQUE 0x0000
16 #define NVIDIA_CTX_TYPE_1 0x0001
17 #define NVIDIA_CTX_TYPE_2 0x0002
18 #define NVIDIA_CTX_TYPE_3 0x0003
19 #define NVIDIA_CTX_TYPE_4 0x0004
20
21 static const char signatures[][16 + 1] = {
22 "SOCHUB\0\0\0\0\0\0\0\0\0\0", "PCIe\0\0\0\0\0\0\0\0\0\0\0\0",
23 "L0 RESET\0\0\0\0\0\0\0\0", "L1 RESET\0\0\0\0\0\0\0\0",
24 "L2 RESET\0\0\0\0\0\0\0\0", "RAS-TELEMETRY\0\0\0",
25 "MSS\0\0\0\0\0\0\0\0\0\0\0\0\0", "HUB\0\0\0\0\0\0\0\0\0\0\0\0\0",
26 "HSM U/I ERROR\0\0\0", "HSM\0\0\0\0\0\0\0\0\0\0\0\0\0",
27 "HSM_FABRIC\0\0\0\0\0\0", "FWERROR\0\0\0\0\0\0\0\0\0",
28 "CCPLEXUCF\0\0\0\0\0\0\0", "GPU-STATUS\0\0\0\0\0\0",
29 "GPU-CONT-GRS\0\0\0\0",
30 };
31
32 // Helper to calculate context data size based on type
get_context_data_size(UINT16 ctx_type,UINT32 num_elements)33 static size_t get_context_data_size(UINT16 ctx_type, UINT32 num_elements)
34 {
35 switch (ctx_type) {
36 case NVIDIA_CTX_TYPE_OPAQUE:
37 return num_elements; // num_elements = byte count for opaque
38 case NVIDIA_CTX_TYPE_1:
39 return num_elements * sizeof(EFI_NVIDIA_EVENT_CTX_DATA_TYPE_1);
40 case NVIDIA_CTX_TYPE_2:
41 return num_elements * sizeof(EFI_NVIDIA_EVENT_CTX_DATA_TYPE_2);
42 case NVIDIA_CTX_TYPE_3:
43 return num_elements * sizeof(EFI_NVIDIA_EVENT_CTX_DATA_TYPE_3);
44 case NVIDIA_CTX_TYPE_4:
45 return num_elements * sizeof(EFI_NVIDIA_EVENT_CTX_DATA_TYPE_4);
46 default:
47 return 0;
48 }
49 }
50
51 // Helper to fill context data based on type
fill_context_data(UINT8 * data,UINT16 ctx_type,UINT32 num_elements)52 static void fill_context_data(UINT8 *data, UINT16 ctx_type, UINT32 num_elements)
53 {
54 switch (ctx_type) {
55 case NVIDIA_CTX_TYPE_OPAQUE:
56 // Fill with random bytes
57 for (UINT32 i = 0; i < num_elements; i++) {
58 data[i] = (UINT8)(cper_rand() & 0xFF);
59 }
60 break;
61 case NVIDIA_CTX_TYPE_1: {
62 EFI_NVIDIA_EVENT_CTX_DATA_TYPE_1 *pairs =
63 (EFI_NVIDIA_EVENT_CTX_DATA_TYPE_1 *)data;
64 for (UINT32 i = 0; i < num_elements; i++) {
65 pairs[i].Key = ((UINT64)cper_rand() << 32) |
66 (UINT64)cper_rand();
67 pairs[i].Value = ((UINT64)cper_rand() << 32) |
68 (UINT64)cper_rand();
69 }
70 break;
71 }
72 case NVIDIA_CTX_TYPE_2: {
73 EFI_NVIDIA_EVENT_CTX_DATA_TYPE_2 *pairs =
74 (EFI_NVIDIA_EVENT_CTX_DATA_TYPE_2 *)data;
75 for (UINT32 i = 0; i < num_elements; i++) {
76 pairs[i].Key = cper_rand();
77 pairs[i].Value = cper_rand();
78 }
79 break;
80 }
81 case NVIDIA_CTX_TYPE_3: {
82 EFI_NVIDIA_EVENT_CTX_DATA_TYPE_3 *vals =
83 (EFI_NVIDIA_EVENT_CTX_DATA_TYPE_3 *)data;
84 for (UINT32 i = 0; i < num_elements; i++) {
85 vals[i].Value = ((UINT64)cper_rand() << 32) |
86 (UINT64)cper_rand();
87 }
88 break;
89 }
90 case NVIDIA_CTX_TYPE_4: {
91 EFI_NVIDIA_EVENT_CTX_DATA_TYPE_4 *vals =
92 (EFI_NVIDIA_EVENT_CTX_DATA_TYPE_4 *)data;
93 for (UINT32 i = 0; i < num_elements; i++) {
94 vals[i].Value = cper_rand();
95 }
96 break;
97 }
98 }
99 }
100
101 // Generates a single pseudo-random NVIDIA Events error section
generate_section_nvidia_events(void ** location,GEN_VALID_BITS_TEST_TYPE validBitsType)102 size_t generate_section_nvidia_events(void **location,
103 GEN_VALID_BITS_TEST_TYPE validBitsType)
104 {
105 (void)validBitsType;
106
107 // Select a random signature
108 int sig_idx =
109 cper_rand() % (sizeof(signatures) / sizeof(signatures[0]));
110
111 // Randomly select device type: 0 = CPU, 1 = GPU
112 UINT32 deviceType = cper_rand() % 2;
113
114 // Calculate size needed
115 size_t event_header_size = sizeof(EFI_NVIDIA_EVENT_HEADER);
116 size_t event_info_header_size = sizeof(EFI_NVIDIA_EVENT_INFO_HEADER);
117 size_t event_info_data_size =
118 (deviceType == 0) ? sizeof(EFI_NVIDIA_CPU_EVENT_INFO) :
119 sizeof(EFI_NVIDIA_GPU_EVENT_INFO);
120
121 // Decide number of contexts (0-5 for variety)
122 UINT32 contextCount = cper_rand() % 6;
123
124 // Generate context configurations
125 UINT16 ctx_types[5];
126 UINT32 ctx_num_elements[5];
127 size_t context_data_sizes[5] = { 0 };
128 size_t context_total_sizes[5] = { 0 }; // header + data (no padding)
129 size_t total_context_size = 0;
130
131 for (UINT32 i = 0; i < contextCount; i++) {
132 // Randomly select context type (0-4)
133 ctx_types[i] = cper_rand() % 5;
134
135 // Number of elements (2-6 for structured, 16-64 bytes for opaque)
136 if (ctx_types[i] == NVIDIA_CTX_TYPE_OPAQUE) {
137 ctx_num_elements[i] =
138 16 + (cper_rand() % 49); // 16-64 bytes
139 } else {
140 ctx_num_elements[i] =
141 2 + (cper_rand() % 5); // 2-6 elements
142 }
143
144 context_data_sizes[i] = get_context_data_size(
145 ctx_types[i], ctx_num_elements[i]);
146
147 // Context size = header + data (no padding between contexts)
148 context_total_sizes[i] = sizeof(EFI_NVIDIA_EVENT_CTX_HEADER) +
149 context_data_sizes[i];
150 total_context_size += context_total_sizes[i];
151 }
152
153 // Total section size
154 size_t total_size = event_header_size + event_info_header_size +
155 event_info_data_size + total_context_size;
156
157 // Allocate section
158 UINT8 *section = (UINT8 *)calloc(1, total_size);
159 if (!section) {
160 return 0;
161 }
162
163 UINT8 *current = section;
164
165 // Fill Event Header
166 EFI_NVIDIA_EVENT_HEADER *event_header =
167 (EFI_NVIDIA_EVENT_HEADER *)current;
168
169 memcpy(event_header->Signature, signatures[sig_idx],
170 sizeof(event_header->Signature));
171
172 event_header->EventVersion = 1;
173 event_header->EventContextCount = contextCount;
174 event_header->SourceDeviceType = deviceType;
175 event_header->Reserved1 = 0;
176 event_header->EventType = cper_rand() % 256;
177 event_header->EventSubtype = cper_rand() % 256;
178 event_header->EventLinkId = ((UINT64)cper_rand() << 32) |
179 (UINT64)cper_rand();
180
181 current += event_header_size;
182
183 // Fill Event Info Header
184 EFI_NVIDIA_EVENT_INFO_HEADER *event_info_header =
185 (EFI_NVIDIA_EVENT_INFO_HEADER *)current;
186
187 if (deviceType == 0) {
188 // CPU: version 0.0
189 event_info_header->InfoVersion =
190 (EFI_NVIDIA_CPU_EVENT_INFO_MAJ << 8) |
191 EFI_NVIDIA_CPU_EVENT_INFO_MIN;
192 } else {
193 // GPU: version 1.0
194 event_info_header->InfoVersion =
195 (EFI_NVIDIA_GPU_EVENT_INFO_MAJ << 8) |
196 EFI_NVIDIA_GPU_EVENT_INFO_MIN;
197 }
198 // InfoSize = header size + device-specific info size
199 event_info_header->InfoSize =
200 (UINT8)(event_info_header_size + event_info_data_size);
201
202 cper_print_log("InfoSize: %d", event_info_header->InfoSize);
203
204 current += event_info_header_size;
205
206 // Fill Event Info based on device type
207 if (deviceType == 0) {
208 // CPU Event Info
209 EFI_NVIDIA_CPU_EVENT_INFO *cpu_info =
210 (EFI_NVIDIA_CPU_EVENT_INFO *)current;
211 cpu_info->SocketNum = cper_rand() % 8;
212 cpu_info->Architecture = cper_rand();
213 cpu_info->Ecid[0] = cper_rand();
214 cpu_info->Ecid[1] = cper_rand();
215 cpu_info->Ecid[2] = cper_rand();
216 cpu_info->Ecid[3] = cper_rand();
217 cpu_info->InstanceBase = ((UINT64)cper_rand() << 32) |
218 (UINT64)cper_rand();
219 } else {
220 // GPU Event Info
221 EFI_NVIDIA_GPU_EVENT_INFO *gpu_info =
222 (EFI_NVIDIA_GPU_EVENT_INFO *)current;
223 gpu_info->EventOriginator = cper_rand() % 4;
224 gpu_info->SourcePartition = cper_rand() % 16;
225 gpu_info->SourceSubPartition = cper_rand() % 8;
226 gpu_info->Pdi = ((UINT64)cper_rand() << 32) |
227 (UINT64)cper_rand();
228 }
229
230 current += event_info_data_size;
231
232 // Fill Event Contexts with various types
233 for (UINT32 i = 0; i < contextCount; i++) {
234 EFI_NVIDIA_EVENT_CTX_HEADER *ctx_header =
235 (EFI_NVIDIA_EVENT_CTX_HEADER *)current;
236
237 // CtxSize = header + data (NOT including padding)
238 size_t ctx_size = sizeof(EFI_NVIDIA_EVENT_CTX_HEADER) +
239 context_data_sizes[i];
240
241 ctx_header->CtxSize = (UINT32)ctx_size;
242 ctx_header->CtxVersion = 0;
243 ctx_header->Reserved1 = 0;
244 ctx_header->DataFormatType = ctx_types[i];
245 ctx_header->DataFormatVersion = 0;
246 ctx_header->DataSize = (UINT32)context_data_sizes[i];
247
248 current += sizeof(EFI_NVIDIA_EVENT_CTX_HEADER);
249
250 // Fill context data based on type
251 fill_context_data(current, ctx_types[i], ctx_num_elements[i]);
252
253 current += context_data_sizes[i];
254 }
255
256 // Set return values
257 *location = section;
258 return total_size;
259 }
260