Handling NMIs on XP/Win2003

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have got a special hardware on which I want to run XP embedded. Under some
circumstances (e.g. powerfail) there are NMIs generated.
Is there any way to handle this NMI simular to Win2003 ?

With Win2003 there you can use KeRegisterNmiCallback to install your own
handler and it works fine.

On XP the only thing I achieve is a bluescreen with **Hardware
Malfunction**. Even if I NOP out the HalHandleNMI call the system is dead
after an NMI.

thanks
Burkhard
 
Hi Burkhard,

nt!KiTrap02
nt!_imp__HalHandleNMI

80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]

80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

For test NOP call and jnz instruction bytes (as you probably know there is more than two bytes to change to NOP). And it might work.
Please let us know.

If this work you have two possible paths.
1. Obtain documentation from MS about writing hal.dll and reimplement HalHandleNMI functionality.
2. Make a simple driver that will patch these bytes in ntoskrnl.exe during the XP init phase.

Regards,
Slobodan
 
Hi Slobodan,
the NMI is implemented in XP and Win2003 via a TaskGate (TSS 58) in the IDT.
This must be done, because in the kernel the SS and ESP are not set with the
non interruptable LSS statement but with CLI and seperate MOV statements.

The HAL!HalHandleNMI routine ends up with a infinite loop
806CC03D jmp 806CC03D (I think to stop system).

When I replace the call to HalHandleNMI with NOPs and correct the stack
(lots of values are pushed onto the stack before the call), XP dies with a
black screen. If I do the same with Win2003 it works.
The implementaion with TSS 58 in XP and Win2003 is nearly identical, the
only difference is some extra code in Win2003 at the beginning of the
NMI-routine (where the EIP of TSS 58 points to):

mov eax,[0xFFDFF040]
mov ecx,[0xFFDFF124]
mov edi,[ECX+0x44]
mov ecx,[edi+0x18]
mov [eax+0x1c],ecx
mov cx,[edi+0x30]
mov [eax+0x66],cx
mov ecx,[edi+0x20]
test ecx,ecx
jz LABEL1
mov cx,0x0048
LABEL1:
mov[eax+0x60],cx

For me it looks a little bit like XP is not intended to continue after an
NMI ?

At the moment I am on holidays, so I can't execute real test until January.
Thanks,
Burkhard

Slobodan Brcin (eMVP) said:
Hi Burkhard,

nt!KiTrap02
nt!_imp__HalHandleNMI

80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]

80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

For test NOP call and jnz instruction bytes (as you probably know there is more than two bytes to change to NOP). And it might work.
Please let us know.

If this work you have two possible paths.
1. Obtain documentation from MS about writing hal.dll and reimplement HalHandleNMI functionality.
2. Make a simple driver that will patch these bytes in ntoskrnl.exe during the XP init phase.

Regards,
Slobodan


bcpauli said:
I have got a special hardware on which I want to run XP embedded. Under some
circumstances (e.g. powerfail) there are NMIs generated.
Is there any way to handle this NMI simular to Win2003 ?

With Win2003 there you can use KeRegisterNmiCallback to install your own
handler and it works fine.

On XP the only thing I achieve is a bluescreen with **Hardware
Malfunction**. Even if I NOP out the HalHandleNMI call the system is dead
after an NMI.

thanks
Burkhard
 
Hi Burkhard,

You are lucky that I'm deep in XP kernel asm code analysis at the moment.

Forget analyzing XP code without at least symbols present.
Let us use following code for analysis: (This is Checked XP SP2 kernel with symbols present) this code in NMI handler forget about
registers, etc

Find this:
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

As you can see if you can make it to pass trough this there is iretd available at the end.

Best regards,
Slobodan


nt!KiTrap02:
80ad6af8 fa cli
80ad6af9 64ff3540000000 push dword ptr fs:[00000040]
80ad6b00 64a13c000000 mov eax,fs:[0000003c]
80ad6b06 8a685f mov ch,[eax+0x5f]
80ad6b09 8a485c mov cl,[eax+0x5c]
80ad6b0c c1e110 shl ecx,0x10
80ad6b0f 668b485a mov cx,[eax+0x5a]
80ad6b13 64890d40000000 mov fs:[00000040],ecx
80ad6b1a 9c pushfd
80ad6b1b 812424ffbfffff and dword ptr [esp],0xffffbfff
80ad6b22 9d popfd
80ad6b23 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6b2a 8d4158 lea eax,[ecx+0x58]
80ad6b2d c6400589 mov byte ptr [eax+0x5],0x89
80ad6b31 8b0424 mov eax,[esp]
80ad6b34 6a00 push 0x0
80ad6b36 6a00 push 0x0
80ad6b38 6a00 push 0x0
80ad6b3a 6a00 push 0x0
80ad6b3c ff7050 push dword ptr [eax+0x50]
80ad6b3f ff7038 push dword ptr [eax+0x38]
80ad6b42 ff7024 push dword ptr [eax+0x24]
80ad6b45 ff704c push dword ptr [eax+0x4c]
80ad6b48 ff7020 push dword ptr [eax+0x20]
80ad6b4b 6a00 push 0x0
80ad6b4d ff703c push dword ptr [eax+0x3c]
80ad6b50 ff7034 push dword ptr [eax+0x34]
80ad6b53 ff7040 push dword ptr [eax+0x40]
80ad6b56 ff7044 push dword ptr [eax+0x44]
80ad6b59 ff7058 push dword ptr [eax+0x58]
80ad6b5c 64ff3500000000 push dword ptr fs:[00000000]
80ad6b63 6aff push 0xff
80ad6b65 ff7028 push dword ptr [eax+0x28]
80ad6b68 ff702c push dword ptr [eax+0x2c]
80ad6b6b ff7030 push dword ptr [eax+0x30]
80ad6b6e ff7054 push dword ptr [eax+0x54]
80ad6b71 ff7048 push dword ptr [eax+0x48]
80ad6b74 ff705c push dword ptr [eax+0x5c]
80ad6b77 6a00 push 0x0
80ad6b79 6a00 push 0x0
80ad6b7b 6a00 push 0x0
80ad6b7d 6a00 push 0x0
80ad6b7f 6a00 push 0x0
80ad6b81 6a00 push 0x0
80ad6b83 6a00 push 0x0
80ad6b85 6a00 push 0x0
80ad6b87 6a00 push 0x0
80ad6b89 6a00 push 0x0
80ad6b8b ff7020 push dword ptr [eax+0x20]
80ad6b8e ff703c push dword ptr [eax+0x3c]
80ad6b91 8bec mov ebp,esp
80ad6b93 33db xor ebx,ebx
80ad6b95 648a1d51000000 mov bl,fs:[00000051]
80ad6b9c 391d5c99ae80 cmp [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6ba2 7414 jz nt!KiTrap02+0xc0 (80ad6bb8)
80ad6ba4 8d055899ae80 lea eax,[nt!KiBiosReenteredAssert+0x27 (80ae9958)]
80ad6baa 50 push eax
80ad6bab 6a00 push 0x0
80ad6bad 8bcc mov ecx,esp
80ad6baf 8bd5 mov edx,ebp
80ad6bb1 e83a32f6ff call nt!KiAcquireQueuedSpinLockCheckForFreeze (80a39df0)
80ad6bb6 eb24 jmp nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bb8 833d6099ae8008 cmp dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)],0x8
80ad6bbf 721b jb nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bc1 7517 jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bc3 803dc0daae8000 cmp byte ptr [nt!KdDebuggerNotPresent (80aedac0)],0x0
80ad6bca 750e jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bcc 803dc1daae8000 cmp byte ptr [nt!KdDebuggerEnabled (80aedac1)],0x0
80ad6bd3 7405 jz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bd5 e83ea2f5ff call nt!KeEnterKernelDebugger (80a30e18)
80ad6bda ebfe jmp nt!KiTrap02+0xe2 (80ad6bda)
80ad6bdc 891d5c99ae80 mov [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6be2 ff056099ae80 inc dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
80ad6bf8 c7055c99ae80ffffffff mov dword ptr [nt!KiBiosReenteredAssert+0x2b (80ae995c)],0xffffffff
80ad6c02 8bcc mov ecx,esp
80ad6c04 e8a7e2ffff call nt!KeReleaseQueuedSpinLockFromDpcLevel (80ad4eb0)
80ad6c09 83c408 add esp,0x8
80ad6c0c 64a140000000 mov eax,fs:[00000040]
80ad6c12 66833858 cmp word ptr [eax],0x58
80ad6c16 742a jz nt!KiTrap02+0x14a (80ad6c42)
80ad6c18 81c48c000000 add esp,0x8c
80ad6c1e 648f0540000000 pop fs:[00000040]
80ad6c25 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6c2c 8d4128 lea eax,[ecx+0x28]
80ad6c2f c640058b mov byte ptr [eax+0x5],0x8b
80ad6c33 9c pushfd
80ad6c34 810c2400400000 or dword ptr [esp],0x4000
80ad6c3b 9d popfd
80ad6c3c cf iretd
80ad6c3d e9b6feffff jmp nt!KiTrap02 (80ad6af8)
80ad6c42 b802000000 mov eax,0x2
80ad6c47 e9a02a0000 jmp nt!KiSystemFatalException (80ad96ec)





bcpauli said:
Hi Slobodan,
the NMI is implemented in XP and Win2003 via a TaskGate (TSS 58) in the IDT.
This must be done, because in the kernel the SS and ESP are not set with the
non interruptable LSS statement but with CLI and seperate MOV statements.

The HAL!HalHandleNMI routine ends up with a infinite loop
806CC03D jmp 806CC03D (I think to stop system).

When I replace the call to HalHandleNMI with NOPs and correct the stack
(lots of values are pushed onto the stack before the call), XP dies with a
black screen. If I do the same with Win2003 it works.
The implementaion with TSS 58 in XP and Win2003 is nearly identical, the
only difference is some extra code in Win2003 at the beginning of the
NMI-routine (where the EIP of TSS 58 points to):

mov eax,[0xFFDFF040]
mov ecx,[0xFFDFF124]
mov edi,[ECX+0x44]
mov ecx,[edi+0x18]
mov [eax+0x1c],ecx
mov cx,[edi+0x30]
mov [eax+0x66],cx
mov ecx,[edi+0x20]
test ecx,ecx
jz LABEL1
mov cx,0x0048
LABEL1:
mov[eax+0x60],cx

For me it looks a little bit like XP is not intended to continue after an
NMI ?

At the moment I am on holidays, so I can't execute real test until January.
Thanks,
Burkhard

Slobodan Brcin (eMVP) said:
Hi Burkhard,

nt!KiTrap02
nt!_imp__HalHandleNMI

80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]

