[TC++] 在 DOS 下讀寫 DMI 的方法

兩個由 Turbo C++ 寫的在 DOS 下讀寫 DMI 的 sample code。

Sample code 1:這是使用搜尋方法尋找記憶體中 BIOS 區域 (F000:0000 ~ F000:FFFF) 中的 SMBIOS 與 DMI table來讀取 DMI 訊息的方法,這個方法只能讀取無法改寫 DMI 內容。

#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <conio.h>
unsigned char far *TblAddr_Ptr;
unsigned int TblLen;

typedef struct
{
    unsigned char type;
    unsigned char length;
    unsigned short handle;
}Header;

/*search two strings in one function*/
int Search_Strs(unsigned int seg_addr, unsigned int offset_addr, char *str1, char *str2)
{
    unsigned char far *ptr;
    int j;
    ptr = (unsigned char far *)MK_FP(seg_addr, offset_addr);

    for (; (long)ptr <= 0xFFFF0;) {
        for (j = 0; j < strlen(str1); j++) /*search the first string*/
            if (*(ptr + j) != *(str1 + j)) break;

        if (j >= strlen(str1)) {
            ptr += 0x10;
            for (j = 0; j < strlen(str2); j++) /*search the next*/
                if (*(ptr + j) != *(str2 + j)) break;
            if (j >= strlen(str2)) {TblAddr_Ptr = ptr + 8;
            TblLen = *((unsigned int far *)(ptr + 6));
            return 1;}
        }
        else {
            ptr += 0x10;
        }
    }
    return 0;
}

/*print the string in a structure specified by the number of it*/
void PrintSpecifiedStr(unsigned char far *HeadAddrOfTypeN, unsigned char length, unsigned char NumOfStr, char *HeaderOfStr)
{
    unsigned char far *p = HeadAddrOfTypeN + length;
    int i = 1, j = 0;
    printf("%s", HeaderOfStr);

    if (!NumOfStr) {printf("Unknow\r\n"); return;}
    while (1) {
        while (*(p + (j++)));
        if (i == NumOfStr) {
            for (i = 0; i < j; i++) printf("%c", *(p + i));

            printf("\r\n");
            return;
        }
        else {i++; p += j; j = 0;}
    }

}

void main(void)
{
    char *str1 = "_SM_";
    char *str2 = "_DMI_";
    unsigned int seg, offset;
    unsigned char far *TableAddr;
    unsigned char type, LenOfStructure;
    int i = 0, flag = 0;
    clrscr();
    if (Search_Strs(0xF000, 0, str1, str2)) {
        /*get segment and offset address of SMBIOS Table*/
        seg = *((unsigned int far *)(TblAddr_Ptr + 2));
        seg <<= 12;
        offset = *((unsigned int far *)TblAddr_Ptr);
        TableAddr = (unsigned char far *)MK_FP(seg, offset);

        while (i < TblLen) {
            type = ((Header far *)TableAddr)->type;

            if (!type && !flag) { /*print Type 0*/
                LenOfStructure = ((Header far *)TableAddr)->length;
                printf("\r\n");
                printf("BIOS Information (Type 0)\r\n\r\n");

                printf("Type:%d\r\n", type);
                printf("Length:%d\r\n", LenOfStructure);
                printf("Handle:%.4x\r\n", ((Header far *)TableAddr)->handle);

                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 4), "Vendor:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 5), "BIOS Version:");
                printf("BIOS Starting Address Segment:%.4x\r\n", (*(unsigned int far *)(TableAddr + 6)));
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 8), "BIOS Release Date:");
                printf("BIOS ROM Size:%dKB\r\n", (*(TableAddr + 9) + 1) * 64);
                printf("BIOS Characteristics:%.8x%.8x\r\n", *((long far *)(TableAddr + 0x0e)), *((long far *)(TableAddr + 0x0a)));
                printf("BIOS Characterics Extension Bytes:%.4x\r\n", *((int far *)(TableAddr + 0x12)));
                printf("System BIOS Major Release:%d\r\n", *(TableAddr + 0x14));
                printf("System BIOS Minor Release:%d\r\n", *(TableAddr + 0x15));
                printf("Embedded Controller Firmware Major Release:%d\r\n", *(TableAddr + 0x16));
                printf("Embedded Controller Firmware Minor Release:%d\r\n", *(TableAddr + 0x17));
                flag = 1;

                printf("press any key to continue...\r\n");
                getch();
                clrscr();
            }
            else if (type == 1) { /*print Type 1*/
                LenOfStructure = ((Header far *)TableAddr)->length;
                printf("\r\n");
                printf("System Information (Type 1)\r\n\r\n");

                printf("Type:%d\r\n", type);
                printf("Length:%d\r\n", LenOfStructure);
                printf("Handle:%.4x\r\n", ((Header far *)TableAddr)->handle);

                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x04), "Manufacturer:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x05), "Product Name:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x06), "Version:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x07), "Serial Number:");
                printf("UUID:%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X \r\n",
                       *((char far *)(TableAddr + 0x08)),
                       *((char far *)(TableAddr + 0x09)),
                       *((char far *)(TableAddr + 0x0a)),
                       *((char far *)(TableAddr + 0x0b)),
                       *((char far *)(TableAddr + 0x0c)),
                       *((char far *)(TableAddr + 0x0d)),
                       *((char far *)(TableAddr + 0x0e)),
                       *((char far *)(TableAddr + 0x0f)),
                       *((char far *)(TableAddr + 0x10)),
                       *((char far *)(TableAddr + 0x11)),
                       *((char far *)(TableAddr + 0x12)),
                       *((char far *)(TableAddr + 0x13)),
                       *((char far *)(TableAddr + 0x14)),
                       *((char far *)(TableAddr + 0x15)),
                       *((char far *)(TableAddr + 0x16)),
                       *((char far *)(TableAddr + 0x17))
                       );

                printf("press any key to continue...\r\n");
                getch();
                clrscr();
            }
            else if (type == 2) { /*print Type 2*/
                LenOfStructure = ((Header far *)TableAddr)->length;
                printf("\r\n");
                printf("Base Board Information (Type 2)\r\n\r\n");

                printf("Type:%d\r\n", type);
                printf("Length:%d\r\n", LenOfStructure);
                printf("Handle:%.4x\r\n", ((Header far *)TableAddr)->handle);

                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x04), "Manufacturer:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x05), "Product Name:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x06), "Version:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x07), "Serial Number:");

                printf("press any key to continue...\r\n");
                getch();
                clrscr();
            }
            else if (type == 17) { /*print Type 17*/
                LenOfStructure = ((Header far *)TableAddr)->length;
                printf("\r\n");
                printf("Memory Device (Type 17)\r\n\r\n");

                printf("Type:%d\r\n", type);
                printf("Length:%d\r\n", LenOfStructure);
                printf("Handle:%.4x\r\n", ((Header far *)TableAddr)->handle);

                printf("Physical Memory Array Handle:%.4x\r\n", *((int far *)(TableAddr + 4)));
                printf("Memory Error Information Handle:%.4x\r\n", *((int far *)(TableAddr + 6)));
                printf("Total Width:%d\r\n", *((int far *)(TableAddr + 8)));
                printf("Data Width:%d\r\n", *((int far *)(TableAddr + 10)));
                printf("size:%d%s\r\n", (*((int far *)(TableAddr + 0x0c)) & 0x7fff), (*((int far *)(TableAddr + 0x0c)) & 0x8000) ? "KB" : "MB");
                printf("Form Factor:%d\r\n", *(TableAddr + 0x0e));
                printf("Device Set:%d\r\n", *(TableAddr + 0x0f));
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x10), "Device Locator:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x11), "Bank Locator:");
                printf("Meomroy Type:%d\r\n", *(TableAddr + 0x12));
                printf("Type Detail:%.4x\r\n", *((int far *)(TableAddr + 0x13)));
                printf("Speed:%dMHz\r\n", *((int far *)(TableAddr + 0x15)));
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x17), "Manufacturer:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x18), "Serial Number:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x19), "Asset Tag:");
                PrintSpecifiedStr(TableAddr, LenOfStructure, *(TableAddr + 0x1a), "Part Number:");
                printf("Attributes:%.2x\r\n", *(TableAddr + 0x1b));
                getch();
                break;
            }
            /*skip the unformatted string*/
            TableAddr += ((Header far *)TableAddr)->length;
            while (*((int far *)TableAddr) != 0) TableAddr++;
            TableAddr += 2;
            i++;
        }
    }
}

 

