> This project is an embedded x86 pc/104 design. I am in need of rebooting
> the system within my software.
>
> I understand it's not safe -- but I'm rebooting the system; who cares.
>
> Not being able to do it doesn't make sense -- Any DPMI experts out there
> that can help?
I have some DPMI code that I use in my disk-tool (DFSee) that does
that. I have only tested it with the DOS32 and CauseWay extenders,
but these are pretty much compatible with DOS4GW
It is using DPMI calls, and there is even an extra call that would flush
a standard hooked disk-cache. You can leave that first part out if
you are sure there will be no disk chaching.
The code fragment below should almost be compilable ;-)
The TxPrint() is just a smart wrapper arround printf()
other macros are either supplied, or come with OW
(best to use a fixed font for readability)
+++++++++ DOS reboot from protected mode ++++++
#define DOS_REVECT_OFF 0x0000 // offset DOS reboot vector
#define DOS_REVECT_SEG 0xffff // segment DOS reboot vector
#define TXDX_DPMI 0x31
#define TXDX_DPMI_RMINT 0x0300
#define TXDX_DPMI_RMFAR 0x0301
typedef struct txdx_rminfo // DOS extender real-mode data
{
long edi;
long esi;
long ebp;
long reserved;
long ebx;
long edx;
long ecx;
long eax;
short flags;
short es;
short ds;
short fs;
short gs;
short ip;
short cs;
short sp;
short ss;
} TXDX_RMINFO; // end of struct "tpdx_rminfo"
// Execute a DPMI call
#define txDpmiCall(r,s) int386x( TXDX_DPMI,r,r,s);
union REGS regs;
struct SREGS sreg;
TXDX_RMINFO txdx_rmi;
TxPrint("in progress ...\n");
TxPrint("Flushing the filesystem, please wait ...\n");
memset( ®s, 0, sizeof(regs));
memset( &sreg, 0, sizeof(sreg));
memset( &txdx_rmi, 0, sizeof(txdx_rmi));
txdx_rmi.eax = 0x0d00; // Reset disk, usually hooked
// by cache-programs ...
regs.w.ax = TXDX_DPMI_RMINT; // simulate realmode INT
regs.h.bl = 0x21; // DOS interrupt 21
regs.x.edi = FP_OFF( &txdx_rmi); // real mode register struct
sreg.es = FP_SEG( &txdx_rmi);
txDpmiCall( ®s, &sreg);
TxSleep( 3000); // busywait, 3 seconds
memset( ®s, 0, sizeof(regs));
memset( &sreg, 0, sizeof(sreg));
memset( &txdx_rmi, 0, sizeof(txdx_rmi));
txdx_rmi.cs = (short) DOS_REVECT_SEG; // CS:IP for reboot vector
txdx_rmi.ip = (short) DOS_REVECT_OFF;
regs.w.ax = TXDX_DPMI_RMFAR; // simulate realmode FAR call
regs.x.edi = FP_OFF( &txdx_rmi); // real mode register struct
sreg.es = FP_SEG( &txdx_rmi);
txDpmiCall( ®s, &sreg); // should not return :-)
+++++++++
--
Jan van Wijk; Author of DFSee: http://www.dfsee.com
Does the pc104 board have the 8742 keyboard controller embedded in the ASIC?
If so, you should be able to reboot using the following instructions:
http://www.faqs.org/faqs/msdos-programmer-faq/part4/section-16.html
Carl
I understand it's not safe -- but I'm rebooting the system; who cares.
Not being able to do it doesn't make sense -- Any DPMI experts out there
that can help?
"Hans-Bernhard Broeker" <bro...@physik.rwth-aachen.de> wrote in message
news:d4r10a$9uj$2...@www1.scitechsoft.com...
> Greg Engle wrote:
>> Anyone know how to reboot in dos while in protected mode using DOS4GW?
>
> The best answer may well be: don't do that. Resetting the system from
> inside a running DOS program can be unsafe enough --- doing it inside a
> program that is in turn running inside a DOS extender (like DOS4GW) is
> practically begging for trouble.
>
> Unless there's a documented API call to DOS4GW that closes your app
> properly, then resets the system, odds are you can't do it.
Thanks
The best answer may well be: don't do that. Resetting the system from
>This project is an embedded x86 pc/104 design. I am in need of rebooting
>the system within my software.
>
>I understand it's not safe -- but I'm rebooting the system; who cares.
>
>Not being able to do it doesn't make sense -- Any DPMI experts out there
>that can help?
I've not kept track, but the original BIOSes had a boot entry point at
address 0xFFFF0 or some such. Can't you switch to real (16 bit) mode and
jump there? I'm sure an x86 compatible chip will have a defined
'start-execution-at-reset' address.
Mat Nieuwenhoven
Any other suggestions?
Thanks.
"Jan van Wijk" <jvw.n...@dfsee.com> wrote in message
news:W1d6fUB5m4qH-pn2-sFJsUmVZOzJV@merlin...
Don't the PC104 board have a watchdog?
I normally reboot my embedded systems using this watchdog, also, in case
it fails I add the following (notice that I'm running at ring 0 level)
and this code is placed in a 16-bit segment:
;try to reset using keyboard controller
mov al,0FEh
out 64h,al
mov cx,255
@@wait_reset: loop @@wait_reset
; ---
;try to reset using triple fault
lidt fword ptr cs:_null_idtr_
int 3
; ---
;try to reset jumping to BIOS reset
jmp cs:[__boot__]
__boot__ label dword
dw 0FFF0h
dw 0F000h
; ---
_null_idtr_ dw 0
dd 0
Never had any problem.
Regards.
On Fri, 29 Apr 2005 12:28:11 UTC, "Greg Engle" <gen...@harringtonsignal.com> wrote:
> I've tried this code and int386x returns instead of rebooting. I've also
> tried taking out the disk-caching code and I get the same results.
OK, too bad.
Assuming DOS4GW does its thing allright, I guess the BIOS on that board
does not implement the reboot-vector ...
> Any other suggestions?
No, not really, but I noticed some others have :-)
Regards, JvW
If the FFFF:0000 vector stills appeals to you (and it is considered one of
the most universal reboot methods), you might try adding an instruction to
place a WORD value of zero at 40h:72h, aka linear address 472h. PCs (used
to) check that location to determine whether to cold or warm boot when the
FFFF vector was hit. According to the outdated but still generally
definitive Ralf Brown Interrupt List, various other values at 472h could
leave to nonbooting behavior depending on your BIOS.
That said, strobing pin 0 of the 8042 controller, defined as a reset, is
also supposed to be a reliable means to reboot. The mechanism I've seen
bandied across the years varies slightly from what's been posted to you here
already, perhaps unimportantly so. It goes like this (directly lifted from
one of several sites which posts the identical code):
cli
@@WaitOutReady: ; Busy-wait until 8042 ready for new command
in al,64h ; read 8042 status byte
test al,00000010b ; this bit indicates input buffer full
jnz @@WaitOutReady
mov al,0FEh ; Pulse "reset" = 8042 pin 0
out 64h,al ; The PC will reboot now
Of course, this is best done by placing the code in real mode memory and
calling down to it to avoid ring protection and possible memory re-mapping
issues.
have u looked at this?
"Greg Engle" <gen...@harringtonsignal.com> wrote in message
news:d4qv52$92e$1...@www1.scitechsoft.com...
Nice code but I thought I could simply press RESET button :-) :-)
_idtr df 0
_gdtr df 0
cli
lidt _idtr
lgdt _gdtr
int 01 ;this should reboot the machine
translating this to C should be no problem for you.
----------------------------------------------------------------------------
----------------------------------------------------------------------------
----------------------------------------------------------------------------
In case your version runs clients in ring 3, here is a full MASM program which
works for clients running in this level
;*** manipulate IDT directly, jump in ring 0 and cause a triple fault ***
.386p
.MODEL FLAT,stdcall
option casemap:none
BINT equ 5
.CODE
_idtr df 0
_gdtr df 0
msg1 db "no flat ring 0 code selector found",13,10,'$'
intproc proc
cli
lidt _idtr
lgdt _gdtr
int 01 ;this should reboot the machine
intproc endp
main proc c
local idt:fword
local gdt:fword
local r0cs:word
;------------------------------- find flat ring 0 cs selector
sgdt gdt
mov edx,dword ptr gdt+2
mov cx,word ptr gdt+0
inc cx
mov ebx,0
.while (cx)
mov ah,[edx+ebx+7]
mov al,[edx+ebx+4]
shl eax,16
mov ax,[edx+ebx+2]
.if (eax == 0)
mov ax,[edx+ebx+5]
and ax,0EFFFh
.break .if (ax == 0CF9Bh)
.endif
sub cx,8
add bx,8
.endw
.if (ax != 0CF9Bh)
mov edx, offset msg1
mov ah,9
int 21h
mov ax,4c00h
int 21h
.endif
mov r0cs,bx
;------------------------------- now modify INT 05 in IDT
sidt idt
mov eax,dword ptr idt+2
add eax,BINT*8
mov ecx,intproc
cli
mov [eax+0],cx ;LOWORD(offset)
shr ecx,16
mov [eax+6],cx ;HIWORD(offset)
and byte ptr [eax+4],09Fh ;set attribute
mov cx,r0cs
mov [eax+2],cx ;selector value
int BINT
main endp
END main
----------------------------------------------------------------------------
----------------------------------------------------------------------------
----------------------------------------------------------------------------
Yes, if you have one available :-)
main()
{
_asm {
cli
mov al,0Fh
out 70h,al
mov al,0
out 71h,al
mov word ptr ds:[472],0
push 0
push 0
lidt fword ptr [esp]
lgdt fword ptr [esp]
int 01
}
return 0;
}
> Wow !!
>
> Nice code but I thought I could simply press RESET button :-) :-)
So print a message telling the operator to press it... ;-)
[Of course, you would need a ream of doc telling the operator where to
find said reset button on various machines types.]
Yes, I think, it depends on what you're asking. I've attached boot.c, a
rebooting
program that I wrote, which compiles for RM Watcom, PM Watcom, and PM DJGPP.
It might give you the clues you need. The cold and warm reboot work. The
soft reboot
(which is commented out) works for Watcom but not DJGPP.
Sincerely,
Rod Pemberton
----
/* boot.c reboot the PC */
/* Rod Pemberton 2000-2004 */
/* this program is released to PUBLIC DOMAIN */
/* */
/* DJGPP gcc -o boot.exe boot.c */
/* WATCOM wcl/l=dos boot.c */
/* or wcl386/l=dos4g boot.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __DJGPP__
#include <go32.h>
#include <dpmi.h>
#include <sys/farptr.h>
__dpmi_regs r;
#endif
#ifdef __WATCOMC__
#include <i86.h>
#include <dos.h>
union REGS r;
struct SREGS s;
struct {
long EDI,ESI,EBP,rsvd,EBX,EDX,ECX,EAX;
short flags,ES,DS,FS,GS,IP,CS,SP,SS;
} RMI;
#endif
int main(int argc,char **argv)
{
#ifdef __WATCOMC__
unsigned short *ptr;
#ifndef __386__
void ( __far *reset)();
#endif
#endif
memset(&r,0,sizeof(r));
if (argc == 1 || argc > 2 || argv[1][0]!='-')
/* no valid flags, print usage & exit */
{
printf( "A program to reboot your computer.\n"
"Usage: Boot <param>\n"
"-c cold \n"
"-w warm \n"
/* "-s soft (Int 19) \n" */
);
exit(1);
}
switch(argv[1][1]) /* fill option controls with arg position */
{
case 'c': /* cold reset */
#ifdef __DJGPP__
/* DJGPP PM */
_farpokew(_dos_ds,0x472,0x0);
r.x.cs = 0xFFFF;
r.x.ip = 0x0000;
__dpmi_simulate_real_mode_procedure_retf(&r);
#endif
#ifdef __WATCOMC__
ptr = (unsigned short *)0x472;
*ptr = 0x0;
#ifdef __386__
/* WATCOM PM, use DPMI */
/* DOS/4G (non-professional) doesn't support */
/* DPMI 0x301 "Call Real Mode Procedure With Far Return Frame" */
/* so we simulate it by setting an interrupt to the BIOS RESET JUMP */
/* and then calling the interrupt using: */
/* DPMI 0x201 "Set Real Mode Interrupt Vector" */
/* DPMI 0x300 "Simulate Real Mode Interrupt" */
r.w.ax=0x0201; /* set real mode interrupt */
r.h.bl=0x60; /* user interrupt */
r.w.cx=0xFFFF;
r.w.dx=0x0000;
int386(0x31,&r,&r);
r.w.ax=0x0300; /* simulate real mode interrupt */
r.h.bl=0x60;
r.h.bh=0;
r.w.cx=0;
s.es=FP_SEG(&RMI);
r.x.edi=FP_OFF(&RMI);
int386x(0x31,&r,&r,&s);
#else
/* WATCOM RM */
reset=MK_FP(0xFFFF,0x0000);
(*reset)(); /* call the function */
#if 0
/* Another possible WATCOM RM coding option: */
void (__interrupt __far *handler)(); /* declaration */
handler=MK_FP(0xFFFF,0x0000);
_dos_setvect(0x60,handler);
int86(0x60,&r,&r);
#endif
#endif
#endif
break;
case 'w': /* warm reset */
#ifdef __DJGPP__
/* DJGPP PM */
_farpokew(_dos_ds,0x472,0x1234);
r.x.cs = 0xFFFF;
r.x.ip = 0x0000;
__dpmi_simulate_real_mode_procedure_retf(&r);
#endif
#ifdef __WATCOMC__
ptr = (unsigned short *)0x472;
*ptr = 0x1234;
#ifdef __386__
/* WATCOM PM, use DPMI */
r.w.ax=0x0201; /* set real mode interrupt */
r.h.bl=0x60; /* user interrupt */
r.w.cx=0xFFFF;
r.w.dx=0x0000;
int386(0x31,&r,&r);
r.w.ax=0x0300; /* simulate real mode interrupt */
r.h.bl=0x60;
r.h.bh=0;
r.w.cx=0;
s.es=FP_SEG(&RMI);
r.x.edi=FP_OFF(&RMI);
int386x(0x31,&r,&r,&s);
#else
/* WATCOM RM */
reset=MK_FP(0xFFFF,0x0000);
(*reset)(); /* call the function */
#endif
#endif
break;
/* Int 0x19 works if HIMEM is not loaded by CONFIG.SYS or Windows9x */
/* i.e., "Safe mode command prompt only" for Windows9x */
/* WATCOM works for both RM & PM */
/* DJGPP fails */
case 's': /* soft reset */
#ifdef __DJGPP__
/* No working method found. */
#endif
#ifdef __WATCOMC__
#ifdef __386__
/* WATCOM PM, use DPMI */
r.w.ax=0x0300; /* simulate real mode interrupt */
r.h.bl=0x19;
r.h.bh=0;
r.w.cx=0;
s.es=FP_SEG(&RMI);
r.x.edi=FP_OFF(&RMI);
int386x(0x31,&r,&r,&s);
#else
/* WATCOM RM */
int86(0x19,&r,&r);
#endif
#endif
break;
default: break;
}
return(0);
}