Skip to content

Commit 9028b11

Browse files
committed
Parse generic EEPROM structure
Not all fields parsed yet, but with -v the serial numbers and type are printed. This is what TUL needs right now. Example: ``` > ./gpu_cfg_gen.exe -g -s FRAFRAFRA1337ASSY0 -p FRAFRAFRA1337PCB00 -o gpu.bin Build: Feb 1 2024 15:59:21 Descriptor Version: 0 1 gpu = 1, ssd = 0, module SN = FRAFRAFRA1337ASSY0 pcb SN = FRAFRAFRA1337PCB00 output file = gpu.bin generating EEPROM writing EEPROM to gpu.bin > ./gpu_cfg_gen -i gpu.bin Build: Feb 1 2024 17:18:38 Serialnum: FRAFRAFRA1337ASSY0 Type: AMD R23M GPU PCBA Serial: FRAFRAFRA1337PCB00 ``` Signed-off-by: Daniel Schaefer <[email protected]>
1 parent 00ad391 commit 9028b11

File tree

2 files changed

+173
-41
lines changed

2 files changed

+173
-41
lines changed

gpu_cfg_generator.c

+170-41
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
#include <unistd.h>
77
#include <string.h>
88
#include <ctype.h>
9+
#include <stdbool.h>
910

1011
#include "crc.h"
1112
#include "gpio_defines.h"
1213
#include "config_definition.h"
1314
#define C_TO_K(temp_c) ((temp_c) + 273)
1415

16+
static bool verbose = false;
17+
1518
enum power_state {
1619
/* Steady states */
1720
POWER_G3 = 0, /*
@@ -213,71 +216,194 @@ static struct default_ssd_cfg ssd_cfg = {
213216
.gpu_3v_5v_en = {.gpio = GPU_3V_5V_EN, .function = GPIO_FUNC_HIGH, .flags = GPIO_OUTPUT_LOW, .power_domain = POWER_S5},
214217
};
215218

216-
void dump_descriptor(struct gpu_cfg_descriptor *desc)
219+
void print_descriptor(struct gpu_cfg_descriptor *desc)
217220
{
218221

219-
// Just for debugging
220-
// printf("Descriptor\n");
221-
// printf(" Magic %02X%02X%02X%02X\n", (uint8_t)desc->magic[0], (uint8_t)desc->magic[1], (uint8_t)desc->magic[2], (uint8_t)desc->magic[3]);
222-
// printf(" Length: %d\n", desc->length);
223-
// printf(" Desc Length: %d\n", desc->descriptor_length);
224-
// printf(" Desc CRC32: %08X\n", desc->descriptor_crc32);
225-
// printf(" CRC32: %08X\n", desc->crc32);
226-
// printf(" Desc Version: %d.%d\n", desc->descriptor_version_major, desc->descriptor_version_minor);
227-
// printf(" HW Version: %04X\n", desc->hardware_version);
228-
// printf(" HW Rev: %d\n", desc->hardware_revision);
229-
// printf(" Serialnum: %s\n", desc->serial);
230-
231-
printf("Serialnum: %s\n", desc->serial);
222+
if (verbose) {
223+
printf("Descriptor\n");
224+
printf(" Magic %02X%02X%02X%02X\n", (uint8_t)desc->magic[0], (uint8_t)desc->magic[1], (uint8_t)desc->magic[2], (uint8_t)desc->magic[3]);
225+
printf(" Length: %d\n", desc->length);
226+
printf(" Desc Version: %d.%d\n", desc->descriptor_version_major, desc->descriptor_version_minor);
227+
printf(" HW Version: %04X\n", desc->hardware_version);
228+
printf(" HW Rev: %d\n", desc->hardware_revision);
229+
printf(" Serialnum: %s\n", desc->serial);
230+
printf(" Desc Length: %d\n", desc->descriptor_length);
231+
printf(" Desc CRC32: %08X\n", desc->descriptor_crc32);
232+
printf(" CRC32: %08X\n", desc->crc32);
233+
} else {
234+
printf("Serialnum: %s\n", desc->serial);
235+
}
232236
}
233237

234-
void dump_gpu(struct default_gpu_cfg* gpu_cfg)
238+
void print_subsys(struct gpu_subsys_serial* subsys)
235239
{
236-
printf("Type: GPU\n");
237-
switch (gpu_cfg->pcba_serial.gpu_subsys) {
240+
printf(" Type: ");
241+
switch (subsys->gpu_subsys) {
238242
case GPU_PCB:
239-
printf("PCBA Serial: %s\n", gpu_cfg->pcba_serial.serial);
243+
printf("PCB\n");
240244
break;
241245
case GPU_LEFT_FAN:
242-
printf("Left Fan SN: %s\n", gpu_cfg->pcba_serial.serial);
246+
printf("Left Fan\n");
243247
break;
244248
case GPU_RIGHT_FAN:
245-
printf("Right Fan SN: %s\n", gpu_cfg->pcba_serial.serial);
249+
printf("Right Fan\n");
246250
break;
247251
case GPU_HOUSING:
248-
printf("Housing SN: %s\n", gpu_cfg->pcba_serial.serial);
252+
printf("Housing\n");
249253
break;
250254
default:
251-
printf("??? Serial: %s\n", gpu_cfg->pcba_serial.serial);
255+
printf("???\n");
252256
break;
253257
}
258+
printf(" Serial: %s\n", subsys->serial);
254259
}
255260

256-
void dump_ssd(struct default_ssd_cfg* ssd_cfg)
257-
{
258-
printf("Type: SSD\n");
261+
void print_vendor(enum gpu_vendor vendor) {
262+
switch (vendor) {
263+
case GPU_VENDOR_INITIALIZING:
264+
printf("Vendor Initializing\n");
265+
break;
266+
case GPU_FAN_ONLY:
267+
printf("Fan Only\n");
268+
break;
269+
case GPU_AMD_R23M:
270+
printf("AMD R23M GPU\n");
271+
break;
272+
case GPU_SSD:
273+
printf("SSD\n");
274+
break;
275+
case GPU_PCIE_ACCESSORY:
276+
printf("PCI-E Accessory\n");
277+
break;
278+
default:
279+
printf("Invalid (%d)\n", vendor);
280+
break;
281+
}
259282
}
260283

284+
261285
void read_eeprom(const char * infilename)
262286
{
263287
FILE *fptr;
264288
fptr = fopen(infilename,"rb");
265-
// TODO: gpu_cfg is bigger than ssd_cfg, that's why I read it into there.
266-
// Should make it safer so that if we change the structures, the same still holds.
267-
fread((void *)&gpu_cfg, sizeof(gpu_cfg), 1, fptr);
289+
290+
struct gpu_cfg_descriptor descriptor;
291+
fread((void *)&descriptor, sizeof(descriptor), 1, fptr);
292+
293+
print_descriptor(&descriptor);
294+
295+
void *blocks = malloc(descriptor.descriptor_length);
296+
if (!blocks) {
297+
fclose(fptr);
298+
return;
299+
}
300+
fread(blocks, descriptor.descriptor_length, 1, fptr);
268301
fclose(fptr);
269302

270-
uint32_t len = gpu_cfg.descriptor.descriptor_length + sizeof(struct gpu_cfg_descriptor);
271-
// TODO: Length comparison won't work if newer versions of the descriptors have different sizes
272-
if (len == sizeof(struct default_gpu_cfg)) {
273-
dump_descriptor((struct gpu_cfg_descriptor *)&gpu_cfg);
274-
dump_gpu((struct default_gpu_cfg*) &gpu_cfg);
275-
} else if (len == sizeof(struct default_ssd_cfg)) {
276-
dump_descriptor((struct gpu_cfg_descriptor *)&gpu_cfg);
277-
dump_ssd((struct default_ssd_cfg*) &gpu_cfg);
278-
} else {
279-
printf("Invalid descriptor. No body found (Len %d)\n", len);
303+
int offset = 0;
304+
int n = 0;
305+
struct gpu_block_header *block_header;
306+
while (offset < descriptor.descriptor_length) {
307+
block_header = (struct gpu_block_header *)(blocks + offset);
308+
void *block_body = blocks + offset + sizeof(struct gpu_block_header);
309+
310+
if (verbose) {
311+
uint8_t *pcie;
312+
struct gpu_cfg_fan *fan;
313+
printf("Block %d\n", n);
314+
printf(" Length: %d\n", block_header->block_length);
315+
printf(" Type: ");
316+
switch (block_header->block_type) {
317+
case GPUCFG_TYPE_UNINITIALIZED:
318+
printf("Uninitialized\n");
319+
break;
320+
case GPUCFG_TYPE_GPIO:
321+
printf("GPIO\n");
322+
break;
323+
case GPUCFG_TYPE_THERMAL_SENSOR:
324+
printf("Thermal Sensor\n");
325+
break;
326+
case GPUCFG_TYPE_FAN:
327+
fan = block_body;
328+
printf("Fan\n");
329+
printf(" ID: %d\n", fan->idx);
330+
printf(" Flags: %d\n", fan->flags);
331+
printf(" Min RPM: %d\n", fan->min_rpm);
332+
printf(" Min Temp: %d\n", fan->min_temp);
333+
printf(" Start RPM: %d\n", fan->start_rpm);
334+
printf(" Max RPM: %d\n", fan->max_rpm);
335+
printf(" Max Temp: %d\n", fan->max_temp);
336+
break;
337+
case GPUCFG_TYPE_POWER:
338+
printf("Power\n");
339+
break;
340+
case GPUCFG_TYPE_BATTERY:
341+
printf("Battery\n");
342+
break;
343+
case GPUCFG_TYPE_PCIE:
344+
printf("PCI-E\n");
345+
pcie = block_body;
346+
switch (*pcie) {
347+
case PCIE_8X1:
348+
printf(" Lanes: 8X1\n");
349+
break;
350+
case PCIE_4X1:
351+
printf(" Lanes: 4X1\n");
352+
break;
353+
case PCIE_4X2:
354+
printf(" Lanes: 4X2\n");
355+
break;
356+
default:
357+
printf(" Invalid (%d)\n", *pcie);
358+
break;
359+
}
360+
break;
361+
case GPUCFG_TYPE_DPMUX:
362+
printf("DP-MUX\n");
363+
break;
364+
case GPUCFG_TYPE_POWEREN:
365+
printf("POWER-EN\n");
366+
break;
367+
case GPUCFG_TYPE_SUBSYS:
368+
printf("Subsystem\n");
369+
print_subsys((struct gpu_subsys_serial *)block_body);
370+
break;
371+
case GPUCFG_TYPE_VENDOR:
372+
printf("Vendor\n");
373+
printf(" Value: ");
374+
print_vendor(*(enum gpu_vendor *) block_body);
375+
break;
376+
case GPUCFG_TYPE_PD:
377+
printf("PD\n");
378+
break;
379+
case GPUCFG_TYPE_GPUPWR:
380+
printf("GPU Power\n");
381+
break;
382+
case GPUCFG_TYPE_CUSTOM_TEMP:
383+
printf("Custom Temp\n");
384+
break;
385+
default:
386+
printf("Unknown\n");
387+
break;
388+
}
389+
} else {
390+
if (block_header->block_type == GPUCFG_TYPE_SUBSYS) {
391+
struct gpu_subsys_serial *subsys = block_body;
392+
if (subsys->gpu_subsys == GPU_PCB) {
393+
printf("PCBA Serial: %s\n", subsys->serial);
394+
}
395+
}
396+
if (block_header->block_type == GPUCFG_TYPE_VENDOR) {
397+
printf("Type: ");
398+
print_vendor(*(enum gpu_vendor *) block_body);
399+
}
400+
}
401+
402+
offset += sizeof(struct gpu_block_header) + block_header->block_length;
403+
n++;
280404
}
405+
406+
free(blocks);
281407
}
282408

283409
void program_eeprom(const char * serial, struct gpu_cfg_descriptor * descriptor, size_t len, const char * outpath)
@@ -305,7 +431,7 @@ void program_eeprom(const char * serial, struct gpu_cfg_descriptor * descriptor,
305431
}
306432

307433
int main(int argc, char *argv[]) {
308-
int gpuflag = 0;
434+
int gpuflag = 0;
309435
int ssdflag = 0;
310436
char *serialvalue = NULL;
311437
char *pcbvalue = NULL;
@@ -315,7 +441,7 @@ int main(int argc, char *argv[]) {
315441

316442
opterr = 0;
317443

318-
while ((c = getopt (argc, argv, "gds:p:o:i:")) != -1)
444+
while ((c = getopt (argc, argv, "gdvs:p:o:i:")) != -1)
319445
switch (c)
320446
{
321447
case 'g':
@@ -336,6 +462,9 @@ int main(int argc, char *argv[]) {
336462
case 'i':
337463
infilename = optarg;
338464
break;
465+
case 'v':
466+
verbose = true;
467+
break;
339468
case '?':
340469
if (optopt == 'c')
341470
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
@@ -359,7 +488,7 @@ int main(int argc, char *argv[]) {
359488
printf("Descriptor Version: %d %d\n", 0, 1);
360489

361490
printf ("gpu = %d, ssd = %d, module SN = %s pcb SN = %s output file = %s\n",
362-
gpuflag, ssdflag, serialvalue, pcbvalue, outfilename, infilename);
491+
gpuflag, ssdflag, serialvalue, pcbvalue, outfilename);
363492

364493
if (gpuflag) {
365494
if (pcbvalue) {

readme.md

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ To double-check you can read the binary back from EEPROM and analyze it with the
4343

4444
```sh
4545
./gpu_cfg_gen -i eeprom.bin
46+
47+
# More verbose output
48+
./gpu_cfg_gen -i eeprom.bin -v
4649
```
4750

4851
# Build natively

0 commit comments

Comments
 (0)