Sample Code 2:這個範例是透過標準的 PnP function 50h, 51h, 52h 來讀寫 DMI ,透過這方法可以讀取與寫入 DMI 資訊。

#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>

typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef unsigned long       DWORD;
typedef BYTE near           *PBYTE;
typedef BYTE far            *LPBYTE;
typedef WORD near           *PWORD;
typedef WORD far            *LPWORD;
typedef DWORD near          *PDWORD;
typedef DWORD far           *LPDWORD;
typedef void near           *LVOID;
typedef void far            *LPVOID;

typedef struct {                              //PnP installation check data
    BYTE    Signature[4];                     // 00h "$PnP"
    BYTE    Version;                          // 04h
    BYTE    Length;                           // 05h
    WORD    Control_Field;                    // 06h
    BYTE    Checksum;                         // 08h
    DWORD   Event_NF_Addr;                    // 09h Event notification flag address
    WORD    RM_EP_Offset;                     // 0Dh Real Mode 16-bit offset to entry point
    WORD    RM_EP_Segment;                    // 0Fh Real Mode 16-bit code segment address
    WORD    PM_EP_Offset;                     // 11h 16-Bit Protected Mode offset to entry point
    DWORD   PM_EP_Segment;                    // 13h 16-Bit Protected Mode code segment base address
    DWORD   OEM_Device_ID;                    // 17h OEM Device Identifier
    WORD    RM_BIOS_Data_Segment;             // 1Bh Real Mode 16-bit data segment address
    DWORD   PM_BIOS_Data_Segment;             // 1Dh 16-Bit Protected Mode data segment base address
} PNP_ICD;

typedef short far (*entryPoint_Func50)(
    WORD Function,                            // PnP BIOS Function 50h
    LPBYTE dmiBIOSRevision,                   // Revision of the SMBIOS Extensions
    LPWORD NumStructures,                     // Max. Number of Structures the BIOS will return
    LPWORD StructureSize,                     // Size of largest SMBIOS Structure
    LPDWORD dmiStorageBase,                   // 32-bit physical base address for memory-mapped SMBIOS data
    LPWORD dmiStorageSize,                    // Size of the memory-mapped SMBIOS data
    WORD BiosSelector);                       // PnP BIOS readable/writable selector


typedef short far (*entryPoint_Func51)(
    WORD Function,                            // PnP BIOS Function 51h
    LPWORD Structure,                         // Structure number/handle to retrieve
    LPBYTE dmiStrucBuffer,                    // Pointer to buffer to copy structure data
    WORD dmiSelector,                         // SMBIOS data read/write selector
    WORD BiosSelector);                       // PnP BIOS readable/writable selector

typedef short far (*entryPoint_Func52)(
    WORD Function,                            // PnP BIOS Function 52h
    LPBYTE dmiDataBuffer,                     // Pointer to buffer with new/change data
    LPBYTE dmiWorkBuffer,                     // Pointer to work buffer area for the BIOS
    BYTE Control,                             // Conditions for performing operation
    WORD dmiSelector,                         // SMBIOS data read/write selector
    WORD BiosSelector);                       // PnP BIOS readable/writeable selector

typedef short far (*entryPoint_Func53)(
    WORD Function,                            // PnP BIOS Function 53h
    LPBYTE dmiChangeStructure,                // Pointer to SMBIOS Change structure
    WORD dmiSelector,                         // SMBIOS data read/write selector
    WORD BiosSelector);                       // PnP BIOS readable writable selector

typedef short far (*entryPoint_Func54)(
    WORD          Function,                   // PnP BIOS Function 54h
    WORD          SubFunction,                // Defines the specific control operation
    LPVOID *Data,                             // Input/output data buffer, SubFunction specific
    BYTE  Control,                            // Conditions for setting the structure
    WORD dmiSelector,                         // SMBIOS data read/write selector
    WORD BiosSelector);                       // PnP BIOS readable/writeable selector

typedef short far (*entryPoint_Func55)(
    WORD Function,                            // PnP BIOS Function 55h
    LPWORD Handle,                            // Identifies which GPNV to access
    LPWORD MinGPNVRWSize,                     // Minimum buffer size in bytes for GPNV access
    LPWORD GPNVSize,                          // Size allocated for GPNV within the R/W Block
    LPDWORD NVStorageBase,                    // 32-bit physical base address for... mem. mapped nonvolatile storage media
    WORD BiosSelector);                       // PnP BIOS readable/writable selector

typedef short far (*entryPoint_Func56)(
    WORD Function,                            // PnP BIOS Function 56h
    WORD Handle,                              // Identifies which GPNV is to be read
    LPBYTE GPNVBuffer,                        // Address of buffer in which to return GPNV
    LPWORD GPNVLock,                          // Lock value
    WORD GPNVSelector,                        // Selector for GPNV Storage
    WORD BiosSelector);                       // PnP BIOS readable/writable selector

typedef short far (*entryPoint_Func57)(
    WORD Function,                            // PnP BIOS Function 57h
    WORD Handle,                              // Identifies which GPNV is to be written
    LPBYTE GPNVBuffer,                        // Address of buffer containing complete GPNV to write
    WORD GPNVLock,                            // Lock value
    WORD GPNVSelector,                        // Selector for GPNV Storage
    WORD BiosSelector);                       // PnP BIOS readable/writable selector


/**
    SMBIOS Structure Header - Common for all structures
    Describing the type, size of the fixed area, and handle
    of the structure.
**/
typedef struct {
    BYTE  Type;
    BYTE  Length;
    WORD  Handle;
} SMBIOS_STRUCTURE_HEADER;

/**
    Set SMBIOS Structure Data
**/
typedef struct {
    BYTE                    Command;
    BYTE                    FieldOffset;
    DWORD                   ChangeMask;
    DWORD                   ChangeValue;
    WORD                    DataLength;
    SMBIOS_STRUCTURE_HEADER StructureHeader;
    BYTE                    StructureData[1];
} SET_SMBIOS_STRUCTURE_DATA;

/**
    BIOS Information Structure (Type 0)
**/
typedef struct {
    SMBIOS_STRUCTURE_HEADER  StructureType;
    BYTE                     BiosVendor;                     // String number
    BYTE                     BiosVersion;                    // String number
    WORD                     BiosStartingAddrSegment;
    BYTE                     BiosReleaseDate;                // String number
    BYTE                     BiosRomSize;
    DWORD                    BiosChar_1;
    DWORD                    BiosChar_2;
    BYTE                     BiosCharExtByte1;
    BYTE                     BiosCharExtByte2;
    BYTE                     SystemBiosMajorRelease;
    BYTE                     SystemBiosMinorRelease;
    BYTE                     ECFirmwareMajorRelease;
    BYTE                     ECFirmwareMinorRelease;
} SMBIOS_BIOS_INFO;                                           // TYPE 0

/**
    System Information Structure (Type 1)
**/
typedef struct {
    SMBIOS_STRUCTURE_HEADER  StructureType;
    BYTE                     Manufacturer;                   // String number
    BYTE                     ProductName;                    // String number
    BYTE                     Version;                        // String number
    BYTE                     SerialNumber;                   // String number
    BYTE                     Uuid[16];
    BYTE                     WakeupType;
    BYTE                     SkuNumber;
    BYTE                     Family;
} SMBIOS_SYSTEM_INFO;                                         // TYPE 1

/**
    Base Board (or Module) Information Structure (Type 2)
**/
typedef struct {
    SMBIOS_STRUCTURE_HEADER  StructureType;
    BYTE                     Manufacturer;                   // String number
    BYTE                     ProductName;                    // String number
    BYTE                     Version;                        // String number
    BYTE                     SerialNumber;                   // String number
    BYTE                     AssetTag;                       // String number
    BYTE                     FeatureTag;
    BYTE                     Location;                       // String number
    WORD                     ChassisHandle;
    BYTE                     BoardType;
    BYTE                     NumberOfObjectHandles;
} SMBIOS_BASE_BOARD_INFO;                                     // TYPE 2

void PrintType0(SMBIOS_BIOS_INFO *type0);
void PrintType1(SMBIOS_SYSTEM_INFO *type1);
void PrintType2(SMBIOS_BASE_BOARD_INFO *type2);

/***************************************/
/*Function:Get PnP Table
/*In : struct PNP_ICD *PnPICDS
/*Out: 0, No PnP Table
/*Out: 1, Get PnP Table
/***************************************/
int GetPnPTable(PNP_ICD *PnPICD)
{
	LPBYTE BIOS;

	BIOS = (LPBYTE)MK_FP(0xf000, 0);
    for (DWORD i = 0; i < 0xfff0; i += 0x10) {
		if (BIOS[i] == '$' && BIOS[i + 1] == 'P' && BIOS[i + 2] == 'n' && BIOS[i + 3] == 'P') {
            for (DWORD j = 0; j <= sizeof(PNP_ICD); j++) {
                ((BYTE*)PnPICD)[j] = BIOS[i + j];
            }
            return 1;
		}
	}
	return 0;
}


//return 1 if error
int PrintDMI()
{
    PNP_ICD *PnP;
    WORD rlt;
	BYTE dmiBIOSRevision;
    WORD NumStructures;
    WORD StructureSize;
    DWORD dmiStorageBase;
    WORD dmiStorageSize;
    WORD BiosSelector;
	WORD Structure;
    LPBYTE dmiStrucBuffer;
    WORD dmiSelector;

    PnP = (PNP_ICD *)malloc(sizeof(PNP_ICD));
    if (GetPnPTable(PnP) == 0) {
        printf("Can't find PnP BIOS support Installation Check Data Structure.\n");
        free(PnP);
        return 1;
    }

    printf("=========================================================\n");
    printf("PnP Table\n\n");
    printf("Signature:                                       %c%c%c%c\n", PnP->Signature[0],
                                                                          PnP->Signature[1],
                                                                          PnP->Signature[2],
                                                                          PnP->Signature[3]);
    printf("Version:                                         %02Xh\n",    PnP->Version);
    printf("Length:                                          %02Xh\n",    PnP->Length);
    printf("Control Field:                                   %04Xh\n",    PnP->Control_Field);
    printf("Checksum:                                        %02Xh\n",    PnP->Checksum);
    printf("Event Notification Flag Address:                 %08Xh\n",    PnP->Event_NF_Addr);
    printf("Real Mode 16-bit offset to entry point:          %04Xh\n",    PnP->RM_EP_Offset);
    printf("Real Mode 16-bit code segment address:           %04Xh\n",    PnP->RM_EP_Segment);
    printf("16-Bit Protected Mode offset to entry point:     %04Xh\n",    PnP->PM_EP_Offset);
    printf("16-Bit Protected Mode code segment base address: %08Xh\n",    PnP->PM_EP_Segment);
    printf("OEM Device Identifier:                           %08Xh\n",    PnP->OEM_Device_ID);
    printf("Real Mode 16-bit data segment address:           %04Xh\n",    PnP->RM_BIOS_Data_Segment);
    printf("16-Bit Protected Mode data segment base address: %08Xh\n",    PnP->PM_BIOS_Data_Segment);
    printf("=========================================================\n\n");
    getch();


    BiosSelector = PnP->RM_BIOS_Data_Segment;
    entryPoint_Func50 Func50 = (entryPoint_Func50)MK_FP(PnP->RM_EP_Segment,PnP->RM_EP_Offset);
    entryPoint_Func51 Func51 = (entryPoint_Func51)MK_FP(PnP->RM_EP_Segment,PnP->RM_EP_Offset);

    rlt = Func50(0x50,
        &dmiBIOSRevision,
        &NumStructures,
        &StructureSize,
        &dmiStorageBase,
        &dmiStorageSize,
        BiosSelector
		);
    if (rlt != 0x00) {
        printf("ERROR: %02Xh\n", rlt);
        exit(1);
        free(PnP);
        return 1;
	}

    printf("=========================================================\n");
    printf("Function 50h: Get SMBIOS Information\n\n");
    printf("Revision of the SMBIOS Extensions:                          %02Xh \n", dmiBIOSRevision);
    printf("Max. Number of Structures the BIOS will return:             %04Xh \n", NumStructures);
    printf("Size of largest SMBIOS Structure:                           %04Xh \n", StructureSize);
    printf("32-bit physical base address for memory-mapped SMBIOS data: %08Xh \n", dmiStorageBase);
    printf("Size of the memory-mapped SMBIOS data:                      %04Xh \n", dmiStorageSize);
    printf("PnP BIOS readable/writable selector:                        %04Xh \n", BiosSelector);
    printf("=========================================================\n\n");
    getch();

    dmiSelector = (WORD)(dmiStorageBase >> 4);
    dmiStrucBuffer = (LPBYTE)malloc(sizeof(BYTE) * (StructureSize));

    //If Structure contains zero, the system BIOS will return the first SMBIOS Structure.
    Structure = 0;
    while ((Structure) != 0xffff) {
        rlt = Func51(
            0x51,
            &Structure,
            dmiStrucBuffer,
            dmiSelector,
            BiosSelector
            );
        if (rlt != 0) {
            printf("ERROR: %02Xh\n", rlt);
            exit(1);
            free(PnP);
            free((void *)dmiStrucBuffer);
            return 1;
        }


        switch (((SMBIOS_STRUCTURE_HEADER*)dmiStrucBuffer)->Type) {
        case 0:                             //type 0
            PrintType0((SMBIOS_BIOS_INFO*)dmiStrucBuffer);
            getch();
            break;

        case 1:                             //type 1
            PrintType1((SMBIOS_SYSTEM_INFO*)dmiStrucBuffer);
            getch();
            break;

        case 2:                             //type 2
            PrintType2((SMBIOS_BASE_BOARD_INFO*)dmiStrucBuffer);
            getch();
            break;
        }
    }

    free(PnP);
    free((void *)dmiStrucBuffer);
    return 0;
}

