From 4d6da0ec7a6a184de4b5ea9791ad5e6e01b186e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 1 Aug 2015 12:41:22 +0000 Subject: [PATCH] [NTVDM] - Remove some hardcoded values. - Reshuffle again DOS initialization to better reflect how it is done in the real world (see "Advanced MS-DOS Programming" by Ray Duncan, Chapter 2 "MS-DOS in Operation"): split DOS data stuff into DOS BIOS data, and DOS kernel data areas. In preparation for an upcoming commit. svn path=/trunk/; revision=68585 --- .../mvdm/ntvdm/dos/dos32krnl/bios.c | 114 +++++++++--------- .../subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c | 61 +++------- .../subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h | 67 ++++++---- .../mvdm/ntvdm/dos/dos32krnl/dosfiles.h | 24 ++++ .../mvdm/ntvdm/dos/dos32krnl/handle.c | 4 +- 5 files changed, 143 insertions(+), 127 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c index 689b7cf50d7..bbe3a242c29 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c @@ -32,6 +32,13 @@ /* PRIVATE VARIABLES **********************************************************/ +// CALLBACK16 BiosContext; + +/* PUBLIC VARIABLES ***********************************************************/ + +/* Global DOS BIOS data area */ +PBIOS_DATA BiosData; + /* PRIVATE FUNCTIONS **********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/ @@ -63,7 +70,7 @@ BOOLEAN DosCheckInput(VOID) return FALSE; } - if (Descriptor->DeviceInfo & (1 << 7)) + if (Descriptor->DeviceInfo & FILE_INFO_DEVICE) { WORD Result; PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer); @@ -155,28 +162,61 @@ BOOLEAN DosBuildSysEnvBlock(VOID) BOOLEAN DosBIOSInitialize(VOID) { -#if 0 - UCHAR i; - CHAR CurrentDirectory[MAX_PATH]; - CHAR DosDirectory[DOS_DIR_LENGTH]; - LPSTR Path; - FILE *Stream; WCHAR Buffer[256]; -#endif /* Set the data segment */ - setDS(DOS_DATA_SEGMENT); + setDS(BIOS_DATA_SEGMENT); - /* Initialize the DOS stack */ - // Stack just before FIRST_MCB_SEGMENT and after SYSTEM_ENV_BLOCK - // FIXME: Add a block of fixed size for the stack in DOS_DATA instead! + /* Initialize the global DOS BIOS data area */ + BiosData = (PBIOS_DATA)SEG_OFF_TO_PTR(BIOS_DATA_SEGMENT, 0x0000); + + /* Initialize the DOS BIOS stack */ + // FIXME: Add a block of fixed size for the stack in BIOS/DOS_DATA instead! setSS(0x0F00); setSP(0x0FF0); - setBP(0x091E); // DOS base stack pointer relic value - /* Initialize memory management */ - DosInitializeMemory(); + /* + * Initialize the INT 13h (BIOS Disk Services) handler chain support. + * + * The INT 13h handler chain is some functionality that allows DOS + * to insert disk filter drivers in between the (hooked) INT 13h handler + * and its original handler. + * Typically, those are: + * - filter for detecting disk changes (for floppy disks), + * - filter for tracking formatting calls and correcting DMA boundary errors, + * - a possible filter to work around a bug in a particular version of PC-AT's + * IBM's ROM BIOS (on systems with model byte FCh and BIOS date "01/10/84" only) + * (see http://www.ctyme.com/intr/rb-4453.htm for more details). + * + * This functionality is known to be used by some legitimate programs, + * by Windows 3.x, as well as some illegitimate ones (aka. virii). + * + * See extra information about this support in dos.h + */ + // FIXME: Should be done by the DOS BIOS + BiosData->RomBiosInt13 = ((PULONG)BaseAddress)[0x13]; + BiosData->PrevInt13 = BiosData->RomBiosInt13; +// RegisterDosInt32(0x13, DosInt13h); // Unused at the moment! + + // + // HERE: Do all hardware initialization needed for DOS + // + + /* + * SysInit part... + */ + + // InitializeContext(&DosContext, BIOS_CODE_SEGMENT, 0x0010); + + /* Initialize the DOS kernel (DosInit) */ + if (!DosKRNLInitialize()) + { + DisplayMessage(L"Failed to load the DOS kernel! Exiting..."); + return FALSE; + } + + /* DOS kernel loading succeeded, we can finish the initialization */ /* Build the system master environment block (inherited by the shell) */ if (!DosBuildSysEnvBlock()) @@ -184,44 +224,7 @@ BOOLEAN DosBIOSInitialize(VOID) DPRINT1("An error occurred when setting up the system environment block.\n"); } - -#if 0 - - /* Clear the current directory buffer */ - RtlZeroMemory(CurrentDirectories, sizeof(CurrentDirectories)); - - /* Get the current directory */ - if (!GetCurrentDirectoryA(MAX_PATH, CurrentDirectory)) - { - // TODO: Use some kind of default path? - return FALSE; - } - - /* Convert that to a DOS path */ - if (!GetShortPathNameA(CurrentDirectory, DosDirectory, DOS_DIR_LENGTH)) - { - // TODO: Use some kind of default path? - return FALSE; - } - - /* Set the drive */ - Sda->CurrentDrive = DosDirectory[0] - 'A'; - - /* Get the directory part of the path */ - Path = strchr(DosDirectory, '\\'); - if (Path != NULL) - { - /* Skip the backslash */ - Path++; - } - - /* Set the directory */ - if (Path != NULL) - { - strncpy(CurrentDirectories[Sda->CurrentDrive], Path, DOS_DIR_LENGTH); - } - - /* Read CONFIG.SYS */ + /* TODO: Read CONFIG.NT/SYS */ Stream = _wfopen(DOS_CONFIG_PATH, L"r"); if (Stream != NULL) { @@ -232,10 +235,7 @@ BOOLEAN DosBIOSInitialize(VOID) fclose(Stream); } -#endif - - /* Initialize the DOS kernel */ - return DosKRNLInitialize(); + return TRUE; } /* EOF */ diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c index 26d3c5bce32..55d7b40f85c 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c @@ -191,7 +191,6 @@ VOID WINAPI DosInt21h(LPWORD Stack) BYTE Character; SYSTEMTIME SystemTime; PCHAR String; - PDOS_INPUT_BUFFER InputBuffer; Sda->InDos++; @@ -351,7 +350,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) case 0x0A: { WORD Count = 0; - InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX()); + PDOS_INPUT_BUFFER InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX()); DPRINT("Read Buffered Input\n"); @@ -2199,12 +2198,12 @@ VOID WINAPI DosInt2Fh(LPWORD Stack) case 0x13: { /* Save the old values of PrevInt13 and RomBiosInt13 */ - ULONG OldInt13 = DosData->PrevInt13; - ULONG OldBiosInt13 = DosData->RomBiosInt13; + ULONG OldInt13 = BiosData->PrevInt13; + ULONG OldBiosInt13 = BiosData->RomBiosInt13; /* Set PrevInt13 and RomBiosInt13 to their new values */ - DosData->PrevInt13 = MAKELONG(getDX(), getDS()); - DosData->RomBiosInt13 = MAKELONG(getBX(), getES()); + BiosData->PrevInt13 = MAKELONG(getDX(), getDS()); + BiosData->RomBiosInt13 = MAKELONG(getBX(), getES()); /* Return in DS:DX the old value of PrevInt13 */ setDS(HIWORD(OldInt13)); @@ -2271,8 +2270,6 @@ VOID WINAPI DosInt2Fh(LPWORD Stack) BOOLEAN DosKRNLInitialize(VOID) { -#if 1 - UCHAR i; PDOS_SFT Sft; LPSTR Path; @@ -2281,7 +2278,8 @@ BOOLEAN DosKRNLInitialize(VOID) CHAR CurrentDirectory[MAX_PATH]; CHAR DosDirectory[DOS_DIR_LENGTH]; - const BYTE NullDriverRoutine[] = { + static const BYTE NullDriverRoutine[] = + { /* Strategy routine entry */ 0x26, // mov [Request.Status], DOS_DEVSTAT_DONE 0xC7, @@ -2294,13 +2292,17 @@ BOOLEAN DosKRNLInitialize(VOID) 0xCB, // retf }; - FILE *Stream; - WCHAR Buffer[256]; + /* Set the data segment */ + setDS(DOS_DATA_SEGMENT); /* Initialize the global DOS data area */ DosData = (PDOS_DATA)SEG_OFF_TO_PTR(DOS_DATA_SEGMENT, 0x0000); RtlZeroMemory(DosData, sizeof(*DosData)); + /* Initialize the DOS stack */ + setSS(DOS_DATA_SEGMENT); + setSP(DOS_DATA_OFFSET(DosStack) + sizeof(DosData->DosStack) - sizeof(WORD)); + /* Initialize the list of lists */ SysVars = &DosData->SysVars; RtlZeroMemory(SysVars, sizeof(*SysVars)); @@ -2409,18 +2411,8 @@ BOOLEAN DosKRNLInitialize(VOID) RtlZeroMemory(&Sft->FileDescriptors[i], sizeof(DOS_FILE_DESCRIPTOR)); } - /* Read CONFIG.SYS */ - Stream = _wfopen(DOS_CONFIG_PATH, L"r"); - if (Stream != NULL) - { - while (fgetws(Buffer, 256, Stream)) - { - // TODO: Parse the line - } - fclose(Stream); - } - -#endif + /* Initialize memory management */ + DosInitializeMemory(); /* Initialize the callback context */ InitializeContext(&DosContext, DOS_CODE_SEGMENT, 0x0000); @@ -2449,29 +2441,6 @@ BOOLEAN DosKRNLInitialize(VOID) RegisterDosInt32(0x2C, NULL); RegisterDosInt32(0x2D, NULL); - /* - * Initialize the INT 13h (BIOS Disk Services) handler chain support. - * - * The INT 13h handler chain is some functionality that allows DOS - * to insert disk filter drivers in between the (hooked) INT 13h handler - * and its original handler. - * Typically, those are: - * - filter for detecting disk changes (for floppy disks), - * - filter for tracking formatting calls and correcting DMA boundary errors, - * - a possible filter to work around a bug in a particular version of PC-AT's - * IBM's ROM BIOS (on systems with model byte FCh and BIOS date "01/10/84" only) - * (see http://www.ctyme.com/intr/rb-4453.htm for more details). - * - * This functionality is known to be used by some legitimate programs, - * by Windows 3.x, as well as some illegitimate ones (aka. virii). - * - * See extra information about this support in dos.h - */ - // FIXME: Should be done by the DOS BIOS - DosData->RomBiosInt13 = ((PULONG)BaseAddress)[0x13]; - DosData->PrevInt13 = DosData->RomBiosInt13; -// RegisterDosInt32(0x13, DosInt13h); // Unused at the moment! - /* Initialize country data */ DosCountryInitialize(); diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h index b6ce853d679..7d322b8bc60 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h @@ -27,22 +27,26 @@ #define DOS_CONFIG_PATH L"%SystemRoot%\\system32\\CONFIG.NT" #define DOS_COMMAND_INTERPRETER L"%SystemRoot%\\system32\\COMMAND.COM /k %SystemRoot%\\system32\\AUTOEXEC.NT" -#define SYSTEM_PSP 0x08 -#define SYSTEM_ENV_BLOCK 0x800 -#define DOS_CODE_SEGMENT 0x70 -#define DOS_DATA_SEGMENT 0xA0 +#define BIOS_CODE_SEGMENT 0x70 +#define BIOS_DATA_SEGMENT 0x70 +#define DOS_CODE_SEGMENT 0x80 +#define DOS_DATA_SEGMENT 0xA5 #define DOS_DATA_OFFSET(x) FIELD_OFFSET(DOS_DATA, x) +#define SYSTEM_ENV_BLOCK 0x600 // FIXME: Should be dynamic + +#define SYSTEM_PSP 0x0008 + #define INVALID_DOS_HANDLE 0xFFFF #define DOS_INPUT_HANDLE 0 #define DOS_OUTPUT_HANDLE 1 #define DOS_ERROR_HANDLE 2 -#define DOS_SFT_SIZE 255 -#define DOS_DIR_LENGTH 64 -#define NUM_DRIVES ('Z' - 'A' + 1) -#define DOS_CHAR_ATTRIBUTE 0x07 +#define DOS_SFT_SIZE 255 // Value of the 'FILES=' command; maximum 255 +#define DOS_DIR_LENGTH 64 +#define NUM_DRIVES ('Z' - 'A' + 1) +#define DOS_CHAR_ATTRIBUTE 0x07 #pragma pack(push, 1) @@ -230,8 +234,27 @@ typedef struct _DOS_SDA DWORD PrevCallFrame; } DOS_SDA, *PDOS_SDA; +/* + * DOS kernel data structure + */ typedef struct _DOS_DATA { + DOS_SYSVARS SysVars; + BYTE NullDriverRoutine[7]; + WORD DosVersion; // DOS version to report to programs (can be different from the true one) + DOS_SDA Sda; + CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]; + BYTE DosStack[384]; + BYTE Sft[ANYSIZE_ARRAY]; +} DOS_DATA, *PDOS_DATA; + +/* + * DOS BIOS data structure at segment 70h + */ +typedef struct _BIOS_DATA +{ + BYTE StartupCode[20]; // 0x00 - 20 bytes: large enough for now! + /* * INT 13h (BIOS Disk Services) handler chain support. * @@ -256,22 +279,20 @@ typedef struct _DOS_DATA * http://repo.hackerzvoice.net/depot_madchat/vxdevl/vdat/tuvd0001.htm * http://vxheaven.org/lib/vsm01.html */ - DWORD RomBiosInt13; - DWORD PrevInt13; // FIXME: Put it at 0070:00B4 + BYTE Padding0[0xB0 - /*FIELD_OFFSET(BIOS_DATA, StartupCode)*/ 20]; + DWORD RomBiosInt13; // 0xb0 + DWORD PrevInt13; // 0xb4 + BYTE Padding1[0x100 - 0xB8]; // 0xb8 +} BIOS_DATA, *PBIOS_DATA; - DOS_SYSVARS SysVars; - BYTE NullDriverRoutine[7]; - WORD DosVersion; // DOS version to report to programs (can be different from the true one) - DOS_SDA Sda; - CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]; - BYTE Sft[ANYSIZE_ARRAY]; -} DOS_DATA, *PDOS_DATA; +C_ASSERT(sizeof(BIOS_DATA) == 0x100); #pragma pack(pop) /* VARIABLES ******************************************************************/ -extern BOOLEAN DoEcho; +extern BOOLEAN DoEcho; // FIXME: Maybe move inside BiosData? (it's set by BIOS but used by CON driver in DOS BIOS) +extern PBIOS_DATA BiosData; extern PDOS_DATA DosData; extern PDOS_SYSVARS SysVars; extern PDOS_SDA Sda; @@ -279,11 +300,13 @@ extern PDOS_SDA Sda; /* FUNCTIONS ******************************************************************/ extern CALLBACK16 DosContext; -#define RegisterDosInt32(IntNumber, IntHandler) \ +#define RegisterDosInt32(IntNumber, IntHandler) \ do { \ - DosContext.NextOffset += RegisterInt32(MAKELONG(DosContext.NextOffset, \ - DosContext.Segment), \ - (IntNumber), (IntHandler), NULL); \ + ASSERT((0x20 <= IntNumber) && (IntNumber <= 0x2F)); \ + RegisterInt32(DosContext.TrampolineFarPtr + \ + DosContext.TrampolineSize + \ + (IntNumber - 0x20) * Int16To32StubSize, \ + (IntNumber), (IntHandler), NULL); \ } while(0); /* diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h index 3cc7a935805..c52286dfcba 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h @@ -12,6 +12,30 @@ #pragma pack(push, 1) +#if 0 // Real DOS-5 SFT entry, for reference only +typedef struct _DOS_FILE_DESCRIPTOR_DOS5 +{ + WORD RefCount; // 0x00 + WORD OpenMode; // 0x02 + BYTE Attributes; // 0x04 + WORD DeviceInfo; // 0x05 + DWORD DevicePointer; // 0x07 + WORD StartCluster; // 0x0b + WORD Time; // 0x0d + WORD Date; // 0x0f + DWORD Size; // 0x11 + DWORD Position; // 0x15 + BYTE Reserved0[7]; // 0x19 + CHAR FileName[11]; // 0x20 + BYTE Reserved1[6]; // 0x2b + WORD OwnerPsp; // 0x31 + BYTE Reserved2[8]; // 0x33 +} DOS_FILE_DESCRIPTOR_DOS5, *PDOS_FILE_DESCRIPTOR_DOS5; + +C_ASSERT(sizeof(DOS_FILE_DESCRIPTOR_DOS5) == 0x3B); +#endif + +// Modified DOS SFT entry, compatible for NTVDM only typedef struct _DOS_FILE_DESCRIPTOR { WORD RefCount; diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c index 2e3ce8e7108..4b5890dd184 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c @@ -360,7 +360,7 @@ BOOLEAN DosCloseHandle(WORD DosHandle) /* Check if the reference count fell to zero */ if (!Descriptor->RefCount) { - if (Descriptor->DeviceInfo & (1 << 7)) + if (Descriptor->DeviceInfo & FILE_INFO_DEVICE) { PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer); @@ -369,7 +369,7 @@ BOOLEAN DosCloseHandle(WORD DosHandle) } else { - /* Close the win32 handle */ + /* Close the Win32 handle */ CloseHandle(Descriptor->Win32Handle); } }