Jump to content

Compiling ACPI v2.0 driver for Windows XP SP3 and Windows 2003 SP2 (x32/x64)


Mov AX, 0xDEAD

Recommended Posts


@Dietmar

WinXP SP3 really works on 486 CPU? It does not requires Pentium1 CPU or Overdrive CPU (P1 CPU in 486-compatible casing)?

About the problems around PCI cards: be prepared, that most of modern PCI cards will not work (it will be undetected), because your mainboard/BIOS does not supports later PCI specifications (PCI v2.3 / v3.0?). And these informations are mostly unknown about PCI cards. Some new cards are backward compatible, but many of them are not. I had similar problem with my P-1 and USB 2.0 card.

Link to comment
Share on other sites

@PPeti66x

Hi, until now not.

But when I take a look at the Source Code from XP SP1 or even XP bit64, there is in each a file with name slist.asm.

The 64bit version is from 2000, same author. But 64bit slist.asm takes another way, not using  cmpxchg8b.

If this opcodes from 64bit can be translated into x86 code, this would be also a possibility.

But I have no idea, how to reach this in Hex code.

It is unchanged since 1996 for NT4. "Only" the opcode cmpxchg8b has to be simulated with opcode from 486 cpu.

Cutler in 1996 and so also for XP SP1 solved this problem, just "jump" over this opcode during

assembly for .386 (and not .586). I make a try with 90 90 90 90 for all apearance of this opcode in XP SP3 in ntoskrnl.exe.

But Bsod. Strange, because also in XP SP3 there is exact the same code from Cutler used from 1996,

as you can see in ntoskrnl.exe via Ida Pro.

It is a heavy memory operation and with more than 1 cpu there can be problems with this "jump".

But the 486 cpu has only 1 processor, so it may be possible

Dietmar

EDIT: With Windbg, starting with bu ExInterlockedFlushSList I come to its driver entry point of my modded driver.

And via trace (t, F8) I can see, that the code in my modded driver was fully entered and left with retn, no Bsod.

slist.asm XP SP1

        title  "Interlocked Support"
;++
;
; Copyright (c) 1996  Microsoft Corporation
;
; Module Name:
;
;    slist.asm
;
; Abstract:
;
;    This module implements functions to support interlocked S-List
;    operations.
;
; Author:
;
;    David N. Cutler (davec) 13-Mar-1996
;
; Environment:
;
;    Any mode.
;
; Revision History:
;
;--
.386p
        .xlist
include ks386.inc
include callconv.inc                    ; calling convention macros
include mac386.inc
        .list


_TEXT$00   SEGMENT DWORD PUBLIC 'CODE'
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

        page , 132
        subttl  "Interlocked Flush Sequenced List"
;++
;
; PSINGLE_LIST_ENTRY
; FASTCALL
; RtlpInterlockedFlushSList (
;    IN PSINGLE_LIST_ENTRY ListHead
;    )
;
; Routine Description:
;
;    This function removes the entire list from a sequenced singly
;    linked list so that access to the list is synchronized in an MP system.
;    If there are no entries in the list, then a value of NULL is returned.
;    Otherwise, the address of the entry at the top of the list is removed
;    and returned as the function value and the list header is set to point
;    to NULL.
;
; Arguments:
;
;    (ecx) = ListHead - Supplies a pointer to the sequenced listhead from
;         which the list is to be flushed.
;
; Return Value:
;
;    The address of the entire current list, or NULL if the list is
;    empty.
;
;--

;
; These old interfaces just fall into the new ones
;
cPublicFastCall ExInterlockedFlushSList, 1
fstENDP ExInterlockedFlushSList

cPublicFastCall RtlpInterlockedFlushSList, 1

cPublicFpo 0,1

;
; Save nonvolatile registers and read the listhead sequence number followed
; by the listhead next link.
;
; N.B. These two dwords MUST be read exactly in this order.
;

        push    ebx                     ; save nonvolatile registers
        push    ebp                     ;
        xor     ebx, ebx                ; zero out new pointer
        mov     ebp, ecx                ; save listhead address
        mov     edx, [ebp] + 4          ; get current sequence number
        mov     eax, [ebp] + 0          ; get current next link