int UpdateDMI()
{
    PNP_ICD *PnP;
    WORD rlt;
	BYTE dmiBIOSRevision;
    WORD NumStructures;
    WORD StructureSize;
    DWORD dmiStorageBase;
    WORD dmiStorageSize;
    WORD BiosSelector;
	WORD Structure;
    LPBYTE dmiStrucBuffer;
    WORD dmiSelector;

    PnP = (PNP_ICD *)malloc(sizeof(PNP_ICD));
    if (GetPnPTable(PnP) == 0) {
        printf("Can't find PnP BIOS support Installation Check Data Structure.\n");
        free(PnP);
        return 1;
    }

    BiosSelector = PnP->RM_BIOS_Data_Segment;
    entryPoint_Func50 Func50 = (entryPoint_Func50)MK_FP(PnP->RM_EP_Segment,PnP->RM_EP_Offset);
    entryPoint_Func51 Func51 = (entryPoint_Func51)MK_FP(PnP->RM_EP_Segment,PnP->RM_EP_Offset);
    entryPoint_Func52 Func52 = (entryPoint_Func52)MK_FP(PnP->RM_EP_Segment,PnP->RM_EP_Offset);

    rlt = Func50(0x50,
        &dmiBIOSRevision,
        &NumStructures,
        &StructureSize,
        &dmiStorageBase,
        &dmiStorageSize,
        BiosSelector
		);
    if (rlt != 0x00) {
        printf("ERROR: %02Xh\n", rlt);
        exit(1);
        free(PnP);
        return 1;
	}

    dmiSelector = (WORD)(dmiStorageBase >> 4);
    dmiStrucBuffer = (LPBYTE)malloc(sizeof(BYTE) * (StructureSize));

    //If Structure contains zero, the system BIOS will return the first SMBIOS Structure.
    Structure = 0;
    while ((Structure) != 0xffff) {
        rlt = Func51(
            0x51,
            &Structure,
            dmiStrucBuffer,
            dmiSelector,
            BiosSelector
            );
        if (rlt != 0) {
            printf("ERROR: %02Xh\n", rlt);
            exit(1);
            free(PnP);
            free((void *)dmiStrucBuffer);
            return 1;
        }


        switch (((SMBIOS_STRUCTURE_HEADER*)dmiStrucBuffer)->Type) {
        case 1:                             //type 1
            SET_SMBIOS_STRUCTURE_DATA *newData;

            printf("Wirte new TYPE1 UUID: 99887766 55443322 11001122 33445566\n");
            printf("Press 'y' to Write\n");
            if (getch() == 'y') {
                //Update Type 1 UUID
                BYTE NewUUID[16] = { 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
                newData = (SET_SMBIOS_STRUCTURE_DATA *)malloc(sizeof(SET_SMBIOS_STRUCTURE_DATA) + 16);
                newData->Command = 0x06;    //a block of information
                newData->FieldOffset = offsetof(SMBIOS_SYSTEM_INFO, Uuid);
                newData->ChangeMask = 0;
                newData->ChangeValue = 0;
                newData->DataLength = 16;
                newData->StructureHeader.Type = ((SMBIOS_SYSTEM_INFO *)dmiStrucBuffer)->StructureType.Type;
                newData->StructureHeader.Handle = ((SMBIOS_SYSTEM_INFO *)dmiStrucBuffer)->StructureType.Handle;
                newData->StructureHeader.Length = ((SMBIOS_SYSTEM_INFO *)dmiStrucBuffer)->StructureType.Length;
                for (int i = 0; i < 16; i++) {
                    newData->StructureData[i] = NewUUID[i];
                }

                rlt = Func52(0x52, (LPBYTE)newData, dmiStrucBuffer, 1, dmiSelector, BiosSelector);
                if (rlt != 0) {
                    printf("ERROR: %02Xh\n", rlt);
                    exit(1);
                    free(newData);
                    free(PnP);
                    free((void *)dmiStrucBuffer);
                    return 1;
                }
                else
                {
                    printf("Success !!\n\n");
                }
                free(newData);
            }
            else {
                printf("Cancel !!\n\n");
            }

            //Update Type 1 Manufacturer string
            printf("Wirte new TYPE1 Manufacturer: \"New Manufacturer\"\n");
            printf("Press 'y' to Write\n");
            if (getch() == 'y') {
                WORD StringNumber = ((SMBIOS_SYSTEM_INFO *)dmiStrucBuffer)->Manufacturer + 3;
                BYTE NewManufacturer[] = "New Manufacturer";
                WORD strLength = strlen(NewManufacturer);
                newData = (SET_SMBIOS_STRUCTURE_DATA *)malloc(sizeof(SET_SMBIOS_STRUCTURE_DATA) + strLength);
                newData->Command = 0x05;                //a string value is to be changed
                newData->FieldOffset = StringNumber;
                newData->ChangeMask = 0;
                newData->ChangeValue = 0;
                newData->DataLength = strLength+1;
                newData->StructureHeader.Type = ((SMBIOS_SYSTEM_INFO *)dmiStrucBuffer)->StructureType.Type;
                newData->StructureHeader.Handle = ((SMBIOS_SYSTEM_INFO *)dmiStrucBuffer)->StructureType.Handle;
                newData->StructureHeader.Length = ((SMBIOS_SYSTEM_INFO *)dmiStrucBuffer)->StructureType.Length;
                strcpy((char*)newData->StructureData, (char*)NewManufacturer);
                rlt = Func52(0x52, (LPBYTE)newData, dmiStrucBuffer, 1, dmiSelector, BiosSelector);
                if (rlt != 0) {
                    printf("ERROR: %02Xh\n", rlt);
                    exit(1);
                    free(newData);
                    free(PnP);
                    free((void *)dmiStrucBuffer);
                    return 1;
                }
                else {
                    printf("Success !!\n\n");
                }
                free(newData);
            }
            else {
                printf("Cancel !!\n\n");
            }



            break;
        }
    }

    free(PnP);
    free((void *)dmiStrucBuffer);
    return 0;
}


LPBYTE GetStrPtr(LPBYTE typeN, BYTE StirngNumber)
{
    LPBYTE p = typeN + ((SMBIOS_STRUCTURE_HEADER*)typeN)->Length;
    int strNum = 1, j = 0;

    if (StirngNumber) {
        while (1) {
            while (*(p + (j++)));
            if (strNum == StirngNumber) {
                return p;
            }
            else {
                strNum++;
                p += j;
                j = 0;
            }
        }
    }

    return NULL;
}

void PrintType0(SMBIOS_BIOS_INFO *type0)
{
    printf("=========================================================\n");
    printf("Type 0: BIOS Information\n\n");
    printf("Bios Vendor:       \"%s\" \n", GetStrPtr((LPBYTE)type0, type0->BiosVendor));
    printf("Bios Version:      \"%s\" \n", GetStrPtr((LPBYTE)type0, type0->BiosVersion));
    printf("Bios Release Date: \"%s\" \n", GetStrPtr((LPBYTE)type0, type0->BiosReleaseDate));
    printf("BIOS ROM Size:     %dK \n", (type0->BiosRomSize+1)*64);
    printf("=========================================================\n\n");

}

void PrintType1(SMBIOS_SYSTEM_INFO *type1)
{
    printf("=========================================================\n");
    printf("Type 1: System Information\n\n");
    printf("Manufacturer: \"%s\" \n", GetStrPtr((LPBYTE)type1, type1->Manufacturer));
    printf("ProductName:  \"%s\" \n", GetStrPtr((LPBYTE)type1, type1->ProductName));
    printf("Version:      \"%s\" \n", GetStrPtr((LPBYTE)type1, type1->Version));
    printf("SerialNumber: \"%s\" \n", GetStrPtr((LPBYTE)type1, type1->SerialNumber));
    printf("UUID:         %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X \n",
           type1->Uuid[0], type1->Uuid[1], type1->Uuid[2], type1->Uuid[3],
           type1->Uuid[4], type1->Uuid[5], type1->Uuid[6], type1->Uuid[7],
           type1->Uuid[8], type1->Uuid[9], type1->Uuid[10], type1->Uuid[11],
           type1->Uuid[12], type1->Uuid[13], type1->Uuid[14], type1->Uuid[15]);
    printf("=========================================================\n\n");
}

void PrintType2(SMBIOS_BASE_BOARD_INFO *type2)
{
    printf("=========================================================\n");
    printf("Type 2: Base Board Information\n\n");
    printf("Manufacturer: \"%s\" \n", GetStrPtr((LPBYTE)type2, type2->Manufacturer));
    printf("ProductName:  \"%s\" \n", GetStrPtr((LPBYTE)type2, type2->ProductName));
    printf("Version:      \"%s\" \n", GetStrPtr((LPBYTE)type2, type2->Version));
    printf("SerialNumber: \"%s\" \n", GetStrPtr((LPBYTE)type2, type2->SerialNumber));
    printf("=========================================================\n\n");
}

void main(void)
{
    //Show DMI type0, type1, type2 information
    PrintDMI();

    //Update DMI type1 UUID and Manfacturer
    UpdateDMI();
}

 

參考資料:Plug and Play BIOS Specification、System Management BIOS
Reference Specification

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *