rendered paste body#define _GNU_SOURCE#include <stdio.h>#include <string.h>#include <stdlib.h>/* 128Kb */#define BIOS_SIZE 131072char BIOS[BIOS_SIZE];enum ELEMENT_TYPES{ STRING=0, CLOCK_INFO, VENDOR_ID,};/* Clock Info Table start marker */#define CLOCK_TABLE_START "\xE8\x03\xE8\x03\x28\x00\x98\x00\x00\x00\x08"/* Clock Info Table end marker */#define CLOCK_TABLE_END "\x08\x00\x00\x00\x7A\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00"/************ Clock Info Table structure ********************************* * [CLOCK_TABLE_START] * [18 bytes ???] * [0x01 0x01 0x02 0x03 0x02 0x040506 0x03 0x070809 etc... depending on how many rows] * <ROW0> [3byte GPU (100x MHz)] [3byte RAM (100x MHz)] [3byte Vcore (mV)] * [7 bytes ???] </ROW0> * <ROW1> ... * [7 bytes ???] </ROW1> * etc.. So each row is 16 bytes. I've seen up to 12 rows * [CLOCK_TABLE_END] */typedef struct { int type; void *data; char *desc; unsigned int offset; unsigned int length;}Element;typedef struct { unsigned int vcore; unsigned int ram; unsigned int gpu;}ClockInfo;typedef struct { char *name; unsigned short id;}VendorID;VendorID KNOWN_VENDORS[] = {{ "Asus" ,0x1043 },{ "Diamond" ,0x1092 },{ "GigaByte" ,0x1458 },{ "VisionTek" ,0x1545 },{ "Sapphire" ,0x174B },{ "Powercolor" ,0x1787 },{ NULL }};Element *HD48xx_vbios[] = {&(Element){ STRING ,NULL,"Bios Date/Time" ,0x0050, 16},&(Element){ VENDOR_ID ,NULL,"Sub Vendor ID" ,0x007C, 2},&(Element){ STRING ,NULL,"Bios Version String" ,0x0094, 14},&(Element){ STRING ,NULL,"Reported Chip Type" ,0x00A3, 5},&(Element){ STRING ,NULL,"Interface" ,0x00A9, 12},&(Element){ STRING ,NULL,"RAM Type" ,0x00B5, 6},&(Element){ STRING ,NULL,"Hardware Spec" ,0x00BD, 76},&(Element){ STRING ,NULL,"Power Cable Error Message" ,0x010E,164},&(Element){ STRING ,NULL,"Copyright" ,0x01B2, 38},&(Element){ STRING ,NULL,"ATOMBios Version" ,0x01D8, 41},&(Element){ CLOCK_INFO ,NULL,"Clock Info Table" ,0,0},NULL};void print_hex(char *ptr, size_t size){ int i; for(i=0;i<size;i++){ printf("%02hhX ",ptr[i]); } puts("\n");}void byte_swap(char *bytes, int length){ char copy; int i; for(i=0;(length-- -i)>1;i++){ copy = bytes[i]; bytes[i] = bytes[length]; bytes[length] = copy; }}void parse_vbios(Element **vbios){ int i,j; char *cptr; char *start,*end; ClockInfo **clk; int number,temp,length; for(i=0;vbios[i];i++){ switch(vbios[i]->type){ case STRING: cptr = malloc(vbios[i]->length); memcpy(cptr, BIOS+vbios[i]->offset, vbios[i]->length); vbios[i]->data = cptr; break; case VENDOR_ID: number = 0; memcpy(&number,BIOS+vbios[i]->offset, vbios[i]->length); for(j=0;KNOWN_VENDORS[j].name ;j++){ if(number == KNOWN_VENDORS[j].id ){ vbios[i]->data = &KNOWN_VENDORS[j]; break; } } break; case CLOCK_INFO: start = NULL; start = memmem(BIOS,BIOS_SIZE,CLOCK_TABLE_START,9); if(start == NULL){ printf("ERROR: Clock info table start\n"); break; } start+=10+19; end = NULL; end = memmem(BIOS,BIOS_SIZE,CLOCK_TABLE_END,16); if(end == NULL){ printf("ERROR: Clock info table end\n"); break; } length = (int) (end-start); number = length/16; if( (length%16) == 0 ){ start+=16; number--; }else { start += length%16; } clk = malloc(sizeof(ClockInfo*)*(number+1)); for(j=0;j<number;j++){ clk[j]=malloc(sizeof(ClockInfo)); temp =0; memcpy(&temp,start,3); clk[j]->gpu = temp/100; temp =0; memcpy(&temp,start+3,3); clk[j]->ram = temp/100; temp =0; memcpy(&temp,start+6,3); clk[j]->vcore = temp; start+=16; } clk[j]=NULL; vbios[i]->data = clk; } };}void dump_vbios(Element **vbios){ int i,j; ClockInfo **clk; for(i=0;vbios[i];i++){ printf("[%04x:%04x] %s\n", vbios[i]->offset, vbios[i]->length, vbios[i]->desc); switch(vbios[i]->type){ case STRING: printf("%s\n",(char*)vbios[i]->data); break; case CLOCK_INFO: if(vbios[i]->data == NULL)break; clk = (ClockInfo**) vbios[i]->data; for(j=0;clk[j];j++){ printf(" Profile %02i: %s %04u %s %04u %s %04u mV\n", j, "GPU =",clk[j]->gpu, "MHz | MEM =", clk[j]->ram, "MHz | Vcore =",clk[j]->vcore); } break; case VENDOR_ID: printf("0x%hX - %s\n", ((VendorID*)vbios[i]->data)->id, ((VendorID*)vbios[i]->data)->name); break; } }}int main(int argc, char **argv){ FILE *fptr; if(argc != 2 ){ printf("Specify file\n"); return 1; } fptr = fopen(argv[1],"r"); fread(BIOS,BIOS_SIZE,1,fptr); fclose(fptr); parse_vbios(HD48xx_vbios); dump_vbios(HD48xx_vbios); return 0;}