代码求助
有人可以根据SMBIOS的spec来实现在Linux中查询EPS表和遍历SMBIOS信息的代码吗?在Windows上实现也行
类似这种 做一下改良
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#define StartAddress0xF0000
#define EndAddress0xFFFFF
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
typedef unsigned long DWORD;
typedef unsigned int DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef struct
{
BYTE Type;
BYTE Length;
WORD Handle;
}Header;
typedef struct
{
BYTE Major_Version;
BYTE Minor_Version;
WORD Length;
DWORD Address;
WORD Struct_Count;
}EPS;
const char *characteristics[]={
"Reserved", "Reserved", "Unknown", "BIOS Characteristics are not supported",
"ISA is supported", "MICA is supported","EISA is supported","PCI is supported",
"PC card(PCMCIA) is supported", "Plug and Play is supported",
"APM is supported", "BIOS is upgradeable(Flash)", "BIOS shadowing is allowed",
"VL-VESA is supported", "ESCD support is available",
"Boot from CD is supported", "Selected boot is supported",
"BIOS ROM is socketed", "Boot from PC card(PCMCIA)is supported",
"EDD specification is supported",
"Int 13h--Japanese floppy for NEC 9800 1.2 MB(3.5\",1K bytes/sector, 360 RPM)is supported",
"Int 13h--Japanese floppy for Toshiba 1.2 MB(3.5\", 360 RPM)is supported",
"Int 13h--5.25\"/360 KB floppy services are supported",
"Int 13h--5.25\"/1.2 MB floppy services are supported",
"Int 13h--3.5\"/720 KB floppy services are supported",
"Int 13h--5.25\"/2.88 MB floppy services are supported",
"Int 5h, print screen Service is supported",
"Int 9h, 8042 keyboard services are supported",
"Int 14h, serial services are supported",
"Int 17h, printer services are supported",
"Int 10h, CGA/Mono Video Services are supported",
"NEC PC-98", "Reserved for BIOS vendor", "Reserved for system vendor"
};
const char *characteristics_ex[]={
"ACPI is supported", "USB Legacy is supported", "AGP is supported",
"I2O boot is supported", "LS-120 SuperDisk boot is supported",
"ATAPI ZIP drive boot is supported", "1394 boot is supported",
"Smart battery is supported", "BIOS Boot Specification is supported",
"Function key-initiated network service boot is supported",
"Enabled targeted content distribution",
"UEFI Specification is supported",
"SMBIOS table describes a virtual machine",
"Reserved for future assignment"
};
DWORD Find_EPS_Addr(EPS *eps, BYTE *addr);
WORD Find_Structure(BYTE *TableAddress, WORD StructureCount, BYTE Type);
int main()
{
char ch ;
while(1)
{
printf("\n");
printf("***************************************************\n");
printf("* 1.show entries of type 0 *\n");
printf("* 2.exit *\n");
printf("***************************************************\n");
printf("PLEASE ENTER YOUR CHOICE : ");
scanf("%d",&ch);
while(getchar()!='\n')
continue;
switch(ch)
{
case 1:dmidecode();
break;
case 2:exit(0);
break;
default:printf("INVALID COMMAND!--NOT EXISTS \n");
break;
}
}
return 0;
}
DWORD Find_EPS_Addr(EPS *eps, BYTE *addr)
{
DWORD i;
BYTE * SM;
SM = addr;
for(i = 0; i <= 0xFFFF; i++)
{
if(SM == MAP_FAILED)
{
handle_error("mmap");
}
if(SM != '_' || SM != 'S' || SM != 'M' || SM != '_')
continue;
if(SM != '_' || SM != 'D' || SM != 'M' || SM != 'I'|| SM != '_')
continue;
eps->Length = *(short *)(SM + i + 0x16);
eps->Address = *(DWORD *)(SM + i + 0x18);
eps->Struct_Count = *(short *)(SM + i + 0x1C);
eps->Major_Version = *(short *)(SM + i + 0x06);
eps->Minor_Version = *(short *)(SM + i + 0x07);
}
return 0;
}
int dmidecode()
{
DWORD Table_Address,segment,offset;
EPS p = {0, 0, 0, 0, 0};
EPS *eps = &p;
int fd = open("/dev/mem",O_RDONLY|O_SYNC);
if(fd == -1)
{
handle_error("open /dev/mem");
return -1;
}
//void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
BYTE *addr= mmap(0, EndAddress-StartAddress, PROT_READ, MAP_SHARED, fd, 0xF0000);
Find_EPS_Addr(eps, addr);
printf("SMBIOS %d.%d present.\n", eps->Major_Version, eps->Minor_Version);
if(eps->Major_Version >= 3)
{
printf("# SMBIOS implementations newer than version 3.0 are not\n");
printf("# fully supported by this version of dmidecode.\n");
}
printf("%d structures occupying %d bytes.\nTable at 0x%08X.\n", eps->Struct_Count, eps->Length, eps->Address);
Table_Address = eps->Address;
segment = Table_Address & 0xFFFF;
offset = Table_Address & 0xF0000;
BYTE * TableAddress = (BYTE *)mmap(0, segment + eps->Length , PROT_READ, MAP_SHARED, fd, offset);
Find_Structure((TableAddress + segment), eps->Struct_Count, 0);
//usage of munmap
//int munmap(void *addr, size_t length);
munmap(addr, 0xFFFF);
munmap(TableAddress, 0xFFFF);
return 0;
}
//Find specified type0 's structure
//TableAddress value is located at offset 18h in EPS table
//StructureCount value is located at offset 1Ch in EPS
WORD Find_Structure(BYTE *TableAddress, WORD StructureCount, BYTE Type)
{
int i;
char *str;
BYTE currtype;
BYTE *Addr;
BYTE *firstAddr = TableAddress;
while(TableAddress-firstAddr <StructureCount)
{
currtype = ((Header *)TableAddress)->Type;
if(currtype != 0)
{
TableAddress += ((Header *)TableAddress)->Length;
while(*(WORD *)TableAddress != 0)
{
TableAddress ++;
}
TableAddress += 2;
}
else
{
Addr = TableAddress;
TableAddress += ((Header *)Addr)->Length;
while(*(WORD *)TableAddress != 0 && *(WORD *)(TableAddress -1) !=0)
{
str = (char *)TableAddress;
while(*(BYTE *)TableAddress != 0)
{
TableAddress ++;
}
i ++;
TableAddress ++;
}
}
}
BYTE type = Addr;
BYTE length = Addr;
WORD handle = Addr;
printf("\nHandle 0x%04x, DMI type %d, %d bytes\n",handle,type,length);
printf("BIOS Information\n");
//vendor
printf("%15s %s\n","Vendor:", Addr==0x0000 ? "": str]);
//version
printf("%16s %s\n","Version:", Addr==0x0000 ? "": str]);
//address
WORD Address = *(WORD *)(Addr+6);
printf("%16s 0x%X\n","Address:", StartAddress);
//release date
printf("%21s %s\n","Release Date:", Addr==0x0000 ? "": str]);
//Runtime Size
printf("%21s %d %s\n","Runtime Size:", (0x10000-Address) * 16 /1024, "KB");
//ROM Size
printf("%17s %d %s\n","ROM Size:", (Addr+1) * 64, "KB");
//BIOS Characteristics
printf("%24s\n","Characteristics:");
QWORD CHAR = *(QWORD *)(Addr + 0x0A);
WORD CHAR_ex = *(WORD *)(Addr + 0x12);
//printf("%x\n",CHAR);
//0011_0111_1000_1011_1001_1000_1000_0000b
for(i = 0; i < 32; i++)
{
if((CHAR >> i) & 1)//check if each bit equals to 1
{
printf("%16s%s\n","",characteristics);
}
}
for(i = 0; i < 13; i++)
{
if((CHAR_ex >> i) & 1)
{
printf("%16s%s\n","",characteristics_ex);
}
}
//BIOS Revision
//if the system does not support the use of this field ,the value is 0FFh
if(Addr != 0xFF || Addr != 0xFF)
{
printf("%22s %d.%d\n","BIOS Revision:",Addr,Addr);
}
//Firmware Revision
//if the system does not have field upgradeable embedded controller firmware ,the value is 0FFh
if(Addr != 0xFF || Addr != 0xFF)
{
printf("%26s %d.%d\n","Firmware Revision:",Addr,Addr);
}
return 0;
}
有人可以根据这个帮忙改一版代码吗? 是这个吗?
https://blog.csdn.net/zhoudaxia/article/details/5919699
那么看到下面这张图,你是不是就会写代码了?
#include <stdio.h>
#include <stdlib.h>
#define __USE_GNU
#include <string.h>
#include <errno.h>
int main(void) {
FILE *fp = fopen("/dev/mem", "r");
if(!fp) {
int err = errno;
perror("/dev/mem");
exit(-err);
}
fseek(fp, 0xf0000, SEEK_SET);
char buff;
fread(buff, 1, 65536, fp);
char *eps = memmem(buff, 65536, "_SM_", 4);
if(eps && !strncmp(eps + 16, "_DMI_", 5)) {
eps = (char *)(eps - buff + 0xf0000);
printf("%p\n", eps);
}
fclose(fp);
return 0;
}
人造人 发表于 2022-10-10 18:11
谢谢大佬,请问这个程序是实现了什么功能呢?我希望的是可以完成遍历SMBIOS信息 2wsx 发表于 2022-10-10 19:07
谢谢大佬,请问这个程序是实现了什么功能呢?我希望的是可以完成遍历SMBIOS信息
这篇文章你看了吗?
https://blog.csdn.net/zhoudaxia/article/details/5919699
对于非 EFI 的系统,访问 SMBIOS EPS 表的操作过程如下:
1 .从物理内存 0x000F0000-0x000FFFFF 之间寻找关键字 “ _SM_” 。
2 .找到后再向后 16 个字节,看后面 5 个 BYTE 是否是关键字 “_DMI_” ,如果是, EPS 表即找到。
对于 UEFI (是 BIOS 的下一代版本)系统,可能通过搜索 EFI 配置表中的 SMBIOS GUID(SMBIOS_TABLE_GUID) ,然后使用指向 SMBIOS 的指针来定位 EPS 表。具体可参考 UEFI 规范。
上面的代码定位eps表在内存中的位置
本帖最后由 howzyao 于 2022-10-15 11:24 编辑
人造人 发表于 2022-10-10 18:11
fseek(fp, 0xf0000, SEEK_SET);
中的 0xf0000 可以理解成1个0代表2进制的8个位吗? 共4*8=32个位,分成4段,每段8个位.谢谢 howzyao 发表于 2022-10-15 11:20
fseek(fp, 0xf0000, SEEK_SET);
中的 0xf0000 可以理解成1个0代表2进制的8个位吗? 共4*8=32个位,分 ...
一个0是4个bit
页:
[1]