80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

For test NOP call and jnz instruction bytes (as you probably know there is more than two bytes to change to NOP). And it might work.
Please let us know.

If this work you have two possible paths.
1. Obtain documentation from MS about writing hal.dll and reimplement HalHandleNMI functionality.
2. Make a simple driver that will patch these bytes in ntoskrnl.exe during the XP init phase.

Regards,
Slobodan


bcpauli said:
I have got a special hardware on which I want to run XP embedded. Under some
circumstances (e.g. powerfail) there are NMIs generated.
Is there any way to handle this NMI simular to Win2003 ?

With Win2003 there you can use KeRegisterNmiCallback to install your own
handler and it works fine.

On XP the only thing I achieve is a bluescreen with **Hardware
Malfunction**. Even if I NOP out the HalHandleNMI call the system is dead
after an NMI.

thanks
Burkhard
 
Guys, I may be completely off the topic but just an idea...

It seems that XP does not really handle NMI. I mean the HAL export is there but it doesn't support callbacks.
However, there is bugcheck support for NMI routine (I think that is there since NT) if you set NMICrashDump reg.value under
CrashControl key (that should set internal HalpNMIDumpFlag global system variable).

Then on XP you can register your own bugcheck callback though KeRegisterBugCheckCallback. And you have a way to call your code on
NMI.

Some more info:
- about NMICrashDump: http://www.microsoft.com/whdc/system/CEC/dmpsw.mspx
- about KeRegisterBugCheckCallback:

--
Regards,
KM, BSquare Corp.

PS. Btw, we don't know much about your special hardware, Burkhard. I hope it is not SMP? Otherwise you will get an IDT table for
each processor.
Hi Burkhard,

You are lucky that I'm deep in XP kernel asm code analysis at the moment.

Forget analyzing XP code without at least symbols present.
Let us use following code for analysis: (This is Checked XP SP2 kernel with symbols present) this code in NMI handler forget about
registers, etc

Find this:
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

As you can see if you can make it to pass trough this there is iretd available at the end.

Best regards,
Slobodan


nt!KiTrap02:
80ad6af8 fa cli
80ad6af9 64ff3540000000 push dword ptr fs:[00000040]
80ad6b00 64a13c000000 mov eax,fs:[0000003c]
80ad6b06 8a685f mov ch,[eax+0x5f]
80ad6b09 8a485c mov cl,[eax+0x5c]
80ad6b0c c1e110 shl ecx,0x10
80ad6b0f 668b485a mov cx,[eax+0x5a]
80ad6b13 64890d40000000 mov fs:[00000040],ecx
80ad6b1a 9c pushfd
80ad6b1b 812424ffbfffff and dword ptr [esp],0xffffbfff
80ad6b22 9d popfd
80ad6b23 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6b2a 8d4158 lea eax,[ecx+0x58]
80ad6b2d c6400589 mov byte ptr [eax+0x5],0x89
80ad6b31 8b0424 mov eax,[esp]
80ad6b34 6a00 push 0x0
80ad6b36 6a00 push 0x0
80ad6b38 6a00 push 0x0
80ad6b3a 6a00 push 0x0
80ad6b3c ff7050 push dword ptr [eax+0x50]
80ad6b3f ff7038 push dword ptr [eax+0x38]
80ad6b42 ff7024 push dword ptr [eax+0x24]
80ad6b45 ff704c push dword ptr [eax+0x4c]
80ad6b48 ff7020 push dword ptr [eax+0x20]
80ad6b4b 6a00 push 0x0
80ad6b4d ff703c push dword ptr [eax+0x3c]
80ad6b50 ff7034 push dword ptr [eax+0x34]
80ad6b53 ff7040 push dword ptr [eax+0x40]
80ad6b56 ff7044 push dword ptr [eax+0x44]
80ad6b59 ff7058 push dword ptr [eax+0x58]
80ad6b5c 64ff3500000000 push dword ptr fs:[00000000]
80ad6b63 6aff push 0xff
80ad6b65 ff7028 push dword ptr [eax+0x28]
80ad6b68 ff702c push dword ptr [eax+0x2c]
80ad6b6b ff7030 push dword ptr [eax+0x30]
80ad6b6e ff7054 push dword ptr [eax+0x54]
80ad6b71 ff7048 push dword ptr [eax+0x48]
80ad6b74 ff705c push dword ptr [eax+0x5c]
80ad6b77 6a00 push 0x0
80ad6b79 6a00 push 0x0
80ad6b7b 6a00 push 0x0
80ad6b7d 6a00 push 0x0
80ad6b7f 6a00 push 0x0
80ad6b81 6a00 push 0x0
80ad6b83 6a00 push 0x0
80ad6b85 6a00 push 0x0
80ad6b87 6a00 push 0x0
80ad6b89 6a00 push 0x0
80ad6b8b ff7020 push dword ptr [eax+0x20]
80ad6b8e ff703c push dword ptr [eax+0x3c]
80ad6b91 8bec mov ebp,esp
80ad6b93 33db xor ebx,ebx
80ad6b95 648a1d51000000 mov bl,fs:[00000051]
80ad6b9c 391d5c99ae80 cmp [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6ba2 7414 jz nt!KiTrap02+0xc0 (80ad6bb8)
80ad6ba4 8d055899ae80 lea eax,[nt!KiBiosReenteredAssert+0x27 (80ae9958)]
80ad6baa 50 push eax
80ad6bab 6a00 push 0x0
80ad6bad 8bcc mov ecx,esp
80ad6baf 8bd5 mov edx,ebp
80ad6bb1 e83a32f6ff call nt!KiAcquireQueuedSpinLockCheckForFreeze (80a39df0)
80ad6bb6 eb24 jmp nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bb8 833d6099ae8008 cmp dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)],0x8
80ad6bbf 721b jb nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bc1 7517 jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bc3 803dc0daae8000 cmp byte ptr [nt!KdDebuggerNotPresent (80aedac0)],0x0
80ad6bca 750e jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bcc 803dc1daae8000 cmp byte ptr [nt!KdDebuggerEnabled (80aedac1)],0x0
80ad6bd3 7405 jz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bd5 e83ea2f5ff call nt!KeEnterKernelDebugger (80a30e18)
80ad6bda ebfe jmp nt!KiTrap02+0xe2 (80ad6bda)
80ad6bdc 891d5c99ae80 mov [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6be2 ff056099ae80 inc dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
80ad6bf8 c7055c99ae80ffffffff mov dword ptr [nt!KiBiosReenteredAssert+0x2b (80ae995c)],0xffffffff
80ad6c02 8bcc mov ecx,esp
80ad6c04 e8a7e2ffff call nt!KeReleaseQueuedSpinLockFromDpcLevel (80ad4eb0)
80ad6c09 83c408 add esp,0x8
80ad6c0c 64a140000000 mov eax,fs:[00000040]
80ad6c12 66833858 cmp word ptr [eax],0x58
80ad6c16 742a jz nt!KiTrap02+0x14a (80ad6c42)
80ad6c18 81c48c000000 add esp,0x8c
80ad6c1e 648f0540000000 pop fs:[00000040]
80ad6c25 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6c2c 8d4128 lea eax,[ecx+0x28]
80ad6c2f c640058b mov byte ptr [eax+0x5],0x8b
80ad6c33 9c pushfd
80ad6c34 810c2400400000 or dword ptr [esp],0x4000
80ad6c3b 9d popfd
80ad6c3c cf iretd
80ad6c3d e9b6feffff jmp nt!KiTrap02 (80ad6af8)
80ad6c42 b802000000 mov eax,0x2
80ad6c47 e9a02a0000 jmp nt!KiSystemFatalException (80ad96ec)





bcpauli said:
Hi Slobodan,
the NMI is implemented in XP and Win2003 via a TaskGate (TSS 58) in the IDT.
This must be done, because in the kernel the SS and ESP are not set with the
non interruptable LSS statement but with CLI and seperate MOV statements.

The HAL!HalHandleNMI routine ends up with a infinite loop
806CC03D jmp 806CC03D (I think to stop system).

When I replace the call to HalHandleNMI with NOPs and correct the stack
(lots of values are pushed onto the stack before the call), XP dies with a
black screen. If I do the same with Win2003 it works.
The implementaion with TSS 58 in XP and Win2003 is nearly identical, the
only difference is some extra code in Win2003 at the beginning of the
NMI-routine (where the EIP of TSS 58 points to):

mov eax,[0xFFDFF040]
mov ecx,[0xFFDFF124]
mov edi,[ECX+0x44]
mov ecx,[edi+0x18]
mov [eax+0x1c],ecx
mov cx,[edi+0x30]
mov [eax+0x66],cx
mov ecx,[edi+0x20]
test ecx,ecx
jz LABEL1
mov cx,0x0048
LABEL1:
mov[eax+0x60],cx

For me it looks a little bit like XP is not intended to continue after an
NMI ?

At the moment I am on holidays, so I can't execute real test until January.
Thanks,
Burkhard

Slobodan Brcin (eMVP) said:
Hi Burkhard,

nt!KiTrap02
nt!_imp__HalHandleNMI

80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]

80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

For test NOP call and jnz instruction bytes (as you probably know there is more than two bytes to change to NOP). And it might work.
Please let us know.

If this work you have two possible paths.
1. Obtain documentation from MS about writing hal.dll and reimplement HalHandleNMI functionality.
2. Make a simple driver that will patch these bytes in ntoskrnl.exe during the XP init phase.

Regards,
Slobodan


I have got a special hardware on which I want to run XP embedded. Under some
circumstances (e.g. powerfail) there are NMIs generated.
Is there any way to handle this NMI simular to Win2003 ?

With Win2003 there you can use KeRegisterNmiCallback to install your own
handler and it works fine.

On XP the only thing I achieve is a bluescreen with **Hardware
Malfunction**. Even if I NOP out the HalHandleNMI call the system is dead
after an NMI.

thanks
Burkhard
 
Konstantin,

Sounds crazy enough that it might even work :-) But he will need to test this.

Regards,
Slobodan


KM said:
Guys, I may be completely off the topic but just an idea...

It seems that XP does not really handle NMI. I mean the HAL export is there but it doesn't support callbacks.
However, there is bugcheck support for NMI routine (I think that is there since NT) if you set NMICrashDump reg.value under
CrashControl key (that should set internal HalpNMIDumpFlag global system variable).

Then on XP you can register your own bugcheck callback though KeRegisterBugCheckCallback. And you have a way to call your code on
NMI.

Some more info:
- about NMICrashDump: http://www.microsoft.com/whdc/system/CEC/dmpsw.mspx
- about KeRegisterBugCheckCallback:

--
Regards,
KM, BSquare Corp.

PS. Btw, we don't know much about your special hardware, Burkhard. I hope it is not SMP? Otherwise you will get an IDT table for
each processor.
Hi Burkhard,

You are lucky that I'm deep in XP kernel asm code analysis at the moment.

Forget analyzing XP code without at least symbols present.
Let us use following code for analysis: (This is Checked XP SP2 kernel with symbols present) this code in NMI handler forget about
registers, etc

Find this:
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

As you can see if you can make it to pass trough this there is iretd available at the end.

Best regards,
Slobodan


nt!KiTrap02:
80ad6af8 fa cli
80ad6af9 64ff3540000000 push dword ptr fs:[00000040]
80ad6b00 64a13c000000 mov eax,fs:[0000003c]
80ad6b06 8a685f mov ch,[eax+0x5f]
80ad6b09 8a485c mov cl,[eax+0x5c]
80ad6b0c c1e110 shl ecx,0x10
80ad6b0f 668b485a mov cx,[eax+0x5a]
80ad6b13 64890d40000000 mov fs:[00000040],ecx
80ad6b1a 9c pushfd
80ad6b1b 812424ffbfffff and dword ptr [esp],0xffffbfff
80ad6b22 9d popfd
80ad6b23 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6b2a 8d4158 lea eax,[ecx+0x58]
80ad6b2d c6400589 mov byte ptr [eax+0x5],0x89
80ad6b31 8b0424 mov eax,[esp]
80ad6b34 6a00 push 0x0
80ad6b36 6a00 push 0x0
80ad6b38 6a00 push 0x0
80ad6b3a 6a00 push 0x0
80ad6b3c ff7050 push dword ptr [eax+0x50]
80ad6b3f ff7038 push dword ptr [eax+0x38]
80ad6b42 ff7024 push dword ptr [eax+0x24]
80ad6b45 ff704c push dword ptr [eax+0x4c]
80ad6b48 ff7020 push dword ptr [eax+0x20]
80ad6b4b 6a00 push 0x0
80ad6b4d ff703c push dword ptr [eax+0x3c]
80ad6b50 ff7034 push dword ptr [eax+0x34]
80ad6b53 ff7040 push dword ptr [eax+0x40]
80ad6b56 ff7044 push dword ptr [eax+0x44]
80ad6b59 ff7058 push dword ptr [eax+0x58]
80ad6b5c 64ff3500000000 push dword ptr fs:[00000000]
80ad6b63 6aff push 0xff
80ad6b65 ff7028 push dword ptr [eax+0x28]
80ad6b68 ff702c push dword ptr [eax+0x2c]
80ad6b6b ff7030 push dword ptr [eax+0x30]
80ad6b6e ff7054 push dword ptr [eax+0x54]
80ad6b71 ff7048 push dword ptr [eax+0x48]
80ad6b74 ff705c push dword ptr [eax+0x5c]
80ad6b77 6a00 push 0x0
80ad6b79 6a00 push 0x0
80ad6b7b 6a00 push 0x0
80ad6b7d 6a00 push 0x0
80ad6b7f 6a00 push 0x0
80ad6b81 6a00 push 0x0
80ad6b83 6a00 push 0x0
80ad6b85 6a00 push 0x0
80ad6b87 6a00 push 0x0
80ad6b89 6a00 push 0x0
80ad6b8b ff7020 push dword ptr [eax+0x20]
80ad6b8e ff703c push dword ptr [eax+0x3c]
80ad6b91 8bec mov ebp,esp
80ad6b93 33db xor ebx,ebx
80ad6b95 648a1d51000000 mov bl,fs:[00000051]
80ad6b9c 391d5c99ae80 cmp [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6ba2 7414 jz nt!KiTrap02+0xc0 (80ad6bb8)
80ad6ba4 8d055899ae80 lea eax,[nt!KiBiosReenteredAssert+0x27 (80ae9958)]
80ad6baa 50 push eax
80ad6bab 6a00 push 0x0
80ad6bad 8bcc mov ecx,esp
80ad6baf 8bd5 mov edx,ebp
80ad6bb1 e83a32f6ff call nt!KiAcquireQueuedSpinLockCheckForFreeze (80a39df0)
80ad6bb6 eb24 jmp nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bb8 833d6099ae8008 cmp dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)],0x8
80ad6bbf 721b jb nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bc1 7517 jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bc3 803dc0daae8000 cmp byte ptr [nt!KdDebuggerNotPresent (80aedac0)],0x0
80ad6bca 750e jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bcc 803dc1daae8000 cmp byte ptr [nt!KdDebuggerEnabled (80aedac1)],0x0
80ad6bd3 7405 jz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bd5 e83ea2f5ff call nt!KeEnterKernelDebugger (80a30e18)
80ad6bda ebfe jmp nt!KiTrap02+0xe2 (80ad6bda)
80ad6bdc 891d5c99ae80 mov [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6be2 ff056099ae80 inc dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
80ad6bf8 c7055c99ae80ffffffff mov dword ptr [nt!KiBiosReenteredAssert+0x2b (80ae995c)],0xffffffff
80ad6c02 8bcc mov ecx,esp
80ad6c04 e8a7e2ffff call nt!KeReleaseQueuedSpinLockFromDpcLevel (80ad4eb0)
80ad6c09 83c408 add esp,0x8
80ad6c0c 64a140000000 mov eax,fs:[00000040]
80ad6c12 66833858 cmp word ptr [eax],0x58
80ad6c16 742a jz nt!KiTrap02+0x14a (80ad6c42)
80ad6c18 81c48c000000 add esp,0x8c
80ad6c1e 648f0540000000 pop fs:[00000040]
80ad6c25 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6c2c 8d4128 lea eax,[ecx+0x28]
80ad6c2f c640058b mov byte ptr [eax+0x5],0x8b
80ad6c33 9c pushfd
80ad6c34 810c2400400000 or dword ptr [esp],0x4000
80ad6c3b 9d popfd
80ad6c3c cf iretd
80ad6c3d e9b6feffff jmp nt!KiTrap02 (80ad6af8)
80ad6c42 b802000000 mov eax,0x2
80ad6c47 e9a02a0000 jmp nt!KiSystemFatalException (80ad96ec)





bcpauli said:
Hi Slobodan,
the NMI is implemented in XP and Win2003 via a TaskGate (TSS 58) in the IDT.
This must be done, because in the kernel the SS and ESP are not set with the
non interruptable LSS statement but with CLI and seperate MOV statements.

The HAL!HalHandleNMI routine ends up with a infinite loop
806CC03D jmp 806CC03D (I think to stop system).

When I replace the call to HalHandleNMI with NOPs and correct the stack
(lots of values are pushed onto the stack before the call), XP dies with a
black screen. If I do the same with Win2003 it works.
The implementaion with TSS 58 in XP and Win2003 is nearly identical, the
only difference is some extra code in Win2003 at the beginning of the
NMI-routine (where the EIP of TSS 58 points to):

mov eax,[0xFFDFF040]
mov ecx,[0xFFDFF124]
mov edi,[ECX+0x44]
mov ecx,[edi+0x18]
mov [eax+0x1c],ecx
mov cx,[edi+0x30]
mov [eax+0x66],cx
mov ecx,[edi+0x20]
test ecx,ecx
jz LABEL1
mov cx,0x0048
LABEL1:
mov[eax+0x60],cx

For me it looks a little bit like XP is not intended to continue after an
NMI ?

At the moment I am on holidays, so I can't execute real test until January.
Thanks,
Burkhard

:

Hi Burkhard,

nt!KiTrap02
nt!_imp__HalHandleNMI

80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]

80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

For test NOP call and jnz instruction bytes (as you probably know there is more than two bytes to change to NOP). And it
might
work.
Please let us know.

If this work you have two possible paths.
1. Obtain documentation from MS about writing hal.dll and reimplement HalHandleNMI functionality.
2. Make a simple driver that will patch these bytes in ntoskrnl.exe during the XP init phase.

Regards,
Slobodan


I have got a special hardware on which I want to run XP embedded. Under some
circumstances (e.g. powerfail) there are NMIs generated.
Is there any way to handle this NMI simular to Win2003 ?

With Win2003 there you can use KeRegisterNmiCallback to install your own
handler and it works fine.

On XP the only thing I achieve is a bluescreen with **Hardware
Malfunction**. Even if I NOP out the HalHandleNMI call the system is dead
after an NMI.

thanks
Burkhard
 
Yup. It always starts from a crazy idea :-)

I seem to have forgotten to include the link to KeRegisterBugCheckCallback:
http://msdn.microsoft.com/library/d..._42736e68-1f5a-47df-976a-df3bfa9a356e.xml.asp.
Anyway, you both have DDK and the docs so you know what I am talking about here.

--
Regards,
Konstantin
Konstantin,

Sounds crazy enough that it might even work :-) But he will need to test this.

Regards,
Slobodan


KM said:
Guys, I may be completely off the topic but just an idea...

It seems that XP does not really handle NMI. I mean the HAL export is there but it doesn't support callbacks.
However, there is bugcheck support for NMI routine (I think that is there since NT) if you set NMICrashDump reg.value under
CrashControl key (that should set internal HalpNMIDumpFlag global system variable).

Then on XP you can register your own bugcheck callback though KeRegisterBugCheckCallback. And you have a way to call your code on
NMI.

Some more info:
- about NMICrashDump: http://www.microsoft.com/whdc/system/CEC/dmpsw.mspx
- about KeRegisterBugCheckCallback:

--
Regards,
KM, BSquare Corp.

PS. Btw, we don't know much about your special hardware, Burkhard. I hope it is not SMP? Otherwise you will get an IDT table for
each processor.
Hi Burkhard,

You are lucky that I'm deep in XP kernel asm code analysis at the moment.

Forget analyzing XP code without at least symbols present.
Let us use following code for analysis: (This is Checked XP SP2 kernel with symbols present) this code in NMI handler forget about
registers, etc

Find this:
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

As you can see if you can make it to pass trough this there is iretd available at the end.

Best regards,
Slobodan


nt!KiTrap02:
80ad6af8 fa cli
80ad6af9 64ff3540000000 push dword ptr fs:[00000040]
80ad6b00 64a13c000000 mov eax,fs:[0000003c]
80ad6b06 8a685f mov ch,[eax+0x5f]
80ad6b09 8a485c mov cl,[eax+0x5c]
80ad6b0c c1e110 shl ecx,0x10
80ad6b0f 668b485a mov cx,[eax+0x5a]
80ad6b13 64890d40000000 mov fs:[00000040],ecx
80ad6b1a 9c pushfd
80ad6b1b 812424ffbfffff and dword ptr [esp],0xffffbfff
80ad6b22 9d popfd
80ad6b23 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6b2a 8d4158 lea eax,[ecx+0x58]
80ad6b2d c6400589 mov byte ptr [eax+0x5],0x89
80ad6b31 8b0424 mov eax,[esp]
80ad6b34 6a00 push 0x0
80ad6b36 6a00 push 0x0
80ad6b38 6a00 push 0x0
80ad6b3a 6a00 push 0x0
80ad6b3c ff7050 push dword ptr [eax+0x50]
80ad6b3f ff7038 push dword ptr [eax+0x38]
80ad6b42 ff7024 push dword ptr [eax+0x24]
80ad6b45 ff704c push dword ptr [eax+0x4c]
80ad6b48 ff7020 push dword ptr [eax+0x20]
80ad6b4b 6a00 push 0x0
80ad6b4d ff703c push dword ptr [eax+0x3c]
80ad6b50 ff7034 push dword ptr [eax+0x34]
80ad6b53 ff7040 push dword ptr [eax+0x40]
80ad6b56 ff7044 push dword ptr [eax+0x44]
80ad6b59 ff7058 push dword ptr [eax+0x58]
80ad6b5c 64ff3500000000 push dword ptr fs:[00000000]
80ad6b63 6aff push 0xff
80ad6b65 ff7028 push dword ptr [eax+0x28]
80ad6b68 ff702c push dword ptr [eax+0x2c]
80ad6b6b ff7030 push dword ptr [eax+0x30]
80ad6b6e ff7054 push dword ptr [eax+0x54]
80ad6b71 ff7048 push dword ptr [eax+0x48]
80ad6b74 ff705c push dword ptr [eax+0x5c]
80ad6b77 6a00 push 0x0
80ad6b79 6a00 push 0x0
80ad6b7b 6a00 push 0x0
80ad6b7d 6a00 push 0x0
80ad6b7f 6a00 push 0x0
80ad6b81 6a00 push 0x0
80ad6b83 6a00 push 0x0
80ad6b85 6a00 push 0x0
80ad6b87 6a00 push 0x0
80ad6b89 6a00 push 0x0
80ad6b8b ff7020 push dword ptr [eax+0x20]
80ad6b8e ff703c push dword ptr [eax+0x3c]
80ad6b91 8bec mov ebp,esp
80ad6b93 33db xor ebx,ebx
80ad6b95 648a1d51000000 mov bl,fs:[00000051]
80ad6b9c 391d5c99ae80 cmp [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6ba2 7414 jz nt!KiTrap02+0xc0 (80ad6bb8)
80ad6ba4 8d055899ae80 lea eax,[nt!KiBiosReenteredAssert+0x27 (80ae9958)]
80ad6baa 50 push eax
80ad6bab 6a00 push 0x0
80ad6bad 8bcc mov ecx,esp
80ad6baf 8bd5 mov edx,ebp
80ad6bb1 e83a32f6ff call nt!KiAcquireQueuedSpinLockCheckForFreeze (80a39df0)
80ad6bb6 eb24 jmp nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bb8 833d6099ae8008 cmp dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)],0x8
80ad6bbf 721b jb nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bc1 7517 jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bc3 803dc0daae8000 cmp byte ptr [nt!KdDebuggerNotPresent (80aedac0)],0x0
80ad6bca 750e jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bcc 803dc1daae8000 cmp byte ptr [nt!KdDebuggerEnabled (80aedac1)],0x0
80ad6bd3 7405 jz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bd5 e83ea2f5ff call nt!KeEnterKernelDebugger (80a30e18)
80ad6bda ebfe jmp nt!KiTrap02+0xe2 (80ad6bda)
80ad6bdc 891d5c99ae80 mov [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6be2 ff056099ae80 inc dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
80ad6bf8 c7055c99ae80ffffffff mov dword ptr [nt!KiBiosReenteredAssert+0x2b (80ae995c)],0xffffffff
80ad6c02 8bcc mov ecx,esp
80ad6c04 e8a7e2ffff call nt!KeReleaseQueuedSpinLockFromDpcLevel (80ad4eb0)
80ad6c09 83c408 add esp,0x8
80ad6c0c 64a140000000 mov eax,fs:[00000040]
80ad6c12 66833858 cmp word ptr [eax],0x58
80ad6c16 742a jz nt!KiTrap02+0x14a (80ad6c42)
80ad6c18 81c48c000000 add esp,0x8c
80ad6c1e 648f0540000000 pop fs:[00000040]
80ad6c25 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6c2c 8d4128 lea eax,[ecx+0x28]
80ad6c2f c640058b mov byte ptr [eax+0x5],0x8b
80ad6c33 9c pushfd
80ad6c34 810c2400400000 or dword ptr [esp],0x4000
80ad6c3b 9d popfd
80ad6c3c cf iretd
80ad6c3d e9b6feffff jmp nt!KiTrap02 (80ad6af8)
80ad6c42 b802000000 mov eax,0x2
80ad6c47 e9a02a0000 jmp nt!KiSystemFatalException (80ad96ec)





Hi Slobodan,
the NMI is implemented in XP and Win2003 via a TaskGate (TSS 58) in the IDT.
This must be done, because in the kernel the SS and ESP are not set with the
non interruptable LSS statement but with CLI and seperate MOV statements.

The HAL!HalHandleNMI routine ends up with a infinite loop
806CC03D jmp 806CC03D (I think to stop system).

When I replace the call to HalHandleNMI with NOPs and correct the stack
(lots of values are pushed onto the stack before the call), XP dies with a
black screen. If I do the same with Win2003 it works.
The implementaion with TSS 58 in XP and Win2003 is nearly identical, the
only difference is some extra code in Win2003 at the beginning of the
NMI-routine (where the EIP of TSS 58 points to):

mov eax,[0xFFDFF040]
mov ecx,[0xFFDFF124]
mov edi,[ECX+0x44]
mov ecx,[edi+0x18]
mov [eax+0x1c],ecx
mov cx,[edi+0x30]
mov [eax+0x66],cx
mov ecx,[edi+0x20]
test ecx,ecx
jz LABEL1
mov cx,0x0048
LABEL1:
mov[eax+0x60],cx

For me it looks a little bit like XP is not intended to continue after an
NMI ?

At the moment I am on holidays, so I can't execute real test until January.
Thanks,
Burkhard

:

Hi Burkhard,

nt!KiTrap02
nt!_imp__HalHandleNMI

80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]

80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

For test NOP call and jnz instruction bytes (as you probably know there is more than two bytes to change to NOP). And it might
work.
Please let us know.

If this work you have two possible paths.
1. Obtain documentation from MS about writing hal.dll and reimplement HalHandleNMI functionality.
2. Make a simple driver that will patch these bytes in ntoskrnl.exe during the XP init phase.

Regards,
Slobodan


I have got a special hardware on which I want to run XP embedded. Under some
circumstances (e.g. powerfail) there are NMIs generated.
Is there any way to handle this NMI simular to Win2003 ?

With Win2003 there you can use KeRegisterNmiCallback to install your own
handler and it works fine.

On XP the only thing I achieve is a bluescreen with **Hardware
Malfunction**. Even if I NOP out the HalHandleNMI call the system is dead
after an NMI.

thanks
Burkhard
 
Hi Slobodan,
I use XP SP1 nonchecked and it looks quite different (after all the pushing):
the lines with asterisk are not present, but I thing most of stuff is for
checking in checked kernel
....
80ad6b8e ff703c push dword ptr [eax+0x3c]
80ad6b91 8bec mov ebp,esp
*80ad6b93 33db xor ebx,ebx
*80ad6b95 648a1d51000000 mov bl,fs:[00000051]
*80ad6b9c 391d5c99ae80 cmp [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
*80ad6ba2 7414 jz nt!KiTrap02+0xc0 (80ad6bb8)
*80ad6ba4 8d055899ae80 lea eax,[nt!KiBiosReenteredAssert+0x27 (80ae9958)]
*80ad6baa 50 push eax
*80ad6bab 6a00 push 0x0
*80ad6bad 8bcc mov ecx,esp
*80ad6baf 8bd5 mov edx,ebp
*80ad6bb1 e83a32f6ff call nt!KiAcquireQueuedSpinLockCheckForFreeze (80a39df0)
*80ad6bb6 eb24 jmp nt!KiTrap02+0xe4 (80ad6bdc)
*80ad6bb8 833d6099ae8008 cmp dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)],0x8
*80ad6bbf 721b jb nt!KiTrap02+0xe4 (80ad6bdc)
*80ad6bc1 7517 jnz nt!KiTrap02+0xe2 (80ad6bda)
*80ad6bc3 803dc0daae8000 cmp byte ptr [nt!KdDebuggerNotPresent (80aedac0)],0x0
*80ad6bca 750e jnz nt!KiTrap02+0xe2 (80ad6bda)
*80ad6bcc 803dc1daae8000 cmp byte ptr [nt!KdDebuggerEnabled (80aedac1)],0x0
*80ad6bd3 7405 jz nt!KiTrap02+0xe2 (80ad6bda)
*80ad6bd5 e83ea2f5ff call nt!KeEnterKernelDebugger (80a30e18)
*80ad6bda ebfe jmp nt!KiTrap02+0xe2 (80ad6bda)
*80ad6bdc 891d5c99ae80 mov [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
*80ad6be2 ff056099ae80 inc dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)]
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
*80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)]
*80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
*80ad6bf8 c7055c99ae80ffffffff mov dword ptr [nt!KiBiosReenteredAssert+0x2b
(80ae995c)],0xffffffff
*80ad6c02 8bcc mov ecx,esp
*80ad6c04 e8a7e2ffff call nt!KeReleaseQueuedSpinLockFromDpcLevel (80ad4eb0)
*80ad6c09 83c408 add esp,0x8
*80ad6c0c 64a140000000 mov eax,fs:[00000040]
*80ad6c12 66833858 cmp word ptr [eax],0x58
*80ad6c16 742a jz nt!KiTrap02+0x14a (80ad6c42)
+80ad6c18 81c48c000000 add esp,0x8c ->> add esp,0x94
80ad6c1e 648f0540000000 pop fs:[00000040]
80ad6c25 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6c2c 8d4128 lea eax,[ecx+0x28]
80ad6c2f c640058b mov byte ptr [eax+0x5],0x8b
80ad6c33 9c pushfd
80ad6c34 810c2400400000 or dword ptr [esp],0x4000
80ad6c3b 9d popfd
80ad6c3c cf iretd

The iretd at the end of nt!KiTrap02 I know, what confuses me is that
HalHandleNMI has no way out I can see and that in nt!KiTrap02 there is no
(official) way to bypass the call to HalHandleNMI .

For my next test I will install the XP SP2 checked kernel, so that we are
talking about the same thing.

Thanks a lot so far,
Burkhard

Slobodan Brcin (eMVP) said:
Hi Burkhard,

You are lucky that I'm deep in XP kernel asm code analysis at the moment.

Forget analyzing XP code without at least symbols present.
Let us use following code for analysis: (This is Checked XP SP2 kernel with symbols present) this code in NMI handler forget about
registers, etc

Find this:
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

As you can see if you can make it to pass trough this there is iretd available at the end.

Best regards,
Slobodan


nt!KiTrap02:
80ad6af8 fa cli
80ad6af9 64ff3540000000 push dword ptr fs:[00000040]
80ad6b00 64a13c000000 mov eax,fs:[0000003c]
80ad6b06 8a685f mov ch,[eax+0x5f]
80ad6b09 8a485c mov cl,[eax+0x5c]
80ad6b0c c1e110 shl ecx,0x10
80ad6b0f 668b485a mov cx,[eax+0x5a]
80ad6b13 64890d40000000 mov fs:[00000040],ecx
80ad6b1a 9c pushfd
80ad6b1b 812424ffbfffff and dword ptr [esp],0xffffbfff
80ad6b22 9d popfd
80ad6b23 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6b2a 8d4158 lea eax,[ecx+0x58]
80ad6b2d c6400589 mov byte ptr [eax+0x5],0x89
80ad6b31 8b0424 mov eax,[esp]
80ad6b34 6a00 push 0x0
80ad6b36 6a00 push 0x0
80ad6b38 6a00 push 0x0
80ad6b3a 6a00 push 0x0
80ad6b3c ff7050 push dword ptr [eax+0x50]
80ad6b3f ff7038 push dword ptr [eax+0x38]
80ad6b42 ff7024 push dword ptr [eax+0x24]
80ad6b45 ff704c push dword ptr [eax+0x4c]
80ad6b48 ff7020 push dword ptr [eax+0x20]
80ad6b4b 6a00 push 0x0
80ad6b4d ff703c push dword ptr [eax+0x3c]
80ad6b50 ff7034 push dword ptr [eax+0x34]
80ad6b53 ff7040 push dword ptr [eax+0x40]
80ad6b56 ff7044 push dword ptr [eax+0x44]
80ad6b59 ff7058 push dword ptr [eax+0x58]
80ad6b5c 64ff3500000000 push dword ptr fs:[00000000]
80ad6b63 6aff push 0xff
80ad6b65 ff7028 push dword ptr [eax+0x28]
80ad6b68 ff702c push dword ptr [eax+0x2c]
80ad6b6b ff7030 push dword ptr [eax+0x30]
80ad6b6e ff7054 push dword ptr [eax+0x54]
80ad6b71 ff7048 push dword ptr [eax+0x48]
80ad6b74 ff705c push dword ptr [eax+0x5c]
80ad6b77 6a00 push 0x0
80ad6b79 6a00 push 0x0
80ad6b7b 6a00 push 0x0
80ad6b7d 6a00 push 0x0
80ad6b7f 6a00 push 0x0
80ad6b81 6a00 push 0x0
80ad6b83 6a00 push 0x0
80ad6b85 6a00 push 0x0
80ad6b87 6a00 push 0x0
80ad6b89 6a00 push 0x0
80ad6b8b ff7020 push dword ptr [eax+0x20]
80ad6b8e ff703c push dword ptr [eax+0x3c]
80ad6b91 8bec mov ebp,esp
80ad6b93 33db xor ebx,ebx
80ad6b95 648a1d51000000 mov bl,fs:[00000051]
80ad6b9c 391d5c99ae80 cmp [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6ba2 7414 jz nt!KiTrap02+0xc0 (80ad6bb8)
80ad6ba4 8d055899ae80 lea eax,[nt!KiBiosReenteredAssert+0x27 (80ae9958)]
80ad6baa 50 push eax
80ad6bab 6a00 push 0x0
80ad6bad 8bcc mov ecx,esp
80ad6baf 8bd5 mov edx,ebp
80ad6bb1 e83a32f6ff call nt!KiAcquireQueuedSpinLockCheckForFreeze (80a39df0)
80ad6bb6 eb24 jmp nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bb8 833d6099ae8008 cmp dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)],0x8
80ad6bbf 721b jb nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bc1 7517 jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bc3 803dc0daae8000 cmp byte ptr [nt!KdDebuggerNotPresent (80aedac0)],0x0
80ad6bca 750e jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bcc 803dc1daae8000 cmp byte ptr [nt!KdDebuggerEnabled (80aedac1)],0x0
80ad6bd3 7405 jz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bd5 e83ea2f5ff call nt!KeEnterKernelDebugger (80a30e18)
80ad6bda ebfe jmp nt!KiTrap02+0xe2 (80ad6bda)
80ad6bdc 891d5c99ae80 mov [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6be2 ff056099ae80 inc dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
80ad6bf8 c7055c99ae80ffffffff mov dword ptr [nt!KiBiosReenteredAssert+0x2b (80ae995c)],0xffffffff
80ad6c02 8bcc mov ecx,esp
80ad6c04 e8a7e2ffff call nt!KeReleaseQueuedSpinLockFromDpcLevel (80ad4eb0)
80ad6c09 83c408 add esp,0x8
80ad6c0c 64a140000000 mov eax,fs:[00000040]
80ad6c12 66833858 cmp word ptr [eax],0x58
80ad6c16 742a jz nt!KiTrap02+0x14a (80ad6c42)
80ad6c18 81c48c000000 add esp,0x8c
80ad6c1e 648f0540000000 pop fs:[00000040]
80ad6c25 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6c2c 8d4128 lea eax,[ecx+0x28]
80ad6c2f c640058b mov byte ptr [eax+0x5],0x8b
80ad6c33 9c pushfd
80ad6c34 810c2400400000 or dword ptr [esp],0x4000
80ad6c3b 9d popfd
80ad6c3c cf iretd
80ad6c3d e9b6feffff jmp nt!KiTrap02 (80ad6af8)
80ad6c42 b802000000 mov eax,0x2
80ad6c47 e9a02a0000 jmp nt!KiSystemFatalException (80ad96ec)





bcpauli said:
Hi Slobodan,
the NMI is implemented in XP and Win2003 via a TaskGate (TSS 58) in the IDT.
This must be done, because in the kernel the SS and ESP are not set with the
non interruptable LSS statement but with CLI and seperate MOV statements.

The HAL!HalHandleNMI routine ends up with a infinite loop
806CC03D jmp 806CC03D (I think to stop system).

When I replace the call to HalHandleNMI with NOPs and correct the stack
(lots of values are pushed onto the stack before the call), XP dies with a
black screen. If I do the same with Win2003 it works.
The implementaion with TSS 58 in XP and Win2003 is nearly identical, the
only difference is some extra code in Win2003 at the beginning of the
NMI-routine (where the EIP of TSS 58 points to):

mov eax,[0xFFDFF040]
mov ecx,[0xFFDFF124]
mov edi,[ECX+0x44]
mov ecx,[edi+0x18]
mov [eax+0x1c],ecx
mov cx,[edi+0x30]
mov [eax+0x66],cx
mov ecx,[edi+0x20]
test ecx,ecx
jz LABEL1
mov cx,0x0048
LABEL1:
mov[eax+0x60],cx

For me it looks a little bit like XP is not intended to continue after an
NMI ?

At the moment I am on holidays, so I can't execute real test until January.
Thanks,
Burkhard

Slobodan Brcin (eMVP) said:
Hi Burkhard,

nt!KiTrap02
nt!_imp__HalHandleNMI

80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]

80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

For test NOP call and jnz instruction bytes (as you probably know there is more than two bytes to change to NOP). And it might work.
Please let us know.

If this work you have two possible paths.
1. Obtain documentation from MS about writing hal.dll and reimplement HalHandleNMI functionality.
2. Make a simple driver that will patch these bytes in ntoskrnl.exe during the XP init phase.

Regards,
Slobodan


I have got a special hardware on which I want to run XP embedded. Under some
circumstances (e.g. powerfail) there are NMIs generated.
Is there any way to handle this NMI simular to Win2003 ?

With Win2003 there you can use KeRegisterNmiCallback to install your own
handler and it works fine.

On XP the only thing I achieve is a bluescreen with **Hardware
Malfunction**. Even if I NOP out the HalHandleNMI call the system is dead
after an NMI.

thanks
Burkhard
 
Hi Burkhard,

As I can see from your post SP2 and SP1 are pretty much the same in regards how they handle call to HAL.

In your case you want to nop following bytes and that is only what is needed:
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

Following is only precautionary check that should never happen:
*80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)]
*80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)


Legal way for handling HalHandleNMI would be for you to obtain rights and documentation from MS and to write your own HAL:.
In mean time :-) try nop-ing above 8 bytes that push and make a call from kernel debugger before NMI happens and see what happen.
If this works you can make your driver that will paths ntoskrnl.exe during the runtime.

Regards,
Slobodan


bcpauli said:
Hi Slobodan,
I use XP SP1 nonchecked and it looks quite different (after all the pushing):
the lines with asterisk are not present, but I thing most of stuff is for
checking in checked kernel
...
80ad6b8e ff703c push dword ptr [eax+0x3c]
80ad6b91 8bec mov ebp,esp
*80ad6b93 33db xor ebx,ebx
*80ad6b95 648a1d51000000 mov bl,fs:[00000051]
*80ad6b9c 391d5c99ae80 cmp [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
*80ad6ba2 7414 jz nt!KiTrap02+0xc0 (80ad6bb8)
*80ad6ba4 8d055899ae80 lea eax,[nt!KiBiosReenteredAssert+0x27 (80ae9958)]
*80ad6baa 50 push eax
*80ad6bab 6a00 push 0x0
*80ad6bad 8bcc mov ecx,esp
*80ad6baf 8bd5 mov edx,ebp
*80ad6bb1 e83a32f6ff call nt!KiAcquireQueuedSpinLockCheckForFreeze (80a39df0)
*80ad6bb6 eb24 jmp nt!KiTrap02+0xe4 (80ad6bdc)
*80ad6bb8 833d6099ae8008 cmp dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)],0x8
*80ad6bbf 721b jb nt!KiTrap02+0xe4 (80ad6bdc)
*80ad6bc1 7517 jnz nt!KiTrap02+0xe2 (80ad6bda)
*80ad6bc3 803dc0daae8000 cmp byte ptr [nt!KdDebuggerNotPresent (80aedac0)],0x0
*80ad6bca 750e jnz nt!KiTrap02+0xe2 (80ad6bda)
*80ad6bcc 803dc1daae8000 cmp byte ptr [nt!KdDebuggerEnabled (80aedac1)],0x0
*80ad6bd3 7405 jz nt!KiTrap02+0xe2 (80ad6bda)
*80ad6bd5 e83ea2f5ff call nt!KeEnterKernelDebugger (80a30e18)
*80ad6bda ebfe jmp nt!KiTrap02+0xe2 (80ad6bda)
*80ad6bdc 891d5c99ae80 mov [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
*80ad6be2 ff056099ae80 inc dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)]
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
*80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)]
*80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
*80ad6bf8 c7055c99ae80ffffffff mov dword ptr [nt!KiBiosReenteredAssert+0x2b
(80ae995c)],0xffffffff
*80ad6c02 8bcc mov ecx,esp
*80ad6c04 e8a7e2ffff call nt!KeReleaseQueuedSpinLockFromDpcLevel (80ad4eb0)
*80ad6c09 83c408 add esp,0x8
*80ad6c0c 64a140000000 mov eax,fs:[00000040]
*80ad6c12 66833858 cmp word ptr [eax],0x58
*80ad6c16 742a jz nt!KiTrap02+0x14a (80ad6c42)
+80ad6c18 81c48c000000 add esp,0x8c ->> add esp,0x94
80ad6c1e 648f0540000000 pop fs:[00000040]
80ad6c25 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6c2c 8d4128 lea eax,[ecx+0x28]
80ad6c2f c640058b mov byte ptr [eax+0x5],0x8b
80ad6c33 9c pushfd
80ad6c34 810c2400400000 or dword ptr [esp],0x4000
80ad6c3b 9d popfd
80ad6c3c cf iretd

The iretd at the end of nt!KiTrap02 I know, what confuses me is that
HalHandleNMI has no way out I can see and that in nt!KiTrap02 there is no
(official) way to bypass the call to HalHandleNMI .

For my next test I will install the XP SP2 checked kernel, so that we are
talking about the same thing.

Thanks a lot so far,
Burkhard

Slobodan Brcin (eMVP) said:
Hi Burkhard,

You are lucky that I'm deep in XP kernel asm code analysis at the moment.

Forget analyzing XP code without at least symbols present.
Let us use following code for analysis: (This is Checked XP SP2 kernel with symbols present) this code in NMI handler forget about
registers, etc

Find this:
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

As you can see if you can make it to pass trough this there is iretd available at the end.

Best regards,
Slobodan


nt!KiTrap02:
80ad6af8 fa cli
80ad6af9 64ff3540000000 push dword ptr fs:[00000040]
80ad6b00 64a13c000000 mov eax,fs:[0000003c]
80ad6b06 8a685f mov ch,[eax+0x5f]
80ad6b09 8a485c mov cl,[eax+0x5c]
80ad6b0c c1e110 shl ecx,0x10
80ad6b0f 668b485a mov cx,[eax+0x5a]
80ad6b13 64890d40000000 mov fs:[00000040],ecx
80ad6b1a 9c pushfd
80ad6b1b 812424ffbfffff and dword ptr [esp],0xffffbfff
80ad6b22 9d popfd
80ad6b23 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6b2a 8d4158 lea eax,[ecx+0x58]
80ad6b2d c6400589 mov byte ptr [eax+0x5],0x89
80ad6b31 8b0424 mov eax,[esp]
80ad6b34 6a00 push 0x0
80ad6b36 6a00 push 0x0
80ad6b38 6a00 push 0x0
80ad6b3a 6a00 push 0x0
80ad6b3c ff7050 push dword ptr [eax+0x50]
80ad6b3f ff7038 push dword ptr [eax+0x38]
80ad6b42 ff7024 push dword ptr [eax+0x24]
80ad6b45 ff704c push dword ptr [eax+0x4c]
80ad6b48 ff7020 push dword ptr [eax+0x20]
80ad6b4b 6a00 push 0x0
80ad6b4d ff703c push dword ptr [eax+0x3c]
80ad6b50 ff7034 push dword ptr [eax+0x34]
80ad6b53 ff7040 push dword ptr [eax+0x40]
80ad6b56 ff7044 push dword ptr [eax+0x44]
80ad6b59 ff7058 push dword ptr [eax+0x58]
80ad6b5c 64ff3500000000 push dword ptr fs:[00000000]
80ad6b63 6aff push 0xff
80ad6b65 ff7028 push dword ptr [eax+0x28]
80ad6b68 ff702c push dword ptr [eax+0x2c]
80ad6b6b ff7030 push dword ptr [eax+0x30]
80ad6b6e ff7054 push dword ptr [eax+0x54]
80ad6b71 ff7048 push dword ptr [eax+0x48]
80ad6b74 ff705c push dword ptr [eax+0x5c]
80ad6b77 6a00 push 0x0
80ad6b79 6a00 push 0x0
80ad6b7b 6a00 push 0x0
80ad6b7d 6a00 push 0x0
80ad6b7f 6a00 push 0x0
80ad6b81 6a00 push 0x0
80ad6b83 6a00 push 0x0
80ad6b85 6a00 push 0x0
80ad6b87 6a00 push 0x0
80ad6b89 6a00 push 0x0
80ad6b8b ff7020 push dword ptr [eax+0x20]
80ad6b8e ff703c push dword ptr [eax+0x3c]
80ad6b91 8bec mov ebp,esp
80ad6b93 33db xor ebx,ebx
80ad6b95 648a1d51000000 mov bl,fs:[00000051]
80ad6b9c 391d5c99ae80 cmp [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6ba2 7414 jz nt!KiTrap02+0xc0 (80ad6bb8)
80ad6ba4 8d055899ae80 lea eax,[nt!KiBiosReenteredAssert+0x27 (80ae9958)]
80ad6baa 50 push eax
80ad6bab 6a00 push 0x0
80ad6bad 8bcc mov ecx,esp
80ad6baf 8bd5 mov edx,ebp
80ad6bb1 e83a32f6ff call nt!KiAcquireQueuedSpinLockCheckForFreeze (80a39df0)
80ad6bb6 eb24 jmp nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bb8 833d6099ae8008 cmp dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)],0x8
80ad6bbf 721b jb nt!KiTrap02+0xe4 (80ad6bdc)
80ad6bc1 7517 jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bc3 803dc0daae8000 cmp byte ptr [nt!KdDebuggerNotPresent (80aedac0)],0x0
80ad6bca 750e jnz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bcc 803dc1daae8000 cmp byte ptr [nt!KdDebuggerEnabled (80aedac1)],0x0
80ad6bd3 7405 jz nt!KiTrap02+0xe2 (80ad6bda)
80ad6bd5 e83ea2f5ff call nt!KeEnterKernelDebugger (80a30e18)
80ad6bda ebfe jmp nt!KiTrap02+0xe2 (80ad6bda)
80ad6bdc 891d5c99ae80 mov [nt!KiBiosReenteredAssert+0x2b (80ae995c)],ebx
80ad6be2 ff056099ae80 inc dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]
80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]
80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)
80ad6bf8 c7055c99ae80ffffffff mov dword ptr [nt!KiBiosReenteredAssert+0x2b (80ae995c)],0xffffffff
80ad6c02 8bcc mov ecx,esp
80ad6c04 e8a7e2ffff call nt!KeReleaseQueuedSpinLockFromDpcLevel (80ad4eb0)
80ad6c09 83c408 add esp,0x8
80ad6c0c 64a140000000 mov eax,fs:[00000040]
80ad6c12 66833858 cmp word ptr [eax],0x58
80ad6c16 742a jz nt!KiTrap02+0x14a (80ad6c42)
80ad6c18 81c48c000000 add esp,0x8c
80ad6c1e 648f0540000000 pop fs:[00000040]
80ad6c25 648b0d3c000000 mov ecx,fs:[0000003c]
80ad6c2c 8d4128 lea eax,[ecx+0x28]
80ad6c2f c640058b mov byte ptr [eax+0x5],0x8b
80ad6c33 9c pushfd
80ad6c34 810c2400400000 or dword ptr [esp],0x4000
80ad6c3b 9d popfd
80ad6c3c cf iretd
80ad6c3d e9b6feffff jmp nt!KiTrap02 (80ad6af8)
80ad6c42 b802000000 mov eax,0x2
80ad6c47 e9a02a0000 jmp nt!KiSystemFatalException (80ad96ec)





bcpauli said:
Hi Slobodan,
the NMI is implemented in XP and Win2003 via a TaskGate (TSS 58) in the IDT.
This must be done, because in the kernel the SS and ESP are not set with the
non interruptable LSS statement but with CLI and seperate MOV statements.

The HAL!HalHandleNMI routine ends up with a infinite loop
806CC03D jmp 806CC03D (I think to stop system).

When I replace the call to HalHandleNMI with NOPs and correct the stack
(lots of values are pushed onto the stack before the call), XP dies with a
black screen. If I do the same with Win2003 it works.
The implementaion with TSS 58 in XP and Win2003 is nearly identical, the
only difference is some extra code in Win2003 at the beginning of the
NMI-routine (where the EIP of TSS 58 points to):

mov eax,[0xFFDFF040]
mov ecx,[0xFFDFF124]
mov edi,[ECX+0x44]
mov ecx,[edi+0x18]
mov [eax+0x1c],ecx
mov cx,[edi+0x30]
mov [eax+0x66],cx
mov ecx,[edi+0x20]
test ecx,ecx
jz LABEL1
mov cx,0x0048
LABEL1:
mov[eax+0x60],cx

For me it looks a little bit like XP is not intended to continue after an
NMI ?

At the moment I am on holidays, so I can't execute real test until January.
Thanks,
Burkhard

:

Hi Burkhard,

nt!KiTrap02
nt!_imp__HalHandleNMI

80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f (80ae9960)]

80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)

For test NOP call and jnz instruction bytes (as you probably know there is more than two bytes to change to NOP). And it
might
work.
Please let us know.

If this work you have two possible paths.
1. Obtain documentation from MS about writing hal.dll and reimplement HalHandleNMI functionality.
2. Make a simple driver that will patch these bytes in ntoskrnl.exe during the XP init phase.

Regards,
Slobodan


I have got a special hardware on which I want to run XP embedded. Under some
circumstances (e.g. powerfail) there are NMIs generated.
Is there any way to handle this NMI simular to Win2003 ?

With Win2003 there you can use KeRegisterNmiCallback to install your own
handler and it works fine.

On XP the only thing I achieve is a bluescreen with **Hardware
Malfunction**. Even if I NOP out the HalHandleNMI call the system is dead
after an NMI.

thanks
Burkhard
 
Konstantin,

I'm using W2003 DDK so it is accurate for this function.
Interesting for XP DDK is that although this is documented there is no function in kernel and header files. But there are myriads of
other functions that are not documented but exist :-)

Regards,
Slobodan
 
Konstantin & Slobodan,
I used the function KeRegisterNmiCallback to install my device driver for
handling NMIs and it worked perfekt on Windows Server 2003 (but it is not the
right operating system for an embedded device). With XP the headers and
ntoskrnl.exe don't export the function, the device dreiver fails to load (of
course).
With XP in nt!KiTrap02 the loop is missing where the handler searches for
registered callbacks and calls HALHandleNmi only when the callbacks return
FALSE.
And I think it also not hidden in the XP ntoskrnl, because the
KeRegisterNmiCallback allocates nonpagedpool memory with the tag KNMI
(KernelNMI ?). I searched the whole kernel for this tag, but could find it.


I think for an embedded OS it is not very good to offer no possibility for
handling NMIs.

Regards,
Burkhard
 
Burkhard,

I agree with Slobodan.
Embedded limitations of XPe are mostly due to the fact that XPe binaries are XP Pro binaries.
XP Pro, certainly, has not been developed specifically for embedded applications.

Anyway, you still have a couple things to try (the dynamic hack of ntkrnl.exe and KeRegisterBugCheckCallback approach) if you have
time.

Or switch to another embedded OS. If you have some "windows-based" applications you may want to take a look at Windows CE.

Konstantin
 
Hi Slobodan,
my holidays are finished and I am back at work.
Here the results of my NOP test:
If I NOP the mentioned bytes in XP the system dies with black screen when i
generate an NMI. :-(

If I NOP the according bytes in Windows Server 2003 it keeps working fine
when i generate an NMI.

Any more idea what the reason could be?

Regards,
Burkhard




Slobodan Brcin (eMVP) said:
Hi Burkhard,

As I can see from your post SP2 and SP1 are pretty much the same in regards how they handle call to HAL.

In your case you want to nop following bytes and that is only what is needed:
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

Following is only precautionary check that should never happen:
*80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)]
*80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)


Legal way for handling HalHandleNMI would be for you to obtain rights and documentation from MS and to write your own HAL:.
In mean time :-) try nop-ing above 8 bytes that push and make a call from kernel debugger before NMI happens and see what happen.
If this works you can make your driver that will paths ntoskrnl.exe during the runtime.

Regards,
Slobodan
 
Hi Burkhard,

No more ideas :-(
But triple check that you have nop-ed all stack push functions to that your return stack is ok.
You might even want to trace it return and see where is hang.

Regards,
Slobodan


bcpauli said:
Hi Slobodan,
my holidays are finished and I am back at work.
Here the results of my NOP test:
If I NOP the mentioned bytes in XP the system dies with black screen when i
generate an NMI. :-(

If I NOP the according bytes in Windows Server 2003 it keeps working fine
when i generate an NMI.

Any more idea what the reason could be?

Regards,
Burkhard




Slobodan Brcin (eMVP) said:
Hi Burkhard,

As I can see from your post SP2 and SP1 are pretty much the same in regards how they handle call to HAL.

In your case you want to nop following bytes and that is only what is needed:
80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

Following is only precautionary check that should never happen:
*80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)]
*80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)


Legal way for handling HalHandleNMI would be for you to obtain rights and documentation from MS and to write your own HAL:.
In mean time :-) try nop-ing above 8 bytes that push and make a call from kernel debugger before NMI happens and see what happen.
If this works you can make your driver that will paths ntoskrnl.exe during the runtime.

Regards,
Slobodan
 
Hi Slobodan,
just found the mistake in the XP kernel, now it works with the NOP-ed routine.

As I was assuming the nt!KiTrap02-routine was never really intended to be
run twice.

The NMI is handled via a TaskGate and not via an InterruptGate as normal
interrupts.
So the state of the task is stored in the corrosponding TSS (TSS 28 for
normal XP, TSS 58 for nt!KiTrap02).

When the first NMI is happening and the NOP-ed nt!KiTrap02 comes to the
iretd (you remember the Hal!HandleNMI routine never cames back, but results
in an endless loop), the iretd causes again a CPU-TaskSwitch (back from TSS
58 to TSS 28) and for the returning task the state is stored to TSS 58.
The stored EIP points now to the instruction behind the iretd. So when a
second NMI occures, the taskGate in the IDT jumps behind the iretd an
executes some interesting code, but not the nt!KiTrap02 again.

To solve this problem after the iretd must be a jmp to nt!KiTrap02!! This is
done in Windows Server 2003 but not in Windows XP !!

After patching a jmp nt!KiTrap02 behind the iretd (I destroyed something I
don't know and didn't use unobviously) I am surviving any number of NMIs.

Based on this now, I can install my own handler, fill the TSS 58 according
to MyHandler, MyStack and so on and I am confident that I will work as I want.

Thanks for yous help,
Burkhard

Slobodan Brcin (eMVP) said:
Hi Burkhard,

No more ideas :-(
But triple check that you have nop-ed all stack push functions to that your return stack is ok.
You might even want to trace it return and see where is hang.

Regards,
Slobodan


bcpauli said:
Hi Slobodan,
my holidays are finished and I am back at work.
Here the results of my NOP test:
If I NOP the mentioned bytes in XP the system dies with black screen when i
generate an NMI. :-(

If I NOP the according bytes in Windows Server 2003 it keeps working fine
when i generate an NMI.

Any more idea what the reason could be?

Regards,
Burkhard




Slobodan Brcin (eMVP) said:
Hi Burkhard,

As I can see from your post SP2 and SP1 are pretty much the same in regards how they handle call to HAL.

In your case you want to nop following bytes and that is only what is needed:

80ad6be8 6a00 push 0x0
80ad6bea ff158c30a080 call dword ptr [nt!_imp__HalHandleNMI (80a0308c)]

Following is only precautionary check that should never happen:
*80ad6bf0 ff0d6099ae80 dec dword ptr [nt!KiBiosReenteredAssert+0x2f
(80ae9960)]
*80ad6bf6 754a jnz nt!KiTrap02+0x14a (80ad6c42)


Legal way for handling HalHandleNMI would be for you to obtain rights and documentation from MS and to write your own HAL:.
In mean time :-) try nop-ing above 8 bytes that push and make a call from kernel debugger before NMI happens and see what happen.
If this works you can make your driver that will paths ntoskrnl.exe during the runtime.

Regards,
Slobodan
 
Back
Top