скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Прочитать ROM-BIOS



Оформил: DeeCo

// An Example of this unit is availabe as Demo Download. 
// Ein Beispiel zur Anwendung dieser Unit kann als Demo heruntergeladen werden. 


//////////////////////////////////////////////////////////////////////////////// 
// 
//                            BIOS Helper for Delphi 
// 
//               BIOS related utilities for Win9x and WinNT(i386) 
// 
//////////////////////////////////////////////////////////////////////////////// 
// 
//  The Original Code is: 
//   BiosHelp.pas, released 2001-09-02. 
// 
//  The Initial Developer of the Original Code is Nico Bendlin. 
// 
//  Portions created by Nico Bendlin are 
//   Copyright (C) 2001-2003 Nico Bendlin. All Rights Reserved. 
// 
//  Contributor(s): 
//   Nico Bendlin<nicode@gmx.net> 
// 
//  The contents of this file are subject to the Mozilla Public License Version 
//  1.1 (the "License"); you may not use this file except in compliance with the 
//  License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
// 
//  Software distributed under the License is distributed on an "AS IS" basis, 
//  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 
//  the specific language governing rights and limitations under the License. 
// 
//  Alternatively, the contents of this file may be used under the terms of 
//  either the GNU General Public License Version 2 or later (the "GPL"), or 
//  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 
//  in which case the provisions of the GPL or the LGPL are applicable instead 
//  of those above. If you wish to allow use of your version of this file only 
//  under the terms of either the GPL or the LGPL, and not to allow others to 
//  use your version of this file under the terms of the MPL, indicate your 
//  decision by deleting the provisions above and replace them with the notice 
//  and other provisions required by the GPL or the LGPL. If you do not delete 
//  the provisions above, a recipient may use your version of this file under 
//  the terms of any one of the MPL, the GPL or the LGPL. 
// 
//////////////////////////////////////////////////////////////////////////////// 
// 
//  Revision: 
// 
//    2003-02-15  2.00 [NicoDE] 
//                     - generic dump method completely rewritten 
//                     - default range is now E000:0000-F000:FFFF 
// 
//////////////////////////////////////////////////////////////////////////////// 

{$IFDEF CONDITIONALEXPRESSIONS}
   {$DEFINE DELPHI6UP}
   {$IF NOT DEFINED(VER140)}
     {$DEFINE DELPHI7UP}
   {$IFEND}
 {$ENDIF}

 unit BiosHelp {$IFDEF DELPHI6UP} platform {$ENDIF};

 {$MINENUMSIZE 4}
 {$WEAKPACKAGEUNIT}
 {$IFDEF DELPHI7UP}
   {$WARN UNSAFE_TYPE OFF}
   {$WARN UNSAFE_CODE OFF}
 {$ENDIF}

 interface

 uses
   Windows;

 const
   RomBiosDumpBase = $000E0000;
   RomBiosDumpEnd  = $000FFFFF;
   RomBiosDumpSize = RomBiosDumpEnd - RomBiosDumpBase + 1;

 type
   PRomBiosDump = ^TRomBiosDump;
   TRomBiosDump = array [RomBiosDumpBase..RomBiosDumpEnd] of Byte;

 type
   TRomDumpMethod = (rdmAutomatic,  // Autodetect OS type and use proper method 
    rdmGeneric,    // Use 16-bit EXE program to dump the BIOS 
    rdmMemory,     // Dump from process's address space (Win9x) 
    rdmPhysical    // Dump from physical memory object (WinNT) 
    );

 function DumpRomBios(out Dump: TRomBiosDump;
   Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean;
 function DumpRomBiosEx(RomBase: Pointer; RomSize: Cardinal; out Dump;
   Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean;

 procedure ReadRomDumpBuffer(const Dump: TRomBiosDump; Addr: Pointer;
   var Buffer; Size: Cardinal);
 procedure ReadRomDumpBufferEx(const Dump; Base, Addr: Pointer;
   var Buffer; Size: Cardinal);

 function GetRomDumpAddr(const Dump: TRomBiosDump; Addr: Pointer): Pointer;
 function GetRomDumpAddrEx(const Dump; Base, Addr: Pointer): Pointer;

 implementation

 //////////////////////////////////////////////////////////////////////////////// 
// 
//  DumpRomBios16 (rdmGeneric) 
// 
//    Creates an 16-bit EXE program in TEMP and runs it redirected to an file. 
// 
//    WARNING: One day 16-bit code will not run on future Windows. 
//    WARNING: You are dumping the BIOS inside the MS-DOS 'emulator'. 
// 

function _RomDumpCode(RomBase: Pointer; RomSize: Cardinal;
   out Code: Pointer; out Size: Cardinal): Boolean;
 const
   BlockSize = $1000;
 type                                     // ; RomDump (dumps mem to STDOUT) 
  PRomDumpCode = ^TRomDumpCode;          // ; BlockSize MUST be multiple of 10h. 
  TRomDumpCode = packed record           // 
    _header: TImageDosHeader;            // 
    _notice: array[0..$4F] of AnsiChar;  // @@note: db      'RomDump 2.0', ... 
    init: packed record                  // @@init: 
      _mov_44: array[0..2] of Byte;      //         mov     ax, 4400h 
      _mov_bx: array[0..2] of Byte;      //         mov     bx, 0001h 
      _dos_21: array[0..1] of Byte;      //         int     21h 
      _jcf_18: array[0..1] of Byte;      //         jc      @@code 
      _and_dx: array[0..3] of Byte;      //         and     dx, 0082h 
      _cmp_dx: array[0..3] of Byte;      //         cmp     dx, 0082h 
      _jne_0E: array[0..1] of Byte;      //         jne     @@code 
      _psh_cs: Byte;                     //         push    cs 
      _pop_ds: Byte;                     //         push    ds 
      _mov_dx: array[0..2] of Byte;      //         mov     dx, offset @@note 
      _mov_09: array[0..1] of Byte;      //         mov     ah, 09h 
      _int_21: array[0..1] of Byte;      //         int     21h 
      _mov_4C: array[0..2] of Byte;      //         mov     ax, 4C01h 
      _int_20: array[0..1] of Byte;      //         int     21h 
    end;                                 // 
    code: packed record                  // @@code: 
      _mov_cx: Byte;
        BlockCount: Word;   //         mov     cx, <BlockCount> 
      _mov_dx: Byte;
        DatSegment: Word;   //         mov     dx, <DatSegment> 
      _jcx_1C: array[0..1] of Byte;      //         jcxz    @@rest 
    end;                                 // 
    loop: packed record                  // @@loop: 
      _psh_cx: Byte;                     //         push    cx 
      _psh_dx: Byte;                     //         push    dx 
      _mov_ds: array[0..1] of Byte;      //         mov     ds, dx 
      _mov_dx: Byte;
        DatOffset: Word;    //         mov     dx, <DatOffset> 
      _mov_cx: array[0..2] of Byte;      //         mov     cx, <BlockSize> 
      _mov_bx: array[0..2] of Byte;      //         mov     bx, 0001h 
      _mov_ax: array[0..2] of Byte;      //         mov     ax, 4000h 
      _int_21: array[0..1] of Byte;      //         int     21h 
      _pop_dx: Byte;                     //         pop     dx 
      _pop_cx: Byte;                     //         pop     cx 
      _jcf_1C: array[0..1] of Byte;      //         jc      @@exit 
      _add_dx: array[0..3] of Byte;      //         add     dx, <BlockSize/10h> 
      _lop_E4: array[0..1] of Byte;      //         loop    @@loop 
    end;                                 // 
    rest: packed record                  // @@rest: 
      _mov_ds: array[0..1] of Byte;      //         mov     ds, dx 
      _mov_dx: Byte;
        DatOffset: Word;    //         mov     dx, <DatOffset> 
      _mov_cx: Byte;
        LenghtMod: Word;    //         mov     cx, <LenghtMod> 
      _mov_bx: array[0..2] of Byte;      //         mov     bx, 0001h 
      _mov_ax: array[0..2] of Byte;      //         mov     ax, 4000h 
      _jcx_06: array[0..1] of Byte;      //         jcxz    @@exit 
      _int_21: array[0..1] of Byte;      //         int     21h 
      _jcf_02: array[0..1] of Byte;      //         jc      @@exit 
      _mov_al: array[0..1] of Byte;      //         mov     al, 00h 
    end;                                 // 
    Exit: packed record                  // @@exit: 
      _mov_ah: array[0..1] of Byte;      //         mov     ah, 4Ch 
      _int_21: array[0..1] of Byte;      //         int     21h 
    end;                                 // 
  end;
 const
   RomDumpCodeSize = SizeOf(TRomDumpCode) - SizeOf(TImageDosHeader);
   RomDumpCode: TRomDumpCode = (_header: (e_magic: IMAGE_DOS_SIGNATURE;
     e_cblp: Word(RomDumpCodeSize) and $1FF;
     e_cp: Word((RomDumpCodeSize - 1) shr 9) + 1;
     e_crlc: $0000;
     e_cparhdr: SizeOf(TImageDosHeader) shr 4;
     e_minalloc: $0000;
     e_maxalloc: $FFFF;
     e_ss: $0000;
     e_sp: $1000;
     e_csum: $0000;
     e_ip: SizeOf(RomDumpCode._notice);
     e_cs: $0000;
     e_lfarlc: SizeOf(TImageDosHeader);
     e_ovno: $0000;
     e_res: ($0000, $0000, $0000, $0000);
     e_oemid: $0000;
     e_oeminfo: $0000;
     e_res2: ($0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000,
     $0000, $0000);
     _lfanew: $00000000
     );
     _notice: #13#10+
    'RomDump 2.0'#13#10 +
     'Copyright (c) 2003 Nico Bendlin'#13#10 +
     #13#10+
    'Usage: RomDump > filename'#13#10 +
     #13#10$';
     init: (_mov_44: ($B8, $00, $44);
     _mov_bx: ($BB, $01, $00);
     _dos_21: ($CD, $21);
     _jcf_18: ($72, $18);
     _and_dx: ($81, $E2, $82, $00);
     _cmp_dx: ($81, $FA, $82, $00);
     _jne_0E: ($75, $0E);
     _psh_cs: $0E;
     _pop_ds: $1F;
     _mov_dx: ($BA, $00, $00);
     _mov_09: ($B4, $09);
     _int_21: ($CD, $21);
     _mov_4C: ($B8, $01, $4C);
     _int_20: ($CD, $21);
     );
     code: (_mov_cx: $B9; BlockCount: $0010;
     _mov_dx: $BA; DatSegment: $F000;
     _jcx_1C: ($E3, $1C)
     );
     loop: (_psh_cx: $51;
     _psh_dx: $52;
     _mov_ds: ($8E, $DA);
     _mov_dx: $BA; DatOffset: $0000;
     _mov_cx: ($B9, Lo(BlockSize), Hi(BlockSize));
     _mov_bx: ($BB, $01, $00);
     _mov_ax: ($B8, $00, $40);
     _int_21: ($CD, $21);
     _pop_dx: $5A;
     _pop_cx: $59;
     _jcf_1C: ($72, $1C);
     _add_dx: ($81, $C2, Lo(BlockSize shr 4), Hi(BlockSize shr 4));
     _lop_E4: ($E2, $E4)
     );
     rest: (_mov_ds: ($8E, $DA);
     _mov_dx: $BA; DatOffset: $0000;
     _mov_cx: $B9; LenghtMod: $0000;
     _mov_bx: ($BB, $01, $00);
     _mov_ax: ($B8, $00, $40);
     _jcx_06: ($E3, $06);
     _int_21: ($CD, $21);
     _jcf_02: ($72, $02);
     _mov_al: ($B0, $00)
     );
     Exit: (_mov_ah: ($B4, $4C);
     _int_21: ($CD, $21)
     )
     );
 begin
   Result := False;
   if (RomSize > 0) and (RomSize <= $100000) and
     (Cardinal(RomBase) < $100000) and
     (Cardinal(RomBase) + RomSize <= $100000) then
   begin
     Size := SizeOf(TRomDumpCode);
     Code := Pointer(LocalAlloc(LPTR, Size));
     if Code <> nil then
       try
         PRomDumpCode(Code)^ := RomDumpCode;
         with PRomDumpCode(Code)^ do
         begin
           code.BlockCount := Word(RomSize div BlockSize);
           code.DatSegment := Word(Cardinal(RomBase) shr 4);
           loop.DatOffset  := Word(Cardinal(RomBase)) and $000F;
           rest.DatOffset  := loop.DatOffset;
           rest.LenghtMod  := Word(RomSize mod BlockSize);
         end;
         Result := True;
       except
         LocalFree(HLOCAL(Code));
         Code := nil;
         Size := 0;
       end;
   end;
 end;

 function _SaveRomDumpCodeToFile(RomBase: Pointer; RomSize: Cardinal;
   const FileName: string): Boolean;
 var
   Code: Pointer;
   Size: Cardinal;
   Hand: THandle;
   Num: DWORD;
 begin
   Result := False;
   if _RomDumpCode(RomBase, RomSize, Code, Size) then
     try
       Hand := CreateFile(PChar(FileName), GENERIC_WRITE, FILE_SHARE_READ, nil,
         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
       if Hand <> INVALID_HANDLE_VALUE then
         try
           Result := WriteFile(Hand, Code^, Size, Num, nil) and (Num = Size);
           if not Result then
             DeleteFile(PChar(FileName));
         finally
           CloseHandle(Hand);
         end;
     finally
       LocalFree(HLOCAL(Code));
     end;
 end;

 function _ExecuteRomDumpCode(const Code, Dump: string; Timeout: DWORD): Boolean;
 var
   ComSpec: string;
   StartInfo: TStartupInfo;
   ProcInfo: TProcessInformation;
   ErrorMode: Cardinal;
 begin
   Result := False;
   SetLength(ComSpec, MAX_PATH + 1);
   SetLength(ComSpec,
     GetEnvironmentVariable('ComSpec', PChar(@ComSpec[1]), MAX_PATH));
   if Length(ComSpec) <= 0 then
     Exit;
   FillChar(StartInfo, SizeOf(TStartupInfo), 0);
   StartInfo.cb := SizeOf(TStartupInfo);
   StartInfo.dwFlags := STARTF_USESHOWWINDOW;
   StartInfo.wShowWindow := SW_HIDE;
   ErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS or SEM_NOGPFAULTERRORBOX or
     SEM_NOALIGNMENTFAULTEXCEPT or SEM_NOOPENFILEERRORBOX);
   try
     if CreateProcess(nil, PChar(ComSpec + ' /C ' + Code + ' > ' + Dump),
       nil, nil, False, HIGH_PRIORITY_CLASS, nil, nil, StartInfo, ProcInfo) then
       try
         Result :=
           (WaitForSingleObject(ProcInfo.hProcess, Timeout) <> WAIT_TIMEOUT);
         if not Result then
           TerminateProcess(ProcInfo.hProcess, STATUS_TIMEOUT);
       finally
         CloseHandle(ProcInfo.hThread);
         CloseHandle(ProcInfo.hProcess);
       end;
   finally
     SetErrorMode(ErrorMode);
   end;
 end;

 function DumpRomBios16(RomBase: Pointer; RomSize: Cardinal; var Dump;
   Timeout: DWORD): Boolean;
 var
   Tmp: array [0..MAX_PATH] of Char;
   Dmp: array [0..MAX_PATH] of Char;
   Exe: array [0..MAX_PATH] of Char;
   Hnd: THandle;
   Num: DWORD;
 begin
   Result := False;
   if GetTempPath(MAX_PATH, Tmp) > 0 then
     GetShortPathName(Tmp, Tmp, MAX_PATH)
   else
     lstrcpy(Tmp, '.');
   if GetTempFileName(Tmp, 'rom', 0, Dmp) > 0 then
     try
       lstrcpy(Exe, Dmp);
       lstrcat(Exe, '.exe');  // Win9x requires .EXE extention 
      if _SaveRomDumpCodeToFile(RomBase, RomSize, Exe) then
         try
           if _ExecuteRomDumpCode(Exe, Dmp, Timeout) then
           begin
             Hnd := CreateFile(Dmp, GENERIC_READ, FILE_SHARE_READ or
               FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
             if Hnd <> INVALID_HANDLE_VALUE then
               try
                 Result := ReadFile(Hnd, Dump, RomSize, Num, nil) and (Num = RomSize);
               finally
                 CloseHandle(Hnd);
               end;
           end;
         finally
           DeleteFile(Exe);
         end;
     finally
       DeleteFile(Dmp);
     end;
 end;

 //////////////////////////////////////////////////////////////////////////////// 
// 
//  DumpRomBios9x (rdmMemory) 
// 
//    Win9x maps the BIOS into every process - therefore it's directly accessed. 
// 

function DumpRomBios9x(RomBase: Pointer; RomSize: Cardinal; var Dump): Boolean;
 begin
   Result := False;
   try
     Move(RomBase^, Dump, RomSize);
     Result := True;
   except
     // ignore exeptions 
  end
 end;

 //////////////////////////////////////////////////////////////////////////////// 
// 
//  DumpRomBiosNt (rdmPhysical) 
// 
//    On WinNT the BIOS is accessable through section '\Device\PhysicalMemory'. 
//    This object can only be opened by members of local 'Adminstrators' group. 
//    ZwOpenSection and RtlNtStatusToDosError are documented in newer MSDN/DDK. 
// 

type
   NTSTATUS = Integer;

   PUnicodeString = ^TUnicodeString;
   TUnicodeString = packed record
     Length: Word;
     MaximumLength: Word;
     Buffer: PWideChar;
   end;

   PObjectAttributes = ^TObjectAttributes;
   TObjectAttributes = record
     Length: ULONG;
     RootDirectory: THandle;
     ObjectName: PUnicodeString;
     Attributes: ULONG;
     SecurityDescriptor: PSecurityDescriptor;
     SecurityQualityOfService: PSecurityQualityOfService;
   end;

   TFNZwOpenSection = function(out Section: THandle; Access: ACCESS_MASK;
     Attributes: PObjectAttributes): NTSTATUS;
    stdcall;
   TFNRtlNtStatusToDosError = function(Status: NTSTATUS): DWORD;
    stdcall;

 const
   PhysMemDevName = '\Device\PhysicalMemory';
   PhysMemName: TUnicodeString = (Length: Length(PhysMemDevName) * SizeOf(WideChar);
     MaximumLength: Length(PhysMemDevName) * SizeOf(WideChar) + SizeOf(WideChar);
     Buffer: PhysMemDevName;
     );
   PhysMemMask: ACCESS_MASK = SECTION_MAP_READ;
   PhysMemAttr: TObjectAttributes = (Length: SizeOf(TObjectAttributes);
     RootDirectory: 0;
     ObjectName: @PhysMemName;
     Attributes: $00000040;  // OBJ_CASE_INSENSITIVE 
    SecurityDescriptor: nil;
     SecurityQualityOfService: nil;
     );

 var
   ZwOpenSection: TFNZwOpenSection;
   RtlNtStatusToDosError: TFNRtlNtStatusToDosError;

 function DumpRomBiosNt(RomBase: Pointer; RomSize: Cardinal; var Dump): Boolean;
 var
   HMod: HMODULE;
   Stat: NTSTATUS;
   Sect: THandle;
   View: Pointer;
 begin
   Result := False;
   HMod   := GetModuleHandle('ntdll.dll');
   if HMod = 0 then
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED)
   else
   begin
     if not Assigned(ZwOpenSection) then
       ZwOpenSection := GetProcAddress(HMod, 'ZwOpenSection');
     if not Assigned(RtlNtStatusToDosError) then
       RtlNtStatusToDosError := GetProcAddress(HMod, 'RtlNtStatusToDosError');
     if not Assigned(ZwOpenSection) or not Assigned(RtlNtStatusToDosError) then
       SetLastError(ERROR_CALL_NOT_IMPLEMENTED)
     else
     begin
       Stat := ZwOpenSection(Sect, PhysMemMask, @PhysMemAttr);
       if Stat >= 0 then
         try
           View := MapViewOfFile(Sect, PhysMemMask, 0, Cardinal(RomBase), RomSize);
           if View <> nil then
             try
               Move(View^, Dump, RomSize);
               Result := True;
             finally
               UnmapViewOfFile(View);
             end;
         finally
           CloseHandle(Sect);
         end
       else
         SetLastError(RtlNtStatusToDosError(Stat));
     end;
   end;
 end;

 //////////////////////////////////////////////////////////////////////////////// 
// 
//  DumpRomBios(Ex) 
// 
//    Public functions to call OS-dependent implementations. 
// 

function DumpRomBios(out Dump: TRomBiosDump;
   Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean;
 begin
   Result := DumpRomBiosEx(Pointer(RomBiosDumpBase), RomBiosDumpSize, Dump,
     Method, Timeout);
 end;

 function DumpRomBiosEx(RomBase: Pointer; RomSize: Cardinal; out Dump;
   Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean;
 begin
   Result := False;
   case Method of
     rdmAutomatic:
       if (GetVersion() and $80000000) <> 0 then
         Result := DumpRomBios9x(RomBase, RomSize, Dump)
       else
         begin
           Result := DumpRomBiosNt(RomBase, RomSize, Dump);
           if not Result then
             DumpRomBios16(RomBase, RomSize, Dump, DWORD(Timeout));
         end;
       rdmGeneric:
       Result := DumpRomBios16(RomBase, RomSize, Dump, DWORD(Timeout));
     rdmMemory:
       Result := DumpRomBios9x(RomBase, RomSize, Dump);
     rdmPhysical:
       Result := DumpRomBiosNt(RomBase, RomSize, Dump);
     else
       SetLastError(ERROR_INVALID_PARAMETER);
   end;
 end;

 //////////////////////////////////////////////////////////////////////////////// 
// 
//  ReadRomDumpBuffer(Ex) / GetRomDumpAddr(Ex) 
// 
//    Utilities to simplify the access to dumps. 
// 

procedure ReadRomDumpBuffer(const Dump: TRomBiosDump; Addr: Pointer;
   var Buffer; Size: Cardinal);
 begin
   Move(Dump[Cardinal(Addr)], Buffer, Size);
 end;

 procedure ReadRomDumpBufferEx(const Dump; Base, Addr: Pointer;
   var Buffer; Size: Cardinal);
 begin
   Move(Pointer(Cardinal(@Dump) + Cardinal(Addr) - Cardinal(Base))^,
     Buffer, Size);
 end;

 function GetRomDumpAddr(const Dump: TRomBiosDump; Addr: Pointer): Pointer;
 begin
   Result := @Dump[Cardinal(Addr)];
 end;

 function GetRomDumpAddrEx(const Dump; Base, Addr: Pointer): Pointer;
 begin
   Result := Pointer(Cardinal(@Dump) + Cardinal(Addr) - Cardinal(Base));
 end;

 end.





Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook