From 0121ac1a124312853c11086fe72d7e8600e1e597 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Wed, 7 Jun 2000 02:02:56 +0000 Subject: [PATCH] Removed mis-aligned accesses during BIOS/DOS data initialization. --- include/miscemu.h | 45 +++++++++++++++ msdos/devices.c | 144 ++++++++++++++++++++++++---------------------- msdos/dosmem.c | 99 ++++++++++++++----------------- msdos/dpmi.c | 4 +- 4 files changed, 167 insertions(+), 125 deletions(-) diff --git a/include/miscemu.h b/include/miscemu.h index 865eb1ad7bb..32bba50e01c 100644 --- a/include/miscemu.h +++ b/include/miscemu.h @@ -74,6 +74,51 @@ typedef struct BYTE DiskDataRate; /* 8B: Last disk data rate selected */ } BIOSDATA; +typedef struct +{ + DWORD StaticFuncTable; /* 00: static functionality table */ + BYTE VideoMode; /* 04: video mode in effect */ + WORD NumberColumns; /* 05: number of columns */ + WORD RegenBufLen; /* 07: length of regen buffer in bytes */ + WORD RegenBufAddr; /* 09: starting address of regen buffer */ + WORD CursorPos[8]; /* 0B: cursor position for page 0..7 */ + WORD CursorType; /* 1B: cursor "type" (start/stop scan lines) */ + BYTE ActivePage; /* 1D: active display page */ + WORD CRTCPort; /* 1E: CRTC port address */ + BYTE Port3x8; /* 20: current setting of PORT 03x8h */ + BYTE Port3x9; /* 21: current setting of PORT 03x9h */ + BYTE NumberRows; /* 22: number of rows - 1 */ + WORD BytesPerChar; /* 23: bytes/character */ + BYTE DCCActive; /* 25: display combination code of active display */ + BYTE DCCAlternate; /* 26: DCC of alternate display */ + WORD NumberColors; /* 27: number of colors supported in current mode (0000h = mono) */ + BYTE NumberPages; /* 29: number of pages supported in current mode */ + BYTE NumberScanlines; /* 2A: number of scan lines active */ + BYTE CharBlockPrimary; /* 2B: primary character block */ + BYTE CharBlockSecondary; /* 2C: secondary character block */ + BYTE MiscFlags; /* 2D: miscellaneous flags */ + BYTE NonVGASupport; /* 2E: non-VGA mode support */ + BYTE _reserved1[2]; /* 2F: */ + BYTE VideoMem; /* 31: video memory available */ + BYTE SavePointerState; /* 32: save pointer state flags */ + BYTE DisplayStatus; /* 33: display information and status */ + BYTE _reserved2[12]; /* 34: */ + +} VIDEOSTATE; + +typedef struct +{ + BYTE ModeSupport[7]; /* 00: modes supported 1..7 */ + BYTE ScanlineSupport; /* 07: scan lines supported */ + BYTE NumberCharBlocks; /* 08: total number of character blocks */ + BYTE ActiveCharBlocks; /* 09: max. number of active character blocks */ + WORD MiscFlags; /* 0A: miscellaneous function support flags */ + WORD _reserved1; /* 0C: */ + BYTE SavePointerFlags; /* 0E: save pointer function flags */ + BYTE _reserved2; /* OF: */ + +} VIDEOFUNCTIONALITY; + #include "poppack.h" extern HANDLE16 DOSMEM_BiosDataSeg; diff --git a/msdos/devices.c b/msdos/devices.c index 5d3632806f7..a3d08639d5b 100644 --- a/msdos/devices.c +++ b/msdos/devices.c @@ -15,12 +15,11 @@ #include "pshpack1.h" typedef struct { - DOS_DEVICE_HEADER hdr; BYTE ljmp1; RMCBPROC strategy; BYTE ljmp2; RMCBPROC interrupt; -} WINEDEV; +} WINEDEV_THUNK; typedef struct { BYTE size; /* length of header + data */ @@ -46,13 +45,11 @@ typedef struct { #include "poppack.h" -#define REQ_SCRATCH sizeof(REQ_IO) +#define CON_BUFFER 128 #define SYSTEM_STRATEGY_NUL 0x0100 #define SYSTEM_STRATEGY_CON 0x0101 -DWORD DOS_LOLSeg; - #define NONEXT ((DWORD)-1) #define ATTR_STDIN 0x0001 @@ -94,10 +91,6 @@ DWORD DOS_LOLSeg; #define LJMP 0xea -#define DEV0_OFS (sizeof(DOS_LISTOFLISTS) - sizeof(DOS_DEVICE_HEADER)) -#define DEV1_OFS (DEV0_OFS + sizeof(WINEDEV)) -#define ALLDEV_OFS (DEV1_OFS + sizeof(devs)) -#define ALL_OFS (ALLDEV_OFS + REQ_SCRATCH) /* prototypes */ static void WINAPI nul_strategy(CONTEXT86*ctx); @@ -105,27 +98,44 @@ static void WINAPI nul_interrupt(CONTEXT86*ctx); static void WINAPI con_strategy(CONTEXT86*ctx); static void WINAPI con_interrupt(CONTEXT86*ctx); -/* the device headers */ -#define STRATEGY_OFS sizeof(DOS_DEVICE_HEADER) -#define INTERRUPT_OFS STRATEGY_OFS+5 - -static DOS_DEVICE_HEADER dev_nul_hdr={ - NONEXT, - ATTR_CHAR|ATTR_NUL|ATTR_DEVICE, - STRATEGY_OFS,INTERRUPT_OFS, - "NUL " -}; - -static WINEDEV devs[]={ +/* devices */ +typedef struct { - {NONEXT, - ATTR_CHAR|ATTR_STDIN|ATTR_STDOUT|ATTR_FASTCON|ATTR_NOTEOF|ATTR_DEVICE, - STRATEGY_OFS,INTERRUPT_OFS, - "CON "}, - LJMP,con_strategy, - LJMP,con_interrupt} + char name[8]; + WORD attr; + RMCBPROC strategy; + RMCBPROC interrupt; + +} WINEDEV; + +static WINEDEV devs[] = +{ + { "NUL ", + ATTR_CHAR|ATTR_NUL|ATTR_DEVICE, + nul_strategy, nul_interrupt }, + + { "CON ", + ATTR_CHAR|ATTR_STDIN|ATTR_STDOUT|ATTR_FASTCON|ATTR_NOTEOF|ATTR_DEVICE, + con_strategy, con_interrupt } }; -#define nr_devs (sizeof(devs)/sizeof(WINEDEV)) + +#define NR_DEVS (sizeof(devs)/sizeof(WINEDEV)) + +/* DOS data segment */ +typedef struct +{ + DOS_LISTOFLISTS lol; + DOS_DEVICE_HEADER dev[NR_DEVS-1]; + WINEDEV_THUNK thunk[NR_DEVS]; + REQ_IO req; + BYTE buffer[CON_BUFFER]; + +} DOS_DATASEG; + +#define DOS_DATASEG_OFF(xxx) FIELD_OFFSET(DOS_DATASEG, xxx) + +DWORD DOS_LOLSeg; + /* the device implementations */ static void do_lret(CONTEXT86*ctx) @@ -182,8 +192,6 @@ static void WINAPI nul_interrupt(CONTEXT86*ctx) do_lret(ctx); } -#define CON_BUFFER 128 - static void WINAPI con_strategy(CONTEXT86*ctx) { do_strategy(ctx, SYSTEM_STRATEGY_CON, sizeof(int)); @@ -196,10 +204,11 @@ static void WINAPI con_interrupt(CONTEXT86*ctx) BIOSDATA *bios = DOSMEM_BiosData(); WORD CurOfs = bios->NextKbdCharPtr; DOS_LISTOFLISTS *lol = DOSMEM_LOL(); - BYTE *linebuffer = ((BYTE*)lol) + ALL_OFS; + DOS_DATASEG *dataseg = (DOS_DATASEG *)lol; + BYTE *linebuffer = dataseg->buffer; BYTE *curbuffer = (lol->offs_unread_CON) ? - (((BYTE*)lol) + lol->offs_unread_CON) : (BYTE*)NULL; - DOS_DEVICE_HEADER *con = (DOS_DEVICE_HEADER*)(((BYTE*)lol) + DEV1_OFS); + (((BYTE*)dataseg) + lol->offs_unread_CON) : (BYTE*)NULL; + DOS_DEVICE_HEADER *con = dataseg->dev; LPDOSTASK lpDosTask = MZ_Current(); switch (hdr->command) { @@ -429,50 +438,47 @@ Output of DOS 6.22: void DOSDEV_InstallDOSDevices(void) { - WINEDEV *dev; - DOS_DEVICE_HEADER *pdev; + DOS_DATASEG *dataseg; UINT16 seg; int n; - WORD ofs = DEV0_OFS; - DOS_LISTOFLISTS *DOS_LOL; /* allocate DOS data segment or something */ - DOS_LOLSeg = GlobalDOSAlloc16(ALL_OFS+CON_BUFFER); + DOS_LOLSeg = GlobalDOSAlloc16(sizeof(DOS_DATASEG)); seg = HIWORD(DOS_LOLSeg); - DOS_LOL = PTR_SEG_OFF_TO_LIN(LOWORD(DOS_LOLSeg), 0); + dataseg = PTR_SEG_OFF_TO_LIN(LOWORD(DOS_LOLSeg), 0); /* initialize the magnificent List Of Lists */ - InitListOfLists(DOS_LOL); + InitListOfLists(&dataseg->lol); - /* copy first device (NUL) */ - pdev = &(DOS_LOL->NUL_dev); - memcpy(pdev,&dev_nul_hdr,sizeof(DOS_DEVICE_HEADER)); - pdev->strategy += ofs; - pdev->interrupt += ofs; - /* set up dev so we can copy over the rest */ - dev = (WINEDEV*)(((char*)DOS_LOL)+ofs); - dev[0].ljmp1 = LJMP; - dev[0].strategy = (RMCBPROC)DPMI_AllocInternalRMCB(nul_strategy); - dev[0].ljmp2 = LJMP; - dev[0].interrupt = (RMCBPROC)DPMI_AllocInternalRMCB(nul_interrupt); + /* Set up first device (NUL) */ + dataseg->lol.NUL_dev.next_dev = PTR_SEG_OFF_TO_SEGPTR(seg, DOS_DATASEG_OFF(dev[0])); + dataseg->lol.NUL_dev.attr = devs[0].attr; + dataseg->lol.NUL_dev.strategy = DOS_DATASEG_OFF(thunk[0].ljmp1); + dataseg->lol.NUL_dev.interrupt = DOS_DATASEG_OFF(thunk[0].ljmp2); + memcpy(dataseg->lol.NUL_dev.name, devs[0].name, 8); - dev++; - ofs += sizeof(WINEDEV); - - /* first of remaining devices is CON */ - DOS_LOL->ptr_CON_dev_hdr = PTR_SEG_OFF_TO_SEGPTR(seg, ofs); - - /* copy remaining devices */ - memcpy(dev,&devs,sizeof(devs)); - for (n=0; nnext_dev = PTR_SEG_OFF_TO_SEGPTR(seg, ofs); - dev[n].hdr.strategy += ofs; - dev[n].hdr.interrupt += ofs; - dev[n].strategy = (RMCBPROC)DPMI_AllocInternalRMCB(dev[n].strategy); - dev[n].interrupt = (RMCBPROC)DPMI_AllocInternalRMCB(dev[n].interrupt); - ofs += sizeof(WINEDEV); - pdev = &(dev[n].hdr); + /* Set up the remaining devices */ + for (n = 1; n < NR_DEVS; n++) + { + dataseg->dev[n-1].next_dev = (n+1) == NR_DEVS ? NONEXT : + PTR_SEG_OFF_TO_SEGPTR(seg, DOS_DATASEG_OFF(dev[n])); + dataseg->dev[n-1].attr = devs[n].attr; + dataseg->dev[n-1].strategy = DOS_DATASEG_OFF(thunk[n].ljmp1); + dataseg->dev[n-1].interrupt = DOS_DATASEG_OFF(thunk[n].ljmp2); + memcpy(dataseg->dev[n-1].name, devs[n].name, 8); } + + /* Set up thunks */ + for (n = 0; n < NR_DEVS; n++) + { + dataseg->thunk[n].ljmp1 = LJMP; + dataseg->thunk[n].strategy = (RMCBPROC)DPMI_AllocInternalRMCB(devs[n].strategy); + dataseg->thunk[n].ljmp2 = LJMP; + dataseg->thunk[n].interrupt = (RMCBPROC)DPMI_AllocInternalRMCB(devs[n].interrupt); + } + + /* CON is device 1 */ + dataseg->lol.ptr_CON_dev_hdr = PTR_SEG_OFF_TO_SEGPTR(seg, DOS_DATASEG_OFF(dev[0])); } DWORD DOSDEV_Console(void) @@ -513,7 +519,7 @@ static void DOSDEV_DoReq(void*req, DWORD dev) char *phdr; dhdr = DOSMEM_MapRealToLinear(dev); - phdr = ((char*)DOSMEM_LOL()) + ALLDEV_OFS; + phdr = ((char*)DOSMEM_LOL()) + DOS_DATASEG_OFF(req); /* copy request to request scratch area */ memcpy(phdr, req, hdr->size); @@ -523,7 +529,7 @@ static void DOSDEV_DoReq(void*req, DWORD dev) /* ES:BX points to request for strategy routine */ ES_reg(&ctx) = HIWORD(DOS_LOLSeg); - EBX_reg(&ctx) = ALLDEV_OFS; + EBX_reg(&ctx) = DOS_DATASEG_OFF(req); /* call strategy routine */ CS_reg(&ctx) = SELECTOROF(dev); diff --git a/msdos/dosmem.c b/msdos/dosmem.c index afdadca9ea8..3967a398102 100644 --- a/msdos/dosmem.c +++ b/msdos/dosmem.c @@ -174,13 +174,14 @@ static void DOSMEM_FillBiosSegments(void) BIOSDATA *pBiosData = (BIOSDATA *)GlobalLock16( DOSMEM_BiosDataSeg ); /* bogus 0xe0xx addresses !! Adapt int 0x10/0x1b if change needed */ - BYTE *pVideoStaticFuncTable = pBiosSys+0xe000; - BYTE *pVideoStateInfo = pBiosSys+0xe010; - BYTE *p; + VIDEOFUNCTIONALITY *pVidFunc = (VIDEOFUNCTIONALITY *)(pBiosSys+0xe000); + VIDEOSTATE *pVidState = (VIDEOSTATE *)(pBiosSys+0xe010); int i; /* Clear all unused values */ memset( pBiosData, 0, sizeof(*pBiosData) ); + memset( pVidFunc, 0, sizeof(*pVidFunc ) ); + memset( pVidState, 0, sizeof(*pVidState) ); /* FIXME: should check the number of configured drives and ports */ @@ -210,7 +211,8 @@ static void DOSMEM_FillBiosSegments(void) pBiosData->DiskDataRate = 0; /* fill ROM configuration table (values from Award) */ - *(WORD *)(pBiosROMTable)= 0x08; /* number of bytes following */ + *(pBiosROMTable+0x0) = 0x08; /* number of bytes following LO */ + *(pBiosROMTable+0x1) = 0x00; /* number of bytes following HI */ *(pBiosROMTable+0x2) = 0xfc; /* model */ *(pBiosROMTable+0x3) = 0x01; /* submodel */ *(pBiosROMTable+0x4) = 0x00; /* BIOS revision */ @@ -220,59 +222,46 @@ static void DOSMEM_FillBiosSegments(void) *(pBiosROMTable+0x8) = 0x00; /* feature byte 4 */ *(pBiosROMTable+0x9) = 0x00; /* feature byte 5 */ - p = pVideoStaticFuncTable; - for (i=0; i < 7; i++) - *(p+i) = 0xff; /* modes supported 1 to 7 */ - *(p+0x7) = 7; /* scan lines supported */ - *(p+0x8) = 0; /* tot nr of char blocks in text mode */ - *(p+0x9) = 0; /* max nr of active char blocks in text */ - *(WORD *)(p+0xa) = 0x8ff; /* misc support flags */ - *(WORD *)(p+0xc) = 0; /* reserved */ - *(p+0xe) = 0x3f; /* save pointer function flags */ - *(p+0xf) = 0; /* reserved */ + for (i = 0; i < 7; i++) + pVidFunc->ModeSupport[i] = 0xff; + + pVidFunc->ScanlineSupport = 7; + pVidFunc->NumberCharBlocks = 0; + pVidFunc->ActiveCharBlocks = 0; + pVidFunc->MiscFlags = 0x8ff; + pVidFunc->SavePointerFlags = 0x3f; - p = pVideoStateInfo; - *(DWORD *)p = 0xf000e000; /* address of pVideoStaticFuncTable, FIXME: always real mode ? */ - *(p+0x04) = /* current video mode, needs updates ! */ - pBiosData->VideoMode; - *(WORD *)(p+0x05) = /* number of columns, needs updates ! */ - pBiosData->VideoColumns; - *(WORD *)(p+0x07) = 0; /* length of regen (???) buffer in bytes */ - *(WORD *)(p+0x09) = 0; /* starting address of regen (?) buffer */ - *(WORD *)(p+0x0b) = 0; /* cursorpos page 0 */ - *(WORD *)(p+0x0d) = 0; /* cursorpos page 1 */ - *(WORD *)(p+0x0f) = 0; /* page 2 */ - *(WORD *)(p+0x11) = 0; /* page 3 */ - *(WORD *)(p+0x13) = 0; /* page 4 */ - *(WORD *)(p+0x15) = 0; /* page 5 */ - *(WORD *)(p+0x17) = 0; /* page 6 */ - *(WORD *)(p+0x19) = 0; /* page 7 */ - *(WORD *)(p+0x1b) = 0x0a0b; /* cursor size (start/end line) */ - *(p+0x1d) = 0; /* active display page */ - *(WORD *)(p+0x1e) = 0x3da; /* CRTC port address */ - *(p+0x20) = 0x0; /* current setting of port 0x3x8 */ - *(p+0x21) = 0x0; /* current setting of port 0x3x9 */ - *(p+0x22) = 23; /* number of rows - 1 */ - *(WORD *)(p+0x23) = 0x10; /* bytes/character */ - *(p+0x25) = /* comb. of active display */ - pBiosData->DisplayCombination; - *(p+0x26) = 0; /* DCC (???) of alternate display */ - *(WORD *)(p+0x27) = 16; /* number of colors in current mode */ - *(p+0x29) = 1; /* number of pages in current mode */ - *(p+0x2a) = 3; /* number of scan lines active */ - /* (0,1,2,3) = (200,350,400,480) */ - *(p+0x2b) = 0; /* primary character block (?) */ - *(p+0x2c) = 0; /* secondary character block (?) */ - *(p+0x2d) = /* miscellaneous flags */ - (pBiosData->VGASettings & 0x0f) - | ((pBiosData->ModeOptions & 1) << 4); /* cursor emulation */ - *(p+0x2e) = 0; /* non-VGA mode support */ - *(WORD *)(p+0x2f) = 0; /* reserved */ - *(p+0x31) = /* video memory available */ - (pBiosData->ModeOptions & 0x60 >> 5); - *(p+0x32) = 0; /* save pointer state flags */ - *(p+0x33) = 4; /* display info and status */ + pVidState->StaticFuncTable = 0xf000e000; /* FIXME: always real mode ? */ + pVidState->VideoMode = pBiosData->VideoMode; /* needs updates! */ + pVidState->NumberColumns = pBiosData->VideoColumns; /* needs updates! */ + pVidState->RegenBufLen = 0; + pVidState->RegenBufAddr = 0; + + for (i = 0; i < 8; i++) + pVidState->CursorPos[i] = 0; + + pVidState->CursorType = 0x0a0b; /* start/end line */ + pVidState->ActivePage = 0; + pVidState->CRTCPort = 0x3da; + pVidState->Port3x8 = 0; + pVidState->Port3x9 = 0; + pVidState->NumberRows = 23; /* number of rows - 1 */ + pVidState->BytesPerChar = 0x10; + pVidState->DCCActive = pBiosData->DisplayCombination; + pVidState->DCCAlternate = 0; + pVidState->NumberColors = 16; + pVidState->NumberPages = 1; + pVidState->NumberScanlines = 3; /* (0,1,2,3) = (200,350,400,480) */ + pVidState->CharBlockPrimary = 0; + pVidState->CharBlockSecondary = 0; + pVidState->MiscFlags = + (pBiosData->VGASettings & 0x0f) + | ((pBiosData->ModeOptions & 1) << 4); /* cursor emulation */ + pVidState->NonVGASupport = 0; + pVidState->VideoMem = (pBiosData->ModeOptions & 0x60 >> 5); + pVidState->SavePointerState = 0; + pVidState->DisplayStatus = 4; /* BIOS date string */ strcpy((char *)pBiosSys+0xfff5, "13/01/99"); diff --git a/msdos/dpmi.c b/msdos/dpmi.c index 910ad607461..0bd0898baab 100644 --- a/msdos/dpmi.c +++ b/msdos/dpmi.c @@ -495,7 +495,7 @@ static RMCB *DPMI_AllocRMCB( void ) the DPMI 0.9 spec states that if it doesn't, it will be called again */ *p++ = 0xeb; *p++ = 0xfc; /* jmp RMCB */ -#else +#elif defined(__i386__) LPVOID RMCBmem = DOSMEM_GetBlock(0, 15, &uParagraph); LPBYTE p = RMCBmem; @@ -508,6 +508,8 @@ static RMCB *DPMI_AllocRMCB( void ) *(WORD *)p = __get_cs(); p+=2; *p++=0xc3; /* lret (FIXME?) */ +#else + uParagraph = 0; #endif NewRMCB->address = MAKELONG(0, uParagraph); NewRMCB->next = FirstRMCB;