;
; N.B. The following code is the retry code should the compare
;      part of the compare exchange operation fail
;
; If the list is empty, then there is nothing that can be removed.
;

Efls10: or      eax, eax                ; check if list is empty
        jz      short Efls20            ; if z set, list is empty
        mov     ecx, edx   		; copy sequence number
        mov     cx, bx                  ; clear depth leaving sequence number

.586
ifndef NT_UP

   lock cmpxchg8b qword ptr [ebp]       ; compare and exchange

else

        cmpxchg8b qword ptr [ebp]       ; compare and exchange

endif
.386

        jnz     short Efls10            ; if z clear, exchange failed

;
; Restore nonvolatile registers and return result.
;

cPublicFpo 0,0

Efls20: pop     ebp                     ; restore nonvolatile registers
        pop     ebx                     ;

        fstRET    RtlpInterlockedFlushSList

fstENDP RtlpInterlockedFlushSList

        page , 132
        subttl  "Interlocked Pop Entry Sequenced List"
;++
;
; PVOID
; FASTCALL
; RtlpInterlockedPopEntrySList (
;    IN PSLIST_HEADER ListHead
;    )
;
; Routine Description:
;
;    This function removes an entry from the front of a sequenced singly
;    linked list so that access to the list is synchronized in an MP system.
;    If there are no entries in the list, then a value of NULL is returned.
;    Otherwise, the address of the entry that is removed is returned as the
;    function value.
;
; Arguments:
;
;    (ecx) = ListHead - Supplies a pointer to the sequenced listhead from
;         which an entry is to be removed.
;
; Return Value:
;
;    The address of the entry removed from the list, or NULL if the list is
;    empty.
;
;--

;
; These older interfaces just fall into the new code below
;

cPublicFastCall InterlockedPopEntrySList, 1
fstENDP InterlockedPopEntrySList

cPublicFastCall ExInterlockedPopEntrySList, 2
fstENDP ExInterlockedPopEntrySList


cPublicFastCall RtlpInterlockedPopEntrySList, 1

cPublicFpo 0,2

;
; Save nonvolatile registers and read the listhead sequence number followed
; by the listhead next link.
;
; N.B. These two dwords MUST be read exactly in this order.
;

        push    ebx                     ; save nonvolatile registers
        push    ebp                     ;
        mov     ebp, ecx                ; save listhead address
;
; N.B. The following code is the continuation address should a fault
;      occur in the rare case described below.
;

        public  ExpInterlockedPopEntrySListResume
        public  _ExpInterlockedPopEntrySListResume@0
ExpInterlockedPopEntrySListResume:      ;
_ExpInterlockedPopEntrySListResume@0:   ;

        mov     edx,[ebp] + 4           ; get current sequence number
        mov     eax,[ebp] + 0           ; get current next link

;
; If the list is empty, then there is nothing that can be removed.
;

Epop10: or      eax, eax                ; check if list is empty
        jz      short Epop20            ; if z set, list is empty
        lea     ecx, [edx-1]            ; Adjust depth only


;
; N.B. It is possible for the following instruction to fault in the rare
;      case where the first entry in the list is allocated on another
;      processor and free between the time the free pointer is read above
;      and the following instruction. When this happens, the access fault
;      code continues execution by skipping the following instruction.
;      This results in the compare failing and the entire operation is
;      retried.
;

        public  ExpInterlockedPopEntrySListFault
ExpInterlockedPopEntrySListFault:       ;

        mov     ebx, [eax]              ; get address of successor entry

        public  _ExpInterlockedPopEntrySListEnd@0
_ExpInterlockedPopEntrySListEnd@0:      ;

.586
ifndef NT_UP

   lock cmpxchg8b qword ptr [ebp]       ; compare and exchange

else

        cmpxchg8b qword ptr [ebp]       ; compare and exchange

endif
.386

        jnz     short Epop10            ; if z clear, exchange failed

;
; Restore nonvolatile registers and return result.
;

cPublicFpo 0,0

Epop20: pop     ebp                     ; restore nonvolatile registers
        pop     ebx                     ;

        fstRET    RtlpInterlockedPopEntrySList

fstENDP RtlpInterlockedPopEntrySList

        page , 132
        subttl  "Interlocked Push Entry Sequenced List"
;++
;
; PVOID
; FASTCALL
; RtlpInterlockedPushEntrySList (
;    IN PSLIST_HEADER ListHead,
;    IN PVOID ListEntry
;    )
;
; Routine Description:
;
;    This function inserts an entry at the head of a sequenced singly linked
;    list so that access to the list is synchronized in an MP system.
;
; Arguments:
;
;    (ecx) ListHead - Supplies a pointer to the sequenced listhead into which
;          an entry is to be inserted.
;
;    (edx) ListEntry - Supplies a pointer to the entry to be inserted at the
;          head of the list.
;
; Return Value:
;
;    Previous contents of ListHead.  NULL implies list went from empty
;       to not empty.
;
;--

;
; This old interface just fall into the new code below.
;

cPublicFastCall ExInterlockedPushEntrySList, 3
       pop	[esp]			; Drop the lock argument
fstENDP ExInterlockedPushEntrySList

cPublicFastCall InterlockedPushEntrySList, 2
fstENDP InterlockedPushEntrySList


cPublicFastCall RtlpInterlockedPushEntrySList, 2

cPublicFpo 0,2

;
; Save nonvolatile registers and read the listhead sequence number followed
; by the listhead next link.
;
; N.B. These two dwords MUST be read exactly in this order.
;

        push    ebx                     ; save nonvolatile registers
        push    ebp                     ;
        mov     ebp, ecx                ; save listhead address
        mov     ebx, edx                ; save list entry address
        mov     edx,[ebp] + 4           ; get current sequence number
        mov     eax,[ebp] + 0           ; get current next link
Epsh10: mov     [ebx], eax              ; set next link in new first entry
        lea     ecx, [edx+010001H]      ; increment sequence number and depth

.586
ifndef NT_UP

   lock cmpxchg8b qword ptr [ebp]       ; compare and exchange

else

        cmpxchg8b qword ptr[ebp]        ; compare and exchange

endif
.386

        jnz     short Epsh10            ; if z clear, exchange failed

;
; Restore nonvolatile registers and return result.
;

cPublicFpo 0,0

        pop     ebp                     ; restore nonvolatile registers
        pop     ebx                     ;

        fstRET  RtlpInterlockedPushEntrySList

fstENDP RtlpInterlockedPushEntrySList

;++
;
; SINGLE_LIST_ENTRY
; FASTCALL
; InterlockedPushListSList (
;     IN PSLIST_HEADER ListHead,
;     IN PSINGLE_LIST_ENTRY List,
;     IN PSINGLE_LIST_ENTRY ListEnd,
;     IN ULONG Count
;    )
;
; Routine Description:
;
;    This function will push multiple entries onto an SList at once
;
; Arguments:
;
;     ListHead - List head to push the list to.
;
;     List - The list to add to the front of the SList
;     ListEnd - The last element in the chain
;     Count - The number of items in the chain
;
; Return Value:
;
;     PSINGLE_LIST_ENTRY - The old header pointer is returned
;
;--

cPublicFastCall InterlockedPushListSList, 4

cPublicFpo 0,4
        push    ebx                     ; save nonvolatile registers
        push    ebp                     ;
        mov     ebp, ecx                ; save listhead address
        mov     ebx, edx                ; save list entry address
        mov     edx,[ebp] + 4           ; get current sequence number
        mov     eax,[ebp] + 0           ; get current next link
Epshl10:
        mov     ecx, [esp+4*3]          ; Fetch address of list tail
        mov     [ecx], eax              ; Store new forward pointer in tail entry
        lea     ecx, [edx+010000H]      ; increment sequence number
        add     ecx, [esp+4*4]		; Add in new count to create correct depth
.586
ifndef NT_UP

   lock cmpxchg8b qword ptr [ebp]       ; compare and exchange

else

        cmpxchg8b qword ptr[ebp]        ; compare and exchange

endif
.386
        jnz     short Epshl10           ; if z clear, exchange failed

cPublicFpo 0,0

        pop     ebp                     ; restore nonvolatile registers
        pop     ebx                     ;

        fstRET  InterlockedPushListSList

fstENDP InterlockedPushListSList

;++
;
; PSINGLE_LIST_ENTRY
; FirstEntrySList (
;     IN PSLIST_HEADER SListHead
;     )
;
; Routine Description:
;
;   This function returns the address of the fisrt entry in the SLIST or
;   NULL.
;
; Arguments:
;
;   ListHead (rcx) - Supplies a pointer to the sequenced listhead from
;       which the first entry address is to be computed.
;
; Return Value:
;
;   The address of the first entry is the specified, or NULL if the list is
;   empty.
;
;--

cPublicProc _FirstEntrySList, 1
cPublicFpo 1,0

        mov       eax, [esp+4]
        mov       eax, [eax]
        stdRET    _FirstEntrySList

stdENDP _FirstEntrySList

;++
;
; LONGLONG
; FASTCALL
; RtlInterlockedCompareExchange64 (
;    IN OUT PLONGLONG Destination,
;    IN PLONGLONG Exchange,
;    IN PLONGLONG Comperand
;    )
;
; Routine Description:
;
;    This function performs a compare and exchange of 64-bits.
;
; Arguments:
;
;    (ecx) Destination - Supplies a pointer to the destination variable.
;
;    (edx) Exchange - Supplies a pointer to the exchange value.
;
;    (esp+4) Comperand - Supplies a pointer to the comperand value.
;
; Return Value:
;
;    The current destination value is returned as the function value.
;
;--

cPublicFastCall RtlInterlockedCompareExchange64, 3

cPublicFpo 0,2

;
; Save nonvolatile registers and read the exchange and comperand values.
;

        push    ebx                     ; save nonvolatile registers
        push    ebp                     ;
        mov     ebp, ecx                ; set destination address
        mov     ebx, [edx]              ; get exchange value
        mov     ecx, [edx] + 4          ;
        mov     edx, [esp] + 12         ; get comperand address
        mov     eax, [edx]              ; get comperand value
        mov     edx, [edx] + 4          ;

.586
ifndef NT_UP

   lock cmpxchg8b qword ptr [ebp]       ; compare and exchange

else

        cmpxchg8b qword ptr[ebp]        ; compare and exchange

endif
.386

;
; Restore nonvolatile registers and return result in edx:eax.
;

cPublicFpo 0,0

        pop     ebp                     ; restore nonvolatile registers
        pop     ebx                     ;

        fstRET  RtlInterlockedCompareExchange64

fstENDP RtlInterlockedCompareExchange64

_TEXT$00   ends
        end

 

Edited by Dietmar
Link to comment
Share on other sites

I think, this is a crazy nice way to overcome this problem, that works on all cpu.

Problem is only the translate from AMD64 with 64bit registers this opcode to x86 (486 cpu) with 32 bit registers.

I think, it can be done

Dietmar

For bit64

        mov     rax, [rcx]              ; get address, sequence, and depth
        and     rax, 0fe000000H         ; isolate packed address

;
; The following code takes advantage of the fact that the high order bit
; for user mode addresses is zero and for system addresses is one.
;

ifdef NTOS_KERNEL_RUNTIME

        cmp     rax, 1                  ; set carry if address is zero
        cmc                             ; set carry if address is not zero
        rcr     rax, 1                  ; rotate carry into high bit
        sar     rax, 63 - 43            ; extract first entry address

else

        shr     rax, 63 - 42            ; extract first entry address

endif

        ret                             ; return

 

Edited by Dietmar
Link to comment
Share on other sites

For the 486 cpu, this AMD64 opcode will look something like this

Dietmar

8B 01           ; mov     eax, [ecx]
25 00 00 00 FE  ; and     eax, 0fe000000H

#ifdef NTOS_KERNEL_RUNTIME
80 38 01        ; cmp     byte ptr [eax], 1
F6 D1           ; not     cl
D1 C2           ; ror     eax, 1
C1 F8 2B        ; sar     eax, 43
#else
C1 F8 2A        ; sar     eax, 42
#endif

C3              ; ret

 

Link to comment
Share on other sites

@Dietmar

But the cmpxchg8b is probably used in many system files and drivers, so you must patch probably hundreds or thousands of files. (0F C7 4D 00 pattern found in ntdll.dll, duser.dll and some others, not only in ntoskernel, and there are more variants).

Link to comment
Share on other sites

@PPeti66x

A nice solution for this would be,

when at the moment, when opcode for cmpxchg8b is asked from a file for the 486 cpu,

that there is something like a tender between the opcode and the cpu,

that makes exact the same operations on all the registers, that cmpxchg8b is doing.

It would be like a software simulation for cmpxchg8b direct before the cpu.

The program for this can be done in C language.

I will call it 486.dll .

At once, such an XP would work on 386, 486 586 686 cpu with all functionality.

And once it has been done one time, crazy work,

other unknown opcodes for other cpu can be done the same way.

Dietmar

 

PS: @Mov AX, 0xDEAD  I remember, that you have a tool, that can check, if 2 binaries are doing the same.

 

Edited by Dietmar
Link to comment
Share on other sites

On 2/24/2024 at 5:03 PM, SEDANEH said:

Because Windows XP does not support Nvidia graphics above 1000 series.

I had XP running on a GT 1030 but only in super-VGA mode. I have a GT 730 but it has disappeared under mounds of equipment...can't find it.

Now, when I try to start XP on the same Asus B360, I get a black screen for a long time and sometimes it BSODs after 5 or 10 minutes. I was too slow to get the error code but it is display related. I am trying to repeat the BSOD but all I have is a black screen.

Oddly, I get the XP welcome screen but it does not reach logon. Any ideas?

Also, I can no longer get W7 running on the B360 machine because I re-installed the USB driver for my new B760 and erased the A36D identifier for the older machine. I am looking for a way to re-install the old hardware ID but I can't even find INFfile for it.

Link to comment
Share on other sites

1 hour ago, Damnation said:

@gordo999

Bricked XP install probably.

Could be. I have not touched the disk for a while and it worked last time I tried it. Also, for some reason I made a clone backup of the installation on another hard drive. It doesn't work either. Rust!!!  :-)

Link to comment
Share on other sites

@Dietmar

I think, the image loader part of the kernel must be hacked to do that. But the task itself is not so easy. The long jump is 5 bytes, the cmpxchg8b is 4 bytes, so we need to recognize and preserve the next instruction. I have no idea, how to do that.

Link to comment
Share on other sites

25 minutes ago, PPeti66x said:

@Dietmar

I think, the image loader part of the kernel must be hacked to do that. But the task itself is not so easy. The long jump is 5 bytes, the cmpxchg8b is 4 bytes, so we need to recognize and preserve the next instruction. I have no idea, how to do that.

You'd need a code cave nearby where you could access it with a jmp instruction, then write your new code and return to the next instruction.

Link to comment
Share on other sites

1 hour ago, PPeti66x said:

@Dietmar

I think, the image loader part of the kernel must be hacked to do that. But the task itself is not so easy. The long jump is 5 bytes, the cmpxchg8b is 4 bytes, so we need to recognize and preserve the next instruction. I have no idea, how to do that.

Something like this maybe?  Red/Blue is existing code, Green is extra code to be added but not enough space.  So Black to jump to free spot, add code, then return from.  As long as there is enough space for jump command and location to jump to a free spot.

x86rtc-HAL-TSC-frequency-divider-subrout

Link to comment
Share on other sites

On 3/29/2024 at 2:24 AM, Damnation said:

@gordo999

Bricked XP install probably.

@Damnation ...Is the old thread around where we can discuss XP in general? I don't want to hijack @Dietmar 's thread.

Part of my problem was brain-deadness. When I tried to run W7 on my old B360, I forgot to add the hardware ID to the INF file. Duh!!!

Have not verified yet but the XP issue may be related to the video driver. I had it running before on a GT 1030 in SVGA mode at high resolution and that worked fine for me. Thought it might be an HDMI/DVI issue but it did not work either on the onboard Intel video driver using a D-type connector.

I don't think XP is bricked. I have been able to run it fine up to the intro screen. Replacing the BIOS got W10 running again and I don't want to try XP again in case it causes the same issue. Trying to understand why it would.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...