flat assembler
Message board for the users of flat assembler.

Index > Windows > Code for reading the SMBIOS table

Author
Thread Post new topic Reply to topic
Core i7



Joined: 14 Nov 2024
Posts: 84
Location: Socket on motherboard
Core i7 01 Jun 2025, 12:42
Here is an example of reading the SMBIOS base with function GetSystemFirmwareTable(). Information is output from the bios table(0), motherboard(2), and processor(4). I would be grateful for testing and errors found.
SMBIOS v3.8 specification: https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.8.0.pdf
Code:
format   pe gui 6.0
entry    start
include 'win32ax.inc'
;//-------------------
.data
ID_Name     =   1000
ID_Sock     =   1001
ID_Cores    =   1002
ID_Enable   =   1003
ID_Threads  =   1004
ID_Clock    =   1005
ID_Max      =   1006
ID_Speed    =   1007
ID_Volt     =   1008
ID_Mem      =   1009
ID_Tsc      =   1010

ID_Bios     =   1011
ID_Date     =   1012
ID_Bver     =   1013
ID_Rom      =   1014
ID_Uefi     =   1015

ID_Board    =   1016
ID_Prod     =   1017
ID_Mver     =   1018
ID_Sn       =   1019
ID_Tag      =   1020
ID_Win      =   1021

hModule     dd  0

;//-------------------
biosBase    dd  0
boardBase   dd  0
cpuBase     dd  0
mByte       dd  1024*1024
strBuff     rb  128

SocketTable     dd  0x15,@15,0x19,@19,0x1d,@1d,0x1e,@1e,0x1f,@1f,0x20,@20,0x21,@21,0x22,@22,0x23,@23,0x24,@24
                dd  0x25,@25,0x26,@26,0x2b,@26,0x2c,@2c,0x2d,@2d,0x2e,@2e,0x2f,@2f,0x30,@30,0x32,@32,0x33,@33
                dd  0x34,@34,0x35,@35,0x36,@36,0x39,@39,0x3a,@3a,0x3b,@3b,0x3c,@3c,0x3d,@3d,0x3e,@3e,0x00,@Unk  ;30=29
@15   db  'LGA775 ',0
@19   db  'LGA1366',0
@1d   db  'LGA1156',0
@1e   db  'LGA1567',0
@1f   db  'PGA988A',0
@20   db  'BGA1288',0
@21   db  'PGA988B',0
@22   db  'BGA1023',0
@23   db  'BGA1224',0
@24   db  'LGA1155',0
@25   db  'LGA1356',0
@26   db  'LGA2011',0
@2c   db  'LGA1356',0
@2d   db  'LGA1150',0
@2e   db  'BGA1168',0
@2f   db  'BGA1234',0
@30   db  'BGA1364',0
@32   db  'LGA1151',0
@33   db  'BGA1356',0
@34   db  'BGA1440',0
@35   db  'BGA1515',0
@36   db  'LGA3647',0
@39   db  'LGA2066',0
@3a   db  'BGA1392',0
@3b   db  'BGA1510',0
@3c   db  'BGA1528',0
@3d   db  'LGA4189',0
@3e   db  'LGA1200',0
@Unk  db  'Unknown',0

align 16
memStat   rb   64
buff      rb   4*1024

;//-------------------
.code
start:    invoke  GetModuleHandle,0
          mov     [hModule],eax
          invoke  DialogBoxParam, eax, 100, 0, DialogProc, 0
          invoke  ExitProcess, 0

proc  DialogProc hwnddlg, msg, wparam, lparam

          cmp     [msg],WM_INITDIALOG
          je      @INIT
          cmp     [msg],WM_TIMER
          je      @RDTSC
          cmp     [msg],WM_COMMAND
          je      @exit
          cmp     [msg],WM_CLOSE
          je      @close
          jmp     @next

;//************************************************************
;//****** "WM_INITDIALOG" Handler *****************************
;//************************************************************
@INIT:    invoke  SetWindowText,[hwnddlg],<'*** SMBIOS Info v1.0 ***',\
                                           '    https://board.flatassembler.net',0>

;// Dump SMBIOS Base
          mov     eax,'RSMB'
          bswap   eax
          invoke  GetSystemFirmwareTable,eax,0,buff,4096
          or      eax,eax
          jnz     @f

          invoke  MessageBox,0,<' Read SMBIOS Table Error!',0>,\
                               <'*** SMBIOS-CPU v0.2 ***',0>,0x10
          jmp     @close

@@:       mov     esi,buff+8
@FindCpuTable:
          movzx   eax,byte[esi+1]
          add     esi,eax
@@:       lodsb
          or      al,al
          jnz     @b
          cmp     byte[esi],0
          jnz     @b
          inc     esi
          cmp     byte[esi],2
          jnz     @f
          mov     [boardBase],esi
@@:       cmp     byte[esi],4
          jnz     @FindCpuTable

          mov     [cpuBase],esi

;// Product Name -------------------------
          mov     eax,0x80000002
          mov     ecx,3
          mov     edi,strBuff
@@:       push    eax ecx
          cpuid
          stosd
          xchg    eax,ebx
          stosd
          xchg    eax,ecx
          stosd
          xchg    eax,edx
          stosd
          pop     ecx eax
          inc     eax
          loop    @b
          invoke  SetDlgItemText,[hwnddlg],ID_Name,strBuff

;// Socket -------------------------------
          mov     esi,[cpuBase]
          movzx   ebx,byte[esi+25]
          mov     esi,SocketTable
          mov     ecx,29
@@:       lodsd
          cmp     eax,ebx
          je      @stop
          add     esi,4
          loop    @b
          add     esi,4           ;<-----------
@stop:    mov     esi,[esi]

          invoke  SetDlgItemText,[hwnddlg],ID_Sock,esi

;// Max Cores ----------------------------
          mov     esi,[cpuBase]
          movzx   eax,byte[esi+35]
         cinvoke  wsprintf,strBuff,<'%d',0>,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Cores,strBuff

;// Cores Enabled ------------------------
          mov     esi,[cpuBase]
          movzx   eax,byte[esi+36]
         cinvoke  wsprintf,strBuff,<'%d',0>,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Enable,strBuff

;// Threads ------------------------------
          mov     esi,[cpuBase]
          movzx   eax,byte[esi+37]
         cinvoke  wsprintf,strBuff,<'%d',0>,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Threads,strBuff

;// External Clock -----------------------
          mov     esi,[cpuBase]
          movzx   eax,word[esi+18]
         cinvoke  wsprintf,strBuff,<'%d MHz',0>,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Clock,strBuff

;// Speed --------------------------------
          mov     esi,[cpuBase]
          movzx   eax,word[esi+22]
         cinvoke  wsprintf,strBuff,<'%d MHz',0>,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Speed,strBuff

;// Max Speed ----------------------------
          mov     esi,[cpuBase]
          movzx   eax,word[esi+20]
         cinvoke  wsprintf,strBuff,<'%d MHz',0>,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Max,strBuff

;// Voltage ------------------------------
          mov     esi,[cpuBase]
          movzx   eax,byte[esi+17]
          and     al,not 80h
          xor     edx,edx
          mov     ebx,10
          div     ebx
         cinvoke  wsprintf,strBuff,<'%d.%d v',0>,eax,edx
          invoke  SetDlgItemText,[hwnddlg],ID_Volt,strBuff

;// Sys Memory ---------------------------
          mov     dword[memStat],8*8
          invoke  GlobalMemoryStatusEx,memStat
          fild    qword[memStat+8]
          fidiv   [mByte]
          fistp   dword[memStat]
         cinvoke  wsprintf,strBuff,<'%d MB',0>,dword[memStat]
          invoke  SetDlgItemText,[hwnddlg],ID_Mem,strBuff

;// Real Time Stamp Counter --------------
          rdtsc
         cinvoke  wsprintf,strBuff,<'%08X-%08X',0>,edx,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Tsc,strBuff


;/******* Parse BIOS Table(0) ***************************************
          mov     esi,buff+8
          mov     [biosBase],esi

;// Vendor -------------------------------
          movzx   eax,byte[esi+1]
          add     esi,eax
          push    esi
          invoke  SetDlgItemText,[hwnddlg],ID_Bios,esi    ;// Vendor
;// Version ------------------------------
          pop     esi
          mov     ecx,-1
          xchg    edi,esi
          xor     al,al
          repne   scasb
          xchg    edi,esi
          push    esi
          invoke  SetDlgItemText,[hwnddlg],ID_Bver,esi
;// Date ---------------------------------
          pop     esi
          mov     ecx,-1
          xchg    edi,esi
          xor     al,al
          repne   scasb
          xchg    edi,esi
          invoke  SetDlgItemText,[hwnddlg],ID_Date,esi
;// ROM size -----------------------------
          mov     esi,[biosBase]
          movzx   eax,byte[esi+9]
          inc     eax
          imul    eax,64*1024
          shr     eax,10           ;<----------------- Byte To Kbyte
         cinvoke  wsprintf,strBuff,<'%d KB',0>,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Rom,strBuff
;// EFI support --------------------------
          mov     esi,[biosBase]
          movzx   eax,byte[esi+19]
          test    al,1000b
          jz      @f
         cinvoke  wsprintf,strBuff,<'Yes',0>,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Uefi,strBuff

;/******* Parse MotherBOARD Table(2) *******************************
@@:       mov     esi,[boardBase]
          movzx   eax,byte[esi+1]
          add     esi,eax
          push    esi
          invoke  SetDlgItemText,[hwnddlg],ID_Board,esi
;// Product ------------------------------
          pop     esi
          mov     ecx,-1
          xchg    edi,esi
          xor     al,al
          repne   scasb
          push    edi
          invoke  SetDlgItemText,[hwnddlg],ID_Prod,edi
;// Version ------------------------------
          pop     edi
          mov     ecx,-1
          xor     al,al
          repne   scasb
          push    edi
          invoke  SetDlgItemText,[hwnddlg],ID_Mver,edi
;// Serial -------------------------------
          pop     edi
          mov     ecx,-1
          xor     al,al
          repne   scasb
          push    edi
          invoke  SetDlgItemText,[hwnddlg],ID_Sn,edi
;// Asset Tag ------------------------------
          pop     edi
          mov     ecx,-1
          xor     al,al
          repne   scasb
          invoke  SetDlgItemText,[hwnddlg],ID_Tag,edi

;//***************************  End of parse ***********************

;//------ OS Version in PEB structure ----------------
          mov     esi,[fs:0x30]
          mov     eax,[esi+0xA4]        ;// PEB.OS_Major
          mov     ebx,[esi+0xA8]        ;// PEB.OS_Minor
          movzx   ecx,word[esi+0xAC]    ;// PEB.OS_Build
          movzx   edx,byte[esi+0xAF]    ;// PEB.OS_ServicePack
         cinvoke  wsprintf,strBuff,<' OS version:  Windows %d.%d.%d-SP%d',0>,eax,ebx,ecx,edx
          invoke  SetDlgItemText,[hwnddlg],ID_Win,strBuff


;//************************************************************
;//****** "WM_TIMER" Handler **********************************
;//************************************************************
@RDTSC:
;// Real Time Stamp Counter --------------
          rdtsc
         cinvoke  wsprintf,strBuff,<'%08X-%08X',0>,edx,eax
          invoke  SetDlgItemText,[hwnddlg],ID_Tsc,strBuff
          invoke  SetTimer,[hwnddlg],0123,1000,0

;//************************************************************
;//****** "WM_CLOSE/COMMAND" Handler **************************
;//************************************************************
@exit:    cmp     [wparam],BN_CLICKED shl 16 + IDCANCEL
          jne     @next
@close:   invoke  EndDialog,[hwnddlg], 0
@next:    xor     eax,eax
@return:  ret
endp

;//------------------
section '.idata' import data readable writeable
library  kernel32,'kernel32.DLL', user32,'user32.DLL'
include  'api\kernel32.inc'
include  'api\user32.inc'

;//------------------
section '.rsrc' data resource readable
directory  RT_DIALOG, dialogs
resource   dialogs, 100, LANG_ENGLISH + SUBLANG_DEFAULT, mainform

dialog  mainform,'',200,050,380,255, DS_3DLOOK + WS_CAPTION + WS_SYSMENU,,,'Verdana',8

   dialogitem 'BUTTON',' CPU ',       -1,010,010,360,080,WS_VISIBLE + BS_GROUPBOX

   dialogitem 'STATIC','Name',        -1,012,025,042,013,WS_VISIBLE + SS_RIGHT
   dialogitem 'STATIC','',ID_Name,       060,025,300,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Socket',      -1,012,040,042,013,WS_VISIBLE + SS_RIGHT
   dialogitem 'STATIC','',ID_Sock,       060,040,060,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Cores',       -1,140,040,050,013,WS_VISIBLE
   dialogitem 'STATIC','',ID_Cores,      165,040,030,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Enabled',     -1,215,040,050,013,WS_VISIBLE
   dialogitem 'STATIC','',ID_Enable,     245,040,030,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Threads',     -1,300,040,050,013,WS_VISIBLE
   dialogitem 'STATIC','',ID_Threads,    330,040,030,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','ExtClock',    -1,012,055,042,013,WS_VISIBLE + SS_RIGHT
   dialogitem 'STATIC','',ID_Clock,      060,055,060,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Speed',       -1,138,055,050,013,WS_VISIBLE
   dialogitem 'STATIC','',ID_Speed,      165,055,070,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Max Speed',   -1,250,055,050,013,WS_VISIBLE
   dialogitem 'STATIC','',ID_Max,        291,055,070,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Voltage',     -1,012,070,042,013,WS_VISIBLE + SS_RIGHT
   dialogitem 'STATIC','',ID_Volt,       060,070,060,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Memory',      -1,132,070,050,013,WS_VISIBLE
   dialogitem 'STATIC','',ID_Mem,        165,070,070,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','TSC',         -1,250,070,050,013,WS_VISIBLE
   dialogitem 'STATIC','',ID_Tsc,        270,070,090,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

;//*******************************************************************************************

   dialogitem 'BUTTON',' BIOS ',      -1,010,100,360,050,WS_VISIBLE + BS_GROUPBOX

   dialogitem 'STATIC','Vendor',      -1,012,115,042,013,WS_VISIBLE + SS_RIGHT
   dialogitem 'STATIC','',ID_Bios,       060,115,300,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Date',        -1,012,130,042,013,WS_VISIBLE + SS_RIGHT
   dialogitem 'STATIC','',ID_Date,       060,130,060,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Ver',         -1,130,130,042,013,WS_VISIBLE
   dialogitem 'STATIC','',ID_Bver,       145,130,060,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','ROM size',    -1,215,130,050,013,WS_VISIBLE
   dialogitem 'STATIC','',ID_Rom,        250,130,050,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','UEFI',        -1,310,130,050,013,WS_VISIBLE
   dialogitem 'STATIC','No',ID_Uefi,     330,130,030,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

;//*******************************************************************************************

   dialogitem 'BUTTON',' BOARD ',     -1,010,162,360,048,WS_VISIBLE + BS_GROUPBOX

   dialogitem 'STATIC','Product',     -1,012,175,042,013,WS_VISIBLE + SS_RIGHT
   dialogitem 'STATIC','',ID_Board,      060,175,175,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN
   dialogitem 'STATIC','',ID_Prod,       245,175,115,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

   dialogitem 'STATIC','Version',     -1,012,190,042,013,WS_VISIBLE + SS_RIGHT
   dialogitem 'STATIC','',ID_Mver,       060,190,092,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN
   dialogitem 'STATIC','',ID_Sn,         163,190,092,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN
   dialogitem 'STATIC','',ID_Tag,        265,190,094,010,WS_VISIBLE + SS_CENTER + SS_SUNKEN

;//*******************************************************************************************

   dialogitem 'STATIC','',ID_Win,        010,230,200,010,WS_VISIBLE
   dialogitem 'BUTTON','Exit',IDCANCEL,  300,230,070,013,WS_VISIBLE + BS_DEFPUSHBUTTON
enddialog
    


Description:
Filesize: 13.07 KB
Viewed: 1786 Time(s)

Win10.png


Description:
Filesize: 13.96 KB
Viewed: 1786 Time(s)

win7.png


Description:
Download
Filename: CPU_SMB.ZIP
Filesize: 2.2 KB
Downloaded: 86 Time(s)



Last edited by Core i7 on 01 Jun 2025, 23:28; edited 2 times in total
Post 01 Jun 2025, 12:42
View user's profile Send private message Reply with quote
Core i7



Joined: 14 Nov 2024
Posts: 84
Location: Socket on motherboard
Core i7 01 Jun 2025, 12:52
another screenshot from a laptop win10


Description:
Filesize: 17.15 KB
Viewed: 1780 Time(s)

Win10_.png


Post 01 Jun 2025, 12:52
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8427
Location: Kraków, Poland
Tomasz Grysztar 01 Jun 2025, 14:03
On my ARM machine it fails to set up the [boardBase] and has an exception because of that. On AMD machine works correctly.
Post 01 Jun 2025, 14:03
View user's profile Send private message Visit poster's website Reply with quote
flier mate



Joined: 24 May 2025
Posts: 29
flier mate 01 Jun 2025, 14:10
Another screenshot...

Now I understand, GetDlgItem + SetWindowText = SetDlgItemText.

I think you can change some of the STATIC to read-only EDIT (e.g. motherboard's SN) so that user can copy and paste. (EDIT: Or save report as .TXT)

Nice to have code. (You didn't state you as the author name, what a modesty)


Description: On my machine
Filesize: 17.93 KB
Viewed: 1762 Time(s)

i7.PNG




Last edited by flier mate on 01 Jun 2025, 16:32; edited 1 time in total
Post 01 Jun 2025, 14:10
View user's profile Send private message Reply with quote
flier mate



Joined: 24 May 2025
Posts: 29
flier mate 01 Jun 2025, 14:38
I also learned new instruction BSWAP from your code. Appreciate it very much!
Post 01 Jun 2025, 14:38
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4249
Location: vpcmpistri
bitRAKE 01 Jun 2025, 14:39
Windows 11 System:
0x02, Socket FL1, µFC-BGAFL1, BGA1763


Description:
Filesize: 23.66 KB
Viewed: 1751 Time(s)

Screenshot 2025-06-01 075520.png



_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 01 Jun 2025, 14:39
View user's profile Send private message Visit poster's website Reply with quote
Core i7



Joined: 14 Nov 2024
Posts: 84
Location: Socket on motherboard
Core i7 01 Jun 2025, 17:47
Thank you very much for the errors found - fixed.

1. Added all 87 sockets from the specification, and sent their table to the external include.
2. bitRAKE - socket type (0x02) is specified as Unknown, so let's wait for a new specification.
3. flier mate - since there is a source, this is easy to do: style "WS_BORDER + ES_CENTER + ES_READONLY"
4. Tomasz Grysztar - added a check for found tables, and if not, then printing is skipped. To do this, I simply check the "baseXX" variables for zero values ​​by default. I also inserted a limiter on the last table (127) - this should work.


Description: smbios.asm/exe & socket.inc
Download
Filename: SMBIOS.ZIP
Filesize: 6.89 KB
Downloaded: 86 Time(s)

Post 01 Jun 2025, 17:47
View user's profile Send private message Reply with quote
Core i7



Joined: 14 Nov 2024
Posts: 84
Location: Socket on motherboard
Core i7 02 Jun 2025, 11:55
In the latest version, I added a block with information about the graphics adapter - its name, GPU core type, vendor codes, and memory size. For this, I use functions and COM methods from the gdi32, setupapi, dxgi.dll libraries. The archive includes "dxgi.inc" + source code with the application. I was unable to test adapters with VRAM greater than 4GB, so the result is questionable.


Description:
Filesize: 16.3 KB
Viewed: 1610 Time(s)

smb2.png


Description:
Download
Filename: SMBIOS.ZIP
Filesize: 14.05 KB
Downloaded: 88 Time(s)

Post 02 Jun 2025, 11:55
View user's profile Send private message Reply with quote
Core i7



Joined: 14 Nov 2024
Posts: 84
Location: Socket on motherboard
Core i7 03 Jun 2025, 14:17
For those who want to understand the structure of the smbios database in detail, I recommend paying attention to the "RW" utility. The menu has an item that will display full information about the database - binary dumps + decoded fields. Developer's website: https://rweverything.com/download/


Description:
Filesize: 31.04 KB
Viewed: 1450 Time(s)

rw.png


Post 03 Jun 2025, 14:17
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1952
Roman 04 Jun 2025, 09:04
Microsoft write bad solutions.
And for this reason we must write utility.
Its the shame!

Microsoft makes life more difficult for a programmers.
Post 04 Jun 2025, 09:04
View user's profile Send private message Reply with quote
Core i7



Joined: 14 Nov 2024
Posts: 84
Location: Socket on motherboard
Core i7 04 Jun 2025, 11:32
Roman wrote:
Microsoft write bad solutions.

The SMBIOS is created by programmers at the motherboard factory and saved in ROM-BIOS. The database can be found in the real CPU mode by the signature "_SM_" in the (f) segment. And in protected mode, Windows provides only an API for reading raw data. It is possible to read some smbios fields from the system registry, but access to it is restricted with user rights, while the GetSystemFirmwareTable() api is available to everyone.
Code:
;// Search smbios in real mode
     push   es 0xf000
     pop    es
     xor    di,di                ; ES:DI = 000F:0000 
@@:  cmp    dword[es:di],'_SM_'  ; find signature
     je     @f
     add    di,16                ; next paragraph
     cmp    di,0xffff            ; end of the segment?
     jnz    @b
     pop    es
     jmp    @SmBiosNotFound

@@:  pop    es
;    ....    
Post 04 Jun 2025, 11:32
View user's profile Send private message Reply with quote
Core i7



Joined: 14 Nov 2024
Posts: 84
Location: Socket on motherboard
Core i7 06 Jun 2025, 16:50
At first I thought to show only the SMBIOS database in the window, but since these are physical devices, then + video adapter, and now for a complete picture let there be collection of information about ATA/SATA/NVMe drives.

The main bet is on the request of the ATA command "IDENTIFY_DEVICE = 0xEC", which returns 1 sector of service data (512 bytes). The problem is that for HDD disks (ata/sata) one implementation of the request is required, and for SSD another. Win32API supports working with SSD starting from Win10, but since I need cross-platform Win7-10 x32/64, for SSD I skip the "IDENTIFY" command and request only basic information. Here is the algorithm:

1. To select disks in the utility window, use the "ComboBox" (arrows on the keyboard, or a drop-down list with the mouse).
2. Starting with "\\.\PhysicalDrive0" and then 1,2,..N I try to open disks in a cycle - if ok, then the number is immediately saved in the "ComboBox".
3. This process occurs in the "WM_INIT" handler:
Code:
.data 
;----------------------------------
dName       db  '\\.\PhysicalDrive'
drive       db  '0',0
hddCount    du  '0123456789'         ; total 10 any storage
;.......

.code 
;----------------------------------
proc  DialogProc hwnddlg, msg, wparam, lparam

;.......
          mov     edi,hddCount
@findMassStorage:
          push    edi edi edi
          invoke  CreateFile,dName,GENERIC_READ + GENERIC_WRITE,\
                                   FILE_SHARE_READ,0,OPEN_EXISTING,0,0
          cmp     eax,-1
          jz      @endFindDisk
          invoke  CloseHandle,eax

          pop     edi
          invoke  SendDlgItemMessage,[hwnddlg], ID_Hdd, CB_ADDSTRING,0,edi        ; ID_Hdd = ComboBox  
          pop     edi
          invoke  SendDlgItemMessage,[hwnddlg], ID_Hdd, CB_SETITEMDATA, eax,edi
          pop     edi
          add     di,2
          inc     byte[drive]
          jmp     @findMassStorage

@endFindDisk:
          add     esp,12
          mov     byte[drive],'0'     ; default
    

4. When selecting a line from the "ComboBox", the control sends a "CBN_SELENDOK" notification to the window via the "WM_COMMAND" message:
Code:
;//************************************************************
;//****** "WM_CLOSE/COMMAND" Handler **************************
;//************************************************************
@exit:    cmp     [wparam],BN_CLICKED shl 16 + IDCANCEL    
          jne     @f
@close:   invoke  EndDialog,[hwnddlg], 0

@@:       cmp     [wparam],CBN_SELENDOK shl 16 + ID_Hdd    ;<---- check combo
          jne     @next
          invoke  SendDlgItemMessage,[hwnddlg],ID_Hdd, CB_GETCURSEL, 0,0       ; string index
          invoke  SendDlgItemMessage,[hwnddlg],ID_Hdd, CB_GETITEMDATA, eax,0   ; string value offset
          mov     al,byte[eax]
          mov     [drive],al            ; change number in "\\.\PhysicalDrive_xx" string
          call    GetIdentifyDevice     ; dump Id sector

@next:    xor     eax,eax
@return:  ret
endp
    

5. The "GetIdentifyDevice" procedure fills in the fields in the utility window. It opens the specified disk and tries to send it the "IOCTL_SMART_RCV_DRIVE_DATA" command via DeviceIoControl(). If there is an error, it means that this is an SSD disk and printing of information is skipped:
Code:
proc GetIdentifyDevice
          invoke  CreateFile,dName,GENERIC_READ or GENERIC_WRITE,\
                                   FILE_SHARE_READ,0,OPEN_EXISTING,0,0
          mov     [hDisk],eax

          mov     [inBuff.irDriveRegs.CommandReg],IDENTIFY_DEVICE       ; ATA-command 0хЕС
          invoke  DeviceIoControl,eax,IOCTL_SMART_RCV_DRIVE_DATA,\
                                      inBuff,sizeof.SENDCMDINPARAMS,\
                                      outBuff,sizeof.SENDCMDOUTPARAMS,retSize,0
          or      eax,eax
          jz      @smartError     ; found SSD..
;............
    

6. The sector (ID) contains 256 words: disk name, serial number, firmware, size, etc. However, more interesting information is stored in the 4K SMART page, such as the power-on counter, lifetime in hours, the number of reassigned (bad) sectors "Remap", and the current temperature. Reading SMART is not a problem - it is simply a request for the ATA command "SMART_READ_DATA = 0xD0". There are 128 identifiers in total, and each record is 12 bytes in size (see the documentation in the archive). The SMART page is always located at a fixed LBA = 0xC24F00 and is not accessible via the usual ReadFile():
Code:
;-------  Read SMART attributes  -----------------

          mov     [inBuff.irDriveRegs.LBA_Middle], SMART_LBA_MIDDLE_REG    ; 0x4F
          mov     [inBuff.irDriveRegs.LBA_High],   SMART_LBA_HIGH_REG      ; 0xC2
          mov     [inBuff.irDriveRegs.CommandReg], SMART_EXECUTE_CMD       ; 0xB0 (basic cmd)
          mov     [inBuff.irDriveRegs.FeaturesReg],SMART_READ_DATA         ;      (  ext cmd)

          invoke  DeviceIoControl,[hDisk], IOCTL_SMART_RCV_DRIVE_DATA,\
                                           inBuff,sizeof.SENDCMDINPARAMS,\
                                           smartBuff,512+18,retSize,0
;............
    

7. If the disk is SSD, then at the "@smartError" label we try to get at least some information about the drive. To do this, you can send the "IOCTL_STORAGE_QUERY_PROPERTY" request, which returns data to the "STORAGE_DEVICE_DESCRIPTOR" structure (name, serial, firmware, transport, etc.). But this structure does not have the total number of sectors, so the disk size will have to be requested separately via "IOCTL_DISK_GET_DRIVE_GEOMETRY":
Code:
struct STORAGE_DEVICE_DESCRIPTOR
   Version                dd  sizeof.STORAGE_DEVICE_DESCRIPTOR
   Size                   dd  0
   DeviceType             db  0
   DeviceTypeModifier     db  0
   RemovableMedia         db  0
   CommandQueueing        db  0
   VendorIdOffset         dd  0
   ProductIdOffset        dd  0
   ProductRevisionOffset  dd  0 
   SerialNumberOffset     dd  0 
   BusType                dd  0    ;<---------//
   RawPropertiesLength    dd  0
   RawDeviceProperties    rb  512
ends

;------  NVMe & any disk controller  -----------------------
@smartError:
          mov     [qInBuff.PropertyId],StorageDeviceProperty
          mov     [qInBuff.QueryType],PropertyStandardQuery
          mov     [qInBuff.AdditionalParameters],0

          invoke  DeviceIoControl,[hDisk],IOCTL_STORAGE_QUERY_PROPERTY,\
                                          qInBuff, sizeof.STORAGE_PROPERTY_QUERY,\
                                          qOutBuff,sizeof.STORAGE_DEVICE_DESCRIPTOR,\
                                          retSize,0

          mov     eax,[qOutBuff.ProductIdOffset]
          or      eax,eax
          je      @f
          add     eax,qOutBuff
          invoke  SetDlgItemText,[hDialog],ID_Hname,eax
;.......
    

8. That's all from the main one, and in the addition at the bottom near the Windows version I also displayed the operating time of the OS from the moment of power-on. It can be obtained via GetTickCount(), or QueryUnbiasedInterruptTime().

9. With each line of code there is more and more, so for convenience I divided it into includes - it's easier to make corrections later. This is what I got in the end. I would be grateful for tests and errors found. The archive contains the source code, the finished application, and a document describing SMART SSD.

ATA Command Set: https://people.freebsd.org/~imp/asiabsdcon2015/works/d2161r5-ATAATAPI_Command_Set_-_3.pdf


Description:
Filesize: 11.81 KB
Viewed: 968 Time(s)

Storage.png


Description:
Download
Filename: SMBIOS_v12.zip
Filesize: 223.94 KB
Downloaded: 60 Time(s)

Post 06 Jun 2025, 16:50
View user's profile Send private message Reply with quote
Core i7



Joined: 14 Nov 2024
Posts: 84
Location: Socket on motherboard
Core i7 12 Jun 2025, 12:37
Today I found a document from Intel "Microcode Update Guidance", and based on it I added 2 more fields to the utility - this is the CPUID code, and the processor "architecture code name" tied to it. This is an incomplete list only for Intel products, so I ask AMD owners to show their ID field value, as well as the code name from the CPU-Z program, so that I can add them to my database. Currently there are only 30 entries in the database and I search it like this. I put asm + exe in the archive:
Code:
;// CPU Code Name ------------------------
          mov     esi,[cpuBase]
          mov     ebx,dword[esi+08]   ; CPU Family\Model\Stepping
          shr     ebx,4               ; delete Stepping
          mov     esi,CpuidTable
          mov     ecx,tableLen
@@:       lodsd                       ; find..
          cmp     ebx,eax
          je      @foundCodeName
          add     esi,4
          loop    @b
          mov     esi,unk             ; not found
          jmp     @NotFoundCodeName
@foundCodeName:
          mov     esi,[esi]
@NotFoundCodeName:
          invoke  SetDlgItemText,[hwnddlg],ID_CName,esi
          jmp     @EofCodeName

align 8
CpuidTable   dd   0x006d,dohan, 0x006e,yonah, 0x006f,conroe,0x00f2,netburst
             dd   0x1067,wolf,  0x106a,bloom, 0x106e,lynn,  0x206c,gulf
             dd   0x2065,arra,  0x206e,neh,   0x206f,west,  0x3067,silver
             dd   0x206a,sandy, 0x206d,sandy, 0x306a,ivy,   0x306e,ivy
             dd   0x306c,hass,  0x306f,hass,  0x4065,hass,  0x4066,hass
             dd   0x306d,broad, 0x4067,broad, 0x406f,broad, 0x5066,broad
             dd   0x406e,sky,   0x5065,sky,   0x506e,sky,   0x00f4,pres
             dd   0x506c,apollo,0x806e,kaby,  0x906e,coffe, 0x706a,gemini
             dd   0x406a,merri, 0x406c,charry,0x406d,avoton,0x5067,phi
             dd   0x506c,brox,  0x506a,moor,  0x506f,denver,0x606e,cougar
tableLen     =    ($ - CpuidTable)/8

dohan      db   'Dothan',0
yonah      db   'Yonah',0
conroe     db   'Conroe',0
netburst   db   'Netburst',0
pres       db   'Prescott',0
wolf       db   'Wolfdale',0
bloom      db   'Bloomfield',0
lynn       db   'Lynnfield',0
gulf       db   'Gulftown',0
arra       db   'Arrandale',0
neh        db   'Nehalem',0
west       db   'Westmere',0
silver     db   'Silvermont',0
sandy      db   'Sandy Bridge',0
ivy        db   'Ivy Bridge',0
hass       db   'Haswell',0
broad      db   'Broadwell',0
sky        db   'Sky Lake',0
apollo     db   'Apollo Lake',0
kaby       db   'Kaby Lake',0
coffe      db   'Coffee Lake',0
gemini     db   'Gemini Lake',0
merri      db   'Merrifield',0
charry     db   'Cherry View',0
avoton     db   'Avoton',0
phi        db   'Phi Knights',0
brox       db   'Broxton',0
moor       db   'Moorefield',0
denver     db   'Denverton',0
cougar     db   'Cougar Mountain',0

;----------------------------------

@EofCodeName:
    


Description:
Filesize: 8.58 KB
Viewed: 262 Time(s)

smb13.png


Description:
Download
Filename: SMBIOS_v1.3.ZIP
Filesize: 16.41 KB
Downloaded: 24 Time(s)

Post 12 Jun 2025, 12:37
View user's profile Send private message Reply with quote
Mat Qua sar



Joined: 13 Jun 2025
Posts: 4
Mat Qua sar 13 Jun 2025, 16:29
Your project is getting bigger! Many API functions I never use before.

I run your SMBIOS_v12.EXE, the BIOS and STORAGE infos were missing.
(If you refer to my "flier mate" previous screenshot, BIOS info was there)

I am sure my BIOS is not UEFI.

Also, where to locate 'equates\dxgi.inc'? I couldn't compile the source code.

Please refer to CPU-Z screenshot for CPU code name.

Nice effort, by the way.


Description:
Filesize: 27.63 KB
Viewed: 58 Time(s)

Capture.PNG


Description:
Filesize: 24.79 KB
Viewed: 58 Time(s)

Untitled.png


Post 13 Jun 2025, 16:29
View user's profile Send private message Reply with quote
Mat Qua sar



Joined: 13 Jun 2025
Posts: 4
Mat Qua sar 13 Jun 2025, 16:34
Also, after I changed my system time to one day earlier, the "Works: 2 days, 21 hours, 39 min" seems incorrect.

EDIT: After reboot, the "2 days" doesn't go away, now is "2 days, 23 hours...". Is it something wrong with my laptop's system time?

From Event Viewer:
Quote:
Log Name: System
Source: Microsoft-Windows-Kernel-General
Date: 13/6/2025 12:43:31 PM
Event ID: 1
Task Category: (5)
Level: Information
Keywords: Time
User: LOCAL SERVICE
Computer: DESKTOP-RNCNAG9
Description:
The system time has changed to ‎2025‎-‎06‎-‎13T04:43:31.671499100Z from ‎2025‎-‎06‎-‎14T21:45:36.745004600Z.

Change Reason: An application or system component changed the time.
Process: '\Device\HarddiskVolume2\Windows\System32\svchost.exe' (PID 7988).
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Kernel-General" Guid="{a68ca8b7-004f-d7b6-a698-07e2de0f1f5d}" />
<EventID>1</EventID>
<Version>2</Version>
<Level>4</Level>
<Task>5</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000010</Keywords>
<TimeCreated SystemTime="2025-06-13T04:43:31.6720405Z" />
<EventRecordID>26648</EventRecordID>
<Correlation />
<Execution ProcessID="7988" ThreadID="2284" />
<Channel>System</Channel>
<Computer>DESKTOP-RNCNAG9</Computer>
<Security UserID="S-1-5-19" />
</System>
<EventData>
<Data Name="NewTime">2025-06-13T04:43:31.6714991Z</Data>
<Data Name="OldTime">2025-06-14T21:45:36.7450046Z</Data>
<Data Name="Reason">1</Data>
<Data Name="ProcessName">\Device\HarddiskVolume2\Windows\System32\svchost.exe</Data>
<Data Name="ProcessID">7988</Data>
</EventData>
</Event>


Description:
Filesize: 2.67 KB
Viewed: 8 Time(s)

Capture.PNG




Last edited by Mat Qua sar on 13 Jun 2025, 18:39; edited 1 time in total
Post 13 Jun 2025, 16:34
View user's profile Send private message Reply with quote
Mat Qua sar



Joined: 13 Jun 2025
Posts: 4
Mat Qua sar 13 Jun 2025, 18:31
Core i7 wrote:

Code:
@@:       lodsd                       ; find..
          cmp     ebx,eax
          je      @foundCodeName
          add     esi,4
          loop    @b
    


From my static analysis, the "lodsd" increment the ESI automatically by 4 bytes to compare the CPU ID, but you need to increment it manually for another 4 bytes to skip the offset to CPU Code Name, since each entry in the table is 8 bytes.
Post 13 Jun 2025, 18:31
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.