📄 fruid.c
字号:
//********************************************************************
//* Munich Update Motherboard FRUID Tool *
//********************************************************************
//*
//* Chipset: NVDIA MCP55
//* EEPROM: ATMEL AT24C64
//* Author: Yuanjie Xu, ESBU/SW MiTAC Shanghai
//* Modifier: Jessie.Jing, SW2, ESBU, MiTAC Shanghai
//*
//********************************************************************
//* Rev. Date Description *
//********************************************************************
//* 0.1 2006-06-19 Initial version
//* 1.0 2007-04-29 Check whether burning time is earlier than 2005
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <mem.h>
#include <conio.h>
#pragma inline
extern unsigned _floatconvert;
#pragma extref _floatconvert
#define inb_p(p) inportb(p)
#define outb_p(v, p) outportb(p, v)
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long u32;
typedef unsigned long long u64;
typedef long uint32_t;
typedef unsigned bool;
#define FALSE 0
#define TRUE 1
static u32 smbus_base_addr = 0;
static u32 smbus_base_offset = 0;
static u32 smbus_value_bit = 0;
struct smbus_controller
{
u32 pci_id;
u32 base_offset;
u32 value_bit;
};
static struct smbus_controller smbus_controller_list[] =
{
{ 0x25a48086, 0x20, 0xffe0}, //Hance Rapids ICH SMBus Controller
{ 0x24838086, 0x20, 0xffe0}, //ICH3 SMBus Controller
{ 0x005210de, 0x24, 0xffff}, //CK804 SMBus Controller, NVDIA
{ 0x036810de, 0x24, 0xffff}, //MCP55 SMBus Controller, NVDIA
{ 0, 0, 0},
};
/*SMBus address offsets */
#define PRTCL (smbus_base_addr + 0)
#define STS (smbus_base_addr + 1)
#define ADDR (smbus_base_addr + 2)
#define CMD (smbus_base_addr + 3)
#define DATA0 (smbus_base_addr + 4)
#define DATA1 (smbus_base_addr + 5)
#define FruSize 0x2000
struct Fru_table
{
char *Field_descript;
WORD Location;
unsigned Length;
};
/*Fru Table for Motherboard or FPB*/
struct Fru_table FruTable_MFS[] = {
{"UNIX_Timestamp32" , 0x1F37 , 4 },
{"FRUID_Info" , 0x1F3B , 29},
{"Manufacture_Loc" , 0x1F8B , 64},
{"Sun_Part_No" , 0x1FCB , 7 },
{"Sun_Serial_No" , 0x1FD2 , 6 },
{"Vendor_Name" , 0x1FD8 , 2 },
{"Initial_HW_Rev_Level" , 0x1FDC , 2 },
{"FRUID_Source_BIN_Info", 0x1FF0 , 11},
{"CRC" , 0x1F33 , 200},
{"CRC32" , 0x1FFC , 4 },
{NULL,0,0}
};
/*Fru Table for SAS SBP, chicago*/
struct Fru_table FruTable_CS[] = {
{"UNIX_Timestamp32" , 0x1F34 , 4 },
{"FRUID_Info" , 0x1F38 , 29},
{"Manufacture_Loc" , 0x1F88 , 64},
{"Sun_Part_No" , 0x1FC8 , 7 },
{"Sun_Serial_No" , 0x1FCF , 6 },
{"Vendor_Name" , 0x1FD5 , 2 },
{"Initial_HW_Rev_Level" , 0x1FD9 , 2 },
{"FRUID_Source_BIN_Info", 0x1FED , 11},
{"CRC" , 0x1F30 , 203},
{"CRC32" , 0x1FFC , 4 },
{NULL,0,0}
};
struct Fru_table *fru=NULL;
WORD CRClength;
BYTE FruBuffer[FruSize];
/* CRC Model Abstract Type */
/* ----------------------- */
/* The following type stores the context of an executing instance of the */
/* model algorithm. Most of the fields are model parameters which must be */
/* set before the first initializing call to cm_ini. */
typedef struct
{
int cm_width; /* Parameter: Width in bits [8,32]. */
uint32_t cm_poly; /* Parameter: The algorithm's polynomial. */
uint32_t cm_init; /* Parameter: Initial register value. */
bool cm_refin; /* Parameter: Reflect input bytes? */
bool cm_refot; /* Parameter: Reflect output CRC? */
uint32_t cm_xorot; /* Parameter: XOR this to output CRC. */
uint32_t cm_reg; /* Context: Context during execution. */
} cm_t;
typedef cm_t *p_cm_t;
/* The following definitions make the code more readable. */
#define BITMASK(X) (1L << (X))
static uint32_t reflect(uint32_t v, int b)
/* Returns the value v with the bottom b [0,32] bits reflected. */
/* Example: reflect(0x3e23L,3) == 0x3e26 */
{
int i;
uint32_t t = v;
for (i = 0; i < b; i++) {
if (t & 1L)
v |= BITMASK((b-1)-i);
else
v &= ~BITMASK((b-1)-i);
t >>= 1;
}
return (v);
}
static uint32_t widmask(p_cm_t p_cm)
/* Returns a longword whose value is (2^p_cm->cm_width)-1. */
/* The trick is to do this portably (e.g. without doing <<32). */
{
return ((((1L<<(p_cm->cm_width-1))-1L)<<1)|1L);
}
//void outb_p(int value, int addr);
//unsigned int inb_p(int addr);
u32 pcibios_read_config_dword(u32 busnum, u32 devnum, u32 funnum, u32 regnum);
int probe_smbus (u32 pci_id);
int get_smbus_addr (void);
BYTE i2c_read_word(WORD offset1);
void i2c_write_word(WORD offset, BYTE data);
void cm_ini(p_cm_t p_cm);
void cm_nxt(p_cm_t p_cm, int ch);
uint32_t cm_crc(p_cm_t p_cm);
uint32_t compute_crc32(BYTE *bytes, int length);
void Display_All_Context(void);
void Update_Binfile(void);
int Update_time(void);
void Update_Serial_NO(void);
void Update_CRC32(void);
void DoubleCheck_CRC32(void);
void Check_Info(void);
void Check_time(void);
void Check_ManuLoc(void);
void Check_PN(void);
void Check_SN(void);
void Check_VendorName(void);
void Check_HW_Rev_Lev(void);
void Check_bin_info(void);
int Check_CRC32(void);
void usage(void);
void cm_ini(p_cm_t p_cm)
{
p_cm->cm_reg = p_cm->cm_init;
}
void cm_nxt(p_cm_t p_cm, int ch)
{
int i;
uint32_t uch = (uint32_t)ch;
uint32_t topbit = BITMASK(p_cm->cm_width-1);
if (p_cm->cm_refin)
uch = reflect(uch, 8);
p_cm->cm_reg ^= (uch << (p_cm->cm_width-8));
for (i = 0; i < 8; i++) {
if (p_cm->cm_reg & topbit)
p_cm->cm_reg = (p_cm->cm_reg << 1) ^ p_cm->cm_poly;
else
p_cm->cm_reg <<= 1;
p_cm->cm_reg &= widmask(p_cm);
}
}
uint32_t cm_crc(p_cm_t p_cm)
{
if (p_cm->cm_refot)
return (p_cm->cm_xorot ^ reflect(p_cm->cm_reg, p_cm->cm_width));
else
return (p_cm->cm_xorot ^ p_cm->cm_reg);
}
uint32_t compute_crc32(BYTE *bytes, int length)
{
cm_t crc_mdl;
p_cm_t p_crc;
int i;
uint32_t aCRC;
p_crc = &crc_mdl;
p_crc->cm_width = 32;
p_crc->cm_poly = 0x04c11db7;
p_crc->cm_init = 0xffffffff;
p_crc->cm_refin = TRUE;
p_crc->cm_refot = TRUE;
p_crc->cm_xorot = 0xffffffff;
cm_ini(p_crc);
for (i = 0; i < length; i++)
{
cm_nxt(p_crc, bytes[i]);
}
aCRC = (uint32_t)cm_crc(p_crc);
return (aCRC);
}
static BYTE slave_addr;
BYTE Low128_Bufer[128],Hi128_Bufer[128],buffer[265];
char SFileName[20]; //source file
char TSFileName[20]; //target file
char SN_number[7];
char compare_time[5];
char compare_info[30];
char compare_ManuLoc[65];
char compare_pn[8];
char compare_sn[7];
char compare_vn[3];
char compare_hw[3];
char compare_bin_info[12];
void Display_All_Context(void)
{
int i, j = 0;
printf("\n\t");
for(i = 0;i<= 0xF;i++)
printf("%2x ",i);
printf("\n");
for(i = 0;i<= 0x1FFF;i++)
{
j = i % 16;
if (j == 0)
{
printf("\n");
printf("0x%2x\t", i);
}
FruBuffer[i] = i2c_read_word(i);
printf("%2.2x ",i2c_read_word(i));
}
printf("\n");
}
void Update_Binfile()
{
int length = 0,i,count = 0;
BYTE buffer[80];
FILE *file = NULL;
file = fopen(SFileName,"rb");
memset (buffer, 0, 80);
do
{
length = fread((void *)buffer,1,80,file);
for(i = 0;i < length;i++)
{
i2c_write_word(count*80+i,buffer[i]);
// printf("%x\t",buffer[i]);
}
count++;
memset(buffer,0,80);
}while(length == 80);
fclose(file);
// printf("\n");
}
int Update_time()
{
time_t Timestamp, Timestamp1;
time_t Timestamp_comp = 0;
int i;
putenv("TZ=EST-8");
tzset();
Timestamp = time(NULL);
Timestamp1 = Timestamp;
printf("Current Time : %s", ctime(&Timestamp));
// Unix_Timestamp32
for (i=(fru[0].Length-1);i>=0;i--)
{
i2c_write_word(fru[0].Location + i, Timestamp & 0xFF);
Timestamp>>=8;
}
printf("Write Time : %s", ctime(&Timestamp1));
for (i=0;i<=3;i++)
{
Timestamp_comp += i2c_read_word(fru[0].Location + i);
if (i != 3)
Timestamp_comp <<=8;
}
printf("Compare Time : %s", ctime(&Timestamp_comp));
if(Timestamp_comp == Timestamp1)
{
printf("Update UNIX_Timestamp32 Pass\n");
return 0;
}
else
{
printf("Update UNIX_Timestamp32 Fail\n");
return 1;
}
}
void Update_Serial_NO(void)
{
// WORD offset = 0x1FD2;
WORD index;
for(index = 0;index < fru[4].Length;index++)
{
i2c_write_word(fru[4].Location+index,SN_number[index]);
// FruBuffer[offset+index] = SN_number[index];
}
}
void Update_CRC32()
{
u32 CRC32 = 0;
int i,j;
BYTE crc1;
BYTE crc2;
BYTE crc3;
BYTE crc4;
CRClength = fru[8].Length;
for(j=0;j<CRClength;j++)
FruBuffer[fru[8].Location+j] = i2c_read_word(fru[8].Location+j);
CRC32=compute_crc32(&FruBuffer[fru[8].Location],CRClength);
for (i=3;i>=0;i--)
{
FruBuffer[fru[9].Location + i] = CRC32 & 0xFF;
i2c_write_word(fru[9].Location + i, CRC32 & 0xFF);
CRC32>>=8;
}
crc1 = i2c_read_word(fru[9].Location);
crc2 = i2c_read_word(fru[9].Location+1);
crc3 = i2c_read_word(fru[9].Location+2);
crc4 = i2c_read_word(fru[9].Location+3);
printf("CRC32: 0x%2.2X%2.2X%2.2X%2.2X\n", crc1, crc2, crc3, crc4);
}
void DoubleCheck_CRC32()
{
u32 CRC32 = 0, CRC32_1 = 0;
char buff[100];
int i;
CRClength = fru[8].Length;
for (i=0;i<=3;i++)
{
CRC32_1+=FruBuffer[fru[9].Location+i];
if (i<=2)
CRC32_1*=256;
}
sprintf(buff,"%08lX",CRC32_1);
// printf("%20s : 0x%s\n","CRC32_1",buff);
CRC32 = compute_crc32(&FruBuffer[fru[8].Location],CRClength);
sprintf(buff,"%08lX",CRC32);
// printf("%20s : 0x%s\n","Re-Caculate CRC32",buff);
if (CRC32 == CRC32_1)
{
printf("Double check EEPROM Checksum32 Pass\n");
exit(0);
}
else
{
printf("Double check EEPROM Checksum32 Error\n");
exit(1);
}
}
void Check_time()
{
time_t Timestamp = 0;
char tmpbuf[10];
int year = 0;
int i;
BYTE time1;
BYTE time2;
BYTE time3;
BYTE time4;
printf("0x%4X Field: %s\n", fru[0].Location, fru[0].Field_descript);
putenv("TZ=EST-8");
tzset();
for (i = 0; i <= 3; i++)
{
Timestamp += i2c_read_word(fru[0].Location + i);;
if (i != 3)
Timestamp <<= 8;
}
time1 = i2c_read_word(fru[0].Location);
time2 = i2c_read_word(fru[0].Location+1);
time3 = i2c_read_word(fru[0].Location+2);
time4 = i2c_read_word(fru[0].Location+3);
printf("Burning UNIX_Timestamp32 in fruid: %s", ctime(&Timestamp));
printf(" (0x%2.2X%2.2X%2.2X%2.2X)\n", time1, time2, time3, time4);
strftime(tmpbuf, 10, "%Y", localtime(&Timestamp));
year = atoi(tmpbuf);
if(year < 2005)
{
printf( "Burning year: %4i is earlier than 2005! Error!", year);
exit(1);
}
}
void Check_Info()
{
WORD index;
WORD offset = fru[1].Location;
printf("0x%4X Field: %s\n", offset, fru[1].Field_descript);
memset(compare_info, 0, 30);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -