From 9231f7b9a2c30dca9d493197fd438254c85de4ca Mon Sep 17 00:00:00 2001 From: David Welch Date: Wed, 27 Aug 2003 21:28:08 +0000 Subject: [PATCH] - Added support for crash dumps:- * Recognize the option /CRASHDUMP on the kernel command line to specify the type of dump desired. * Added a new driver (diskdump) which wraps the miniport for the disk containing the pagefile and does the crash dump i/o. * Added a FSCTL to get the mapping between LCNs and disk offsets so crash dumps don't need to go through the filesystem. svn path=/trunk/; revision=5887 --- reactos/drivers/fs/vfat/fsctl.c | 29 +- reactos/drivers/storage/class2/class2.c | 27 +- reactos/drivers/storage/diskdump/.cvsignore | 8 + reactos/drivers/storage/diskdump/Makefile | 19 + reactos/drivers/storage/diskdump/diskdump.c | 432 ++++++++++++++++++ reactos/drivers/storage/diskdump/diskdump.def | 7 + reactos/drivers/storage/diskdump/diskdump.edf | 7 + reactos/drivers/storage/diskdump/diskdump.rc | 38 ++ .../storage/diskdump/diskdump_helper.S | 9 + .../drivers/storage/scsiport/scsiport_int.h | 70 +++ reactos/include/ddk/ntddscsi.h | 7 +- reactos/include/ddk/ntifs.h | 8 + reactos/include/napi/core.h | 18 +- reactos/ntoskrnl/include/internal/mm.h | 4 + reactos/ntoskrnl/ke/bug.c | 12 +- reactos/ntoskrnl/ke/main.c | 20 +- reactos/ntoskrnl/mm/i386/page.c | 43 +- reactos/ntoskrnl/mm/pagefile.c | 289 ++++++++---- reactos/ntoskrnl/ntoskrnl.def | 3 +- reactos/ntoskrnl/ntoskrnl.edf | 3 +- 20 files changed, 937 insertions(+), 116 deletions(-) create mode 100644 reactos/drivers/storage/diskdump/.cvsignore create mode 100644 reactos/drivers/storage/diskdump/Makefile create mode 100644 reactos/drivers/storage/diskdump/diskdump.c create mode 100644 reactos/drivers/storage/diskdump/diskdump.def create mode 100644 reactos/drivers/storage/diskdump/diskdump.edf create mode 100644 reactos/drivers/storage/diskdump/diskdump.rc create mode 100644 reactos/drivers/storage/diskdump/diskdump_helper.S create mode 100644 reactos/drivers/storage/scsiport/scsiport_int.h diff --git a/reactos/drivers/fs/vfat/fsctl.c b/reactos/drivers/fs/vfat/fsctl.c index 57849fce90e..feac10743fa 100644 --- a/reactos/drivers/fs/vfat/fsctl.c +++ b/reactos/drivers/fs/vfat/fsctl.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: fsctl.c,v 1.22 2003/08/10 20:01:16 hbirr Exp $ +/* $Id: fsctl.c,v 1.23 2003/08/27 21:28:07 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -428,7 +428,7 @@ VfatGetVolumeBitmap(PVFAT_IRP_CONTEXT IrpContext) static NTSTATUS VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext) { - PIO_STACK_LOCATION Stack; + PIO_STACK_LOCATION Stack; LARGE_INTEGER Vcn; PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers; PFILE_OBJECT FileObject; @@ -524,6 +524,28 @@ VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext) return STATUS_INVALID_DEVICE_REQUEST; } +static NTSTATUS +VfatRosQueryLcnMapping(PVFAT_IRP_CONTEXT IrpContext) +{ + PDEVICE_EXTENSION DeviceExt; + PROS_QUERY_LCN_MAPPING LcnQuery; + PIO_STACK_LOCATION Stack; + + DPRINT("VfatGetRetrievalPointers(IrpContext %x)\n", IrpContext); + + DeviceExt = IrpContext->DeviceExt; + Stack = IrpContext->Stack; + if (IrpContext->Irp->AssociatedIrp.SystemBuffer == NULL || + Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ROS_QUERY_LCN_MAPPING)) + { + return STATUS_BUFFER_TOO_SMALL; + } + LcnQuery = (PROS_QUERY_LCN_MAPPING)(IrpContext->Irp->AssociatedIrp.SystemBuffer); + LcnQuery->LcnDiskOffset.QuadPart = DeviceExt->FatInfo.dataStart * DeviceExt->FatInfo.BytesPerSector; + IrpContext->Irp->IoStatus.Information = sizeof(ROS_QUERY_LCN_MAPPING); + return(STATUS_SUCCESS); +} + NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext) /* * FUNCTION: File system control @@ -554,6 +576,9 @@ NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext) case FSCTL_MOVE_FILE: Status = VfatMoveFile(IrpContext); break; + case FSCTL_ROS_QUERY_LCN_MAPPING: + Status = VfatRosQueryLcnMapping(IrpContext); + break; default: Status = STATUS_INVALID_DEVICE_REQUEST; } diff --git a/reactos/drivers/storage/class2/class2.c b/reactos/drivers/storage/class2/class2.c index d09fe6454db..97d21c29873 100644 --- a/reactos/drivers/storage/class2/class2.c +++ b/reactos/drivers/storage/class2/class2.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: class2.c,v 1.38 2003/07/12 13:10:45 ekohl Exp $ +/* $Id: class2.c,v 1.39 2003/08/27 21:28:08 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -441,6 +441,31 @@ ScsiClassDeviceControl(IN PDEVICE_OBJECT DeviceObject, InputBufferLength = Stack->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = Stack->Parameters.DeviceIoControl.OutputBufferLength; + if (IoControlCode == IOCTL_SCSI_GET_DUMP_POINTERS) + { + PDUMP_POINTERS DumpPointers; + + if (OutputBufferLength < sizeof(DUMP_POINTERS)) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_BUFFER_TOO_SMALL); + } + DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer; + + /* Initialize next stack location for call to the port driver */ + NextStack = IoGetNextIrpStackLocation(Irp); + + NextStack->Parameters = Stack->Parameters; + NextStack->MajorFunction = Stack->MajorFunction; + NextStack->MinorFunction = Stack->MinorFunction; + + /* Call port driver */ + return(IoCallDriver(DeviceExtension->PortDeviceObject, + Irp)); + } if (IoControlCode == IOCTL_SCSI_GET_ADDRESS) { PSCSI_ADDRESS ScsiAddress; diff --git a/reactos/drivers/storage/diskdump/.cvsignore b/reactos/drivers/storage/diskdump/.cvsignore new file mode 100644 index 00000000000..905450c3198 --- /dev/null +++ b/reactos/drivers/storage/diskdump/.cvsignore @@ -0,0 +1,8 @@ +base.tmp +junk.tmp +temp.exp +diskdump.coff +*.o +*.sym +*.sys +*.map diff --git a/reactos/drivers/storage/diskdump/Makefile b/reactos/drivers/storage/diskdump/Makefile new file mode 100644 index 00000000000..68b33455bd0 --- /dev/null +++ b/reactos/drivers/storage/diskdump/Makefile @@ -0,0 +1,19 @@ +# $Id: Makefile,v 1.1 2003/08/27 21:28:08 dwelch Exp $ + +PATH_TO_TOP = ../../.. + +TARGET_BOOTSTRAP = yes + +TARGET_TYPE = export_driver + +TARGET_NAME = diskdump + +TARGET_DDKLIBS = + +TARGET_OBJECTS = $(TARGET_NAME).o diskdump_helper.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/reactos/drivers/storage/diskdump/diskdump.c b/reactos/drivers/storage/diskdump/diskdump.c new file mode 100644 index 00000000000..25925d63157 --- /dev/null +++ b/reactos/drivers/storage/diskdump/diskdump.c @@ -0,0 +1,432 @@ +/* + * ReactOS kernel + * Copyright (C) 2001, 2002, 2003 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: diskdump.c,v 1.1 2003/08/27 21:28:08 dwelch Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/storage/diskdump/diskdump.c + * PURPOSE: Dumping crash data to the pagefile + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include "../scsiport/scsiport_int.h" + +#define NDEBUG +#include + +#define VERSION "0.0.1" + +/* PROTOTYPES ***************************************************************/ + +NTSTATUS STDCALL +DiskDumpPrepare(PDEVICE_OBJECT StorageDevice, PDUMP_POINTERS DumpPointers); +VOID +DiskDumpScsiInvalid(VOID); +VOID +_DiskDumpScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, + IN PVOID HwDeviceExtension, + ...); +NTSTATUS STDCALL +DiskDumpInit(VOID); +NTSTATUS STDCALL +DiskDumpFinish(VOID); +NTSTATUS STDCALL +DiskDumpWrite(LARGE_INTEGER StartAddress, PMDL Mdl); + +typedef VOID (*SCSIPORTNOTIFICATION)(IN SCSI_NOTIFICATION_TYPE NotificationType, + IN PVOID HwDeviceExtension, + ...); + +/* GLOBALS ******************************************************************/ + +MM_CORE_DUMP_FUNCTIONS DiskDumpFunctions = + { + DiskDumpPrepare, + DiskDumpInit, + DiskDumpWrite, + DiskDumpFinish, + }; + +typedef struct +{ + PCH Name; + ULONG Ordinal; + PVOID OldFunction; + PVOID NewFunction; +} SUBSTITUTE_EXPORT; + +static SCSI_REQUEST_BLOCK CoreDumpSrb; +static DUMP_POINTERS CoreDumpPointers; +static PDEVICE_OBJECT CoreDumpClassDevice; +static PDEVICE_EXTENSION CoreDumpClass2DeviceExtension; +static PDEVICE_OBJECT CoreDumpPortDevice; +static SCSI_PORT_DEVICE_EXTENSION* CoreDumpPortDeviceExtension; +BOOLEAN IsDumping = FALSE; +static PDRIVER_OBJECT DiskDumpDriver; +static UCHAR DiskDumpSenseData[SENSE_BUFFER_SIZE]; +static BOOLEAN IrqComplete, IrqNextRequest; +PVOID OldScsiPortNotification; +static SUBSTITUTE_EXPORT DiskDumpExports[] = + { + {"ScsiPortConvertPhysicalAddressToUlong", 2, NULL, NULL}, + {"ScsiPortConvertUlongToPhysicalAddress", 3, NULL, NULL}, + {"ScsiPortFreeDeviceBase", 5, NULL, DiskDumpScsiInvalid}, + {"ScsiPortGetBusData", 6, NULL, DiskDumpScsiInvalid}, + {"ScsiPortGetDeviceBase", 7, DiskDumpScsiInvalid}, + {"ScsiPortInitialize", 13, NULL, DiskDumpScsiInvalid}, + {"ScsiPortNotification", 17, NULL, _DiskDumpScsiPortNotification}, + {"ScsiPortReadPortBufferUlong", 19, NULL}, + {"ScsiPortReadPortBufferUshort", 20, NULL}, + {"ScsiPortReadPortUchar", 21, NULL, NULL}, + {"ScsiPortReadPortUshort", 23, NULL, NULL}, + {"ScsiPortStallExecution", 31, NULL, NULL}, + {"ScsiPortWritePortBufferUlong", 34, NULL}, + {"ScsiPortWritePortBufferUshort", 35, NULL}, + {"ScsiPortWritePortUchar", 36, NULL, NULL}, + {"ScsiDebugPrint", 0, NULL, NULL}, + }; + +/* FUNCTIONS ****************************************************************/ + + + +VOID +DiskDumpScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, + IN PVOID HwDeviceExtension, + ...) +{ + if (NotificationType == RequestComplete) + { + IrqComplete = TRUE; + } + if (NotificationType == NextRequest) + { + IrqNextRequest = TRUE; + } +} + +VOID +DiskDumpScsiInvalid(VOID) +{ + DbgPrint("DISKDUMP: Error: Miniport called a function not supported at dump time.\n"); + KeBugCheck(0); +} + +VOID STDCALL +DiskDumpBuildRequest(LARGE_INTEGER StartingOffset, PMDL Mdl) +{ + LARGE_INTEGER StartingBlock; + PSCSI_REQUEST_BLOCK Srb; + PCDB Cdb; + ULONG LogicalBlockAddress; + USHORT TransferBlocks; + + /* Calculate logical block address */ + StartingBlock.QuadPart = StartingOffset.QuadPart >> CoreDumpClass2DeviceExtension->SectorShift; + LogicalBlockAddress = (ULONG)StartingBlock.u.LowPart; + + DPRINT("Logical block address: %lu\n", LogicalBlockAddress); + + /* Allocate and initialize an SRB */ + Srb = &CoreDumpSrb; + + Srb->SrbFlags = 0; + Srb->Length = sizeof(SCSI_REQUEST_BLOCK); //SCSI_REQUEST_BLOCK_SIZE; + Srb->OriginalRequest = NULL; + Srb->PathId = CoreDumpClass2DeviceExtension->PathId; + Srb->TargetId = CoreDumpClass2DeviceExtension->TargetId; + Srb->Lun = CoreDumpClass2DeviceExtension->Lun; + Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + Srb->DataBuffer = Mdl->MappedSystemVa; + Srb->DataTransferLength = PAGE_SIZE; + Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; + Srb->QueueSortKey = LogicalBlockAddress; + + Srb->SenseInfoBuffer = DiskDumpSenseData; + Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; + + Srb->TimeOutValue = + ((Srb->DataTransferLength + 0xFFFF) >> 16) * CoreDumpClass2DeviceExtension->TimeOutValue; + + Srb->SrbStatus = SRB_STATUS_SUCCESS; + Srb->ScsiStatus = 0; + Srb->NextSrb = 0; + + Srb->CdbLength = 10; + Cdb = (PCDB)Srb->Cdb; + + /* Initialize ATAPI packet (12 bytes) */ + RtlZeroMemory(Cdb, MAXIMUM_CDB_SIZE); + + Cdb->CDB10.LogicalUnitNumber = CoreDumpClass2DeviceExtension->Lun; + TransferBlocks = (USHORT)(PAGE_SIZE >> + CoreDumpClass2DeviceExtension->SectorShift); + + /* Copy little endian values into CDB in big endian format */ + Cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte3; + Cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte2; + Cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte1; + Cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte0; + + Cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&TransferBlocks)->Byte1; + Cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&TransferBlocks)->Byte0; + + + /* Write Command. */ + Srb->SrbFlags |= SRB_FLAGS_DATA_OUT; + Cdb->CDB10.OperationCode = SCSIOP_WRITE; + + /* Leave caching disabled. */ +} + +BOOLEAN STDCALL +DiskDumpIsr(PKINTERRUPT Interrupt, PVOID ServiceContext) +{ + if (!CoreDumpPortDeviceExtension->HwInterrupt(&CoreDumpPortDeviceExtension->MiniPortDeviceExtension)) + { + return(FALSE); + } + return(TRUE); +} + +NTSTATUS STDCALL +DiskDumpInit(VOID) +{ + KIRQL CurrentIrql = KeGetCurrentIrql(); + IsDumping = TRUE; + if (CurrentIrql >= CoreDumpPortDeviceExtension->Interrupt->SynchLevel) + { + DbgPrint("DISKDUMP: Error: Crash inside high priority interrupt routine.\n"); + return(STATUS_UNSUCCESSFUL); + } + CoreDumpPortDeviceExtension->Interrupt->ServiceRoutine = DiskDumpIsr; + + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +DiskDumpFinish(VOID) +{ + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +DiskDumpWrite(LARGE_INTEGER Address, PMDL Mdl) +{ + KIRQL OldIrql, OldIrql2; + KIRQL CurrentIrql = KeGetCurrentIrql(); + + if (CurrentIrql < (CoreDumpPortDeviceExtension->Interrupt->SynchLevel - 1)) + { + KeRaiseIrql(CoreDumpPortDeviceExtension->Interrupt->SynchLevel - 1, &OldIrql); + } + + /* Adjust the address for the start of the partition. */ + Address.QuadPart += + (CoreDumpClass2DeviceExtension->StartingOffset.QuadPart + CoreDumpClass2DeviceExtension->DMByteSkew); + + /* Assume the device is always able to transfer a page so no need to split up the transfer. */ + + /* Build an SRB to describe the write. */ + DiskDumpBuildRequest(Address, Mdl); + + /* Start i/o on the HBA. */ + IrqComplete = IrqNextRequest = FALSE; + KeRaiseIrql(CoreDumpPortDeviceExtension->Interrupt->SynchLevel, &OldIrql2); + if (!CoreDumpPortDeviceExtension->HwStartIo(&CoreDumpPortDeviceExtension->MiniPortDeviceExtension, + &CoreDumpSrb)) + { + KeLowerIrql(OldIrql); + DbgPrint("DISKDUMP: Error: Miniport HwStartIo failed.\n"); + return(STATUS_UNSUCCESSFUL); + } + KeLowerIrql(OldIrql2); + + /* Wait for the miniport to finish. */ + __asm__ ("sti\n\t"); + while (!IrqComplete || !IrqNextRequest) + { + __asm__ ("hlt\n\t"); + } + if (CurrentIrql < (CoreDumpPortDeviceExtension->Interrupt->SynchLevel - 1)) + { + KeLowerIrql(OldIrql); + } + __asm__("cli\n\t"); + + /* Check the result. */ + if (SRB_STATUS(CoreDumpSrb.SrbStatus) != SRB_STATUS_SUCCESS) + { + DbgPrint("DISKDUMP: Error: SRB failed.\n"); + return(STATUS_UNSUCCESSFUL); + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +DiskDumpPrepare(PDEVICE_OBJECT StorageDevice, PDUMP_POINTERS DumpPointers) +{ + PIMAGE_NT_HEADERS NtHeader; + PVOID ImportDirectory; + ULONG ImportDirectorySize; + PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory; + PVOID DriverBase; + PCH Name; + ULONG i; + ULONG Hint; + PVOID* ImportAddressList; + PULONG FunctionNameList; + + /* Save the information from the kernel. */ + CoreDumpClassDevice = StorageDevice; + CoreDumpPointers = *DumpPointers; + CoreDumpClass2DeviceExtension = (PDEVICE_EXTENSION)CoreDumpClassDevice->DeviceExtension; + CoreDumpPortDevice = DumpPointers->DeviceObject; + CoreDumpPortDeviceExtension = CoreDumpPortDevice->DeviceExtension; + + /* Replace all the miniport driver's imports with our functions. */ + DriverBase = CoreDumpPortDevice->DriverObject->DriverStart; + NtHeader = RtlImageNtHeader(DriverBase); + ImportDirectory = RtlImageDirectoryEntryToData(DriverBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_IMPORT, + &ImportDirectorySize); + if (ImportDirectory == NULL || ImportDirectorySize == 0) + { + DbgPrint("DISKDUMP: Error: Miniport has no imports?\n"); + return(STATUS_UNSUCCESSFUL); + } + /* Process each import module */ + ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)ImportDirectory; + DPRINT("Processeing import directory at %p\n", ImportModuleDirectory); + while (ImportModuleDirectory->dwRVAModuleName) + { + /* Check to make sure that import lib is kernel */ + Name = (PCHAR) DriverBase + ImportModuleDirectory->dwRVAModuleName; + + if (strcmp(Name, "scsiport.sys") != 0) + { + DbgPrint("DISKDUMP: Warning: Miniport has illegal imports.\n"); + ImportModuleDirectory++; + continue; + } + + /* Get the import address list */ + ImportAddressList = (PVOID *) ((PUCHAR)DriverBase + + ImportModuleDirectory->dwRVAFunctionAddressList); + + /* Get the list of functions to import */ + if (ImportModuleDirectory->dwRVAFunctionNameList != 0) + { + FunctionNameList = (PULONG) ((PUCHAR)DriverBase + + ImportModuleDirectory->dwRVAFunctionNameList); + } + else + { + FunctionNameList = (PULONG) ((PUCHAR)DriverBase + + ImportModuleDirectory->dwRVAFunctionAddressList); + } + /* Walk through function list and fixup addresses */ + while (*FunctionNameList != 0L) + { + if ((*FunctionNameList) & 0x80000000) // hint + { + Name = NULL; + + Hint = (*FunctionNameList) & 0xffff; + } + else // hint-name + { + Name = (PCHAR)((DWORD)DriverBase + + *FunctionNameList + 2); + Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList); + } + DPRINT(" Hint:%04x Name:%s\n", Hint, pName); + + for (i = 0; i < (sizeof(DiskDumpExports) / sizeof(DiskDumpExports[0])); i++) + { + if (DiskDumpExports[i].Ordinal == Hint || + (Name != NULL && strcmp(DiskDumpExports[i].Name, Name) == 0)) + { + break; + } + } + if (i == (sizeof(DiskDumpExports) / sizeof(DiskDumpExports[0]))) + { + DbgPrint("DISKDUMP: Error: Miniport imports unknown symbol %s.\n", Name); + return(STATUS_UNSUCCESSFUL); + } + if (strcmp(Name, "ScsiPortNotification") == 0) + { + OldScsiPortNotification = *ImportAddressList; + } + DiskDumpExports[i].OldFunction = *ImportAddressList; + if (DiskDumpExports[i].NewFunction != NULL) + { + *ImportAddressList = DiskDumpExports[i].NewFunction; + } + + ImportAddressList++; + FunctionNameList++; + } + ImportModuleDirectory++; + } + return(STATUS_SUCCESS); +} + +/********************************************************************** + * NAME EXPORTED + * DriverEntry + * + * DESCRIPTION + * This function initializes the driver, locates and claims + * hardware resources, and creates various NT objects needed + * to process I/O requests. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DriverObject + * System allocated Driver Object for this driver + * + * RegistryPath + * Name of registry driver service key + * + * RETURN VALUE + * Status + */ + +NTSTATUS STDCALL +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DiskDumpDriver = DriverObject; + return(STATUS_SUCCESS); +} + + +/* EOF */ diff --git a/reactos/drivers/storage/diskdump/diskdump.def b/reactos/drivers/storage/diskdump/diskdump.def new file mode 100644 index 00000000000..fd44ce89503 --- /dev/null +++ b/reactos/drivers/storage/diskdump/diskdump.def @@ -0,0 +1,7 @@ +; $Id: diskdump.def,v 1.1 2003/08/27 21:28:08 dwelch Exp $ +; +; diskdump.def - export definition file for crash dump driver +; +LIBRARY DISKDUMP.SYS +EXPORTS +DiskDumpFunctions diff --git a/reactos/drivers/storage/diskdump/diskdump.edf b/reactos/drivers/storage/diskdump/diskdump.edf new file mode 100644 index 00000000000..9f221ecb577 --- /dev/null +++ b/reactos/drivers/storage/diskdump/diskdump.edf @@ -0,0 +1,7 @@ +; $Id: diskdump.edf,v 1.1 2003/08/27 21:28:08 dwelch Exp $ +; +; diskdump.edf - export definition file for crash dump driver +; +LIBRARY DISKDUMP.SYS +EXPORTS +DiskDumpFunctions diff --git a/reactos/drivers/storage/diskdump/diskdump.rc b/reactos/drivers/storage/diskdump/diskdump.rc new file mode 100644 index 00000000000..f3f9243d190 --- /dev/null +++ b/reactos/drivers/storage/diskdump/diskdump.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Crash Dump Disk Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "diskdump\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "diskdump.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/reactos/drivers/storage/diskdump/diskdump_helper.S b/reactos/drivers/storage/diskdump/diskdump_helper.S new file mode 100644 index 00000000000..761ee7c61e5 --- /dev/null +++ b/reactos/drivers/storage/diskdump/diskdump_helper.S @@ -0,0 +1,9 @@ +.globl __DiskDumpScsiPortNotification +__DiskDumpScsiPortNotification: + cmp $0, _IsDumping + je .l1 + jmp _DiskDumpScsiPortNotification +.l1: + jmp *_OldScsiPortNotification +.L2: + jmp .L2 diff --git a/reactos/drivers/storage/scsiport/scsiport_int.h b/reactos/drivers/storage/scsiport/scsiport_int.h new file mode 100644 index 00000000000..6743523b853 --- /dev/null +++ b/reactos/drivers/storage/scsiport/scsiport_int.h @@ -0,0 +1,70 @@ +/* + * SCSI_PORT_TIMER_STATES + * + * DESCRIPTION + * An enumeration containing the states in the timer DFA + */ +typedef enum _SCSI_PORT_TIMER_STATES +{ + IDETimerIdle, + IDETimerCmdWait, + IDETimerResetWaitForBusyNegate, + IDETimerResetWaitForDrdyAssert +} SCSI_PORT_TIMER_STATES; + + +typedef struct _SCSI_PORT_DEVICE_BASE +{ + LIST_ENTRY List; + + PVOID MappedAddress; + ULONG NumberOfBytes; + SCSI_PHYSICAL_ADDRESS IoAddress; + ULONG SystemIoBusNumber; +} SCSI_PORT_DEVICE_BASE, *PSCSI_PORT_DEVICE_BASE; + +/* + * SCSI_PORT_DEVICE_EXTENSION + * + * DESCRIPTION + * First part of the port objects device extension. The second + * part is the miniport-specific device extension. + */ + +typedef struct _SCSI_PORT_DEVICE_EXTENSION +{ + ULONG Length; + ULONG MiniPortExtensionSize; + PORT_CONFIGURATION_INFORMATION PortConfig; + ULONG PortNumber; + + KSPIN_LOCK IrpLock; + KSPIN_LOCK SpinLock; + PKINTERRUPT Interrupt; + PIRP CurrentIrp; + ULONG IrpFlags; + + SCSI_PORT_TIMER_STATES TimerState; + LONG TimerCount; + + BOOLEAN Initializing; + + LIST_ENTRY DeviceBaseListHead; + + ULONG PortBusInfoSize; + PSCSI_ADAPTER_BUS_INFO PortBusInfo; + + PIO_SCSI_CAPABILITIES PortCapabilities; + + PDEVICE_OBJECT DeviceObject; + PCONTROLLER_OBJECT ControllerObject; + + PHW_STARTIO HwStartIo; + PHW_INTERRUPT HwInterrupt; + + PSCSI_REQUEST_BLOCK OriginalSrb; + SCSI_REQUEST_BLOCK InternalSrb; + SENSE_DATA InternalSenseData; + + UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */ +} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION; diff --git a/reactos/include/ddk/ntddscsi.h b/reactos/include/ddk/ntddscsi.h index 70bc8e6a8b9..2f52cd29814 100644 --- a/reactos/include/ddk/ntddscsi.h +++ b/reactos/include/ddk/ntddscsi.h @@ -1,4 +1,4 @@ -/* $Id: ntddscsi.h,v 1.3 2003/06/22 16:35:58 ekohl Exp $ +/* $Id: ntddscsi.h,v 1.4 2003/08/27 21:28:08 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -132,6 +132,11 @@ typedef struct _SCSI_PASS_THROUGH_DIRECT #define SCSI_IOCTL_DATA_IN 1 #define SCSI_IOCTL_DATA_UNSPECIFIED 2 +typedef struct _DUMP_POINTERS +{ + PVOID DeviceObject; +} DUMP_POINTERS, *PDUMP_POINTERS; + #endif /* __STORAGE_INCLUDE_NTDDSCSI_H */ /* EOF */ diff --git a/reactos/include/ddk/ntifs.h b/reactos/include/ddk/ntifs.h index 4cda7db60e5..8a1a5efe220 100644 --- a/reactos/include/ddk/ntifs.h +++ b/reactos/include/ddk/ntifs.h @@ -13,6 +13,14 @@ CcRosInitializeFileCache (PFILE_OBJECT FileObject, NTSTATUS STDCALL CcRosReleaseFileCache (PFILE_OBJECT FileObject); +#define FSCTL_ROS_QUERY_LCN_MAPPING \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 63, METHOD_BUFFERED, FILE_ANY_ACCESS) + +typedef struct _ROS_QUERY_LCN_MAPPING +{ + LARGE_INTEGER LcnDiskOffset; +} ROS_QUERY_LCN_MAPPING, *PROS_QUERY_LCN_MAPPING; + #include #include diff --git a/reactos/include/napi/core.h b/reactos/include/napi/core.h index ca13d207a27..8548bb01fe1 100644 --- a/reactos/include/napi/core.h +++ b/reactos/include/napi/core.h @@ -2,9 +2,12 @@ #define __INCLUDE_NAPI_CORE_H #include "../ntoskrnl/include/internal/ke.h" +#include #define MM_CORE_DUMP_HEADER_MAGIC (0xdeafbead) #define MM_CORE_DUMP_HEADER_VERSION (0x1) + +#define MM_CORE_DUMP_TYPE_NONE (0x0) #define MM_CORE_DUMP_TYPE_MINIMAL (0x1) #define MM_CORE_DUMP_TYPE_FULL (0x2) @@ -21,15 +24,12 @@ typedef struct _MM_CORE_DUMP_HEADER ULONG PhysicalMemorySize; } MM_CORE_DUMP_HEADER, *PMM_CORE_DUMP_HEADER; -typedef struct _MM_DUMP_POINTERS +typedef struct MM_CORE_DUMP_FUNCTIONS { - PVOID Context; - NTSTATUS (*DeviceInit)(PVOID Context); - NTSTATUS (*DeviceWrite)(PVOID Context, ULONG Block, PMDL Mdl); - NTSTATUS (*DeviceFinish)(PVOID Context); -} MM_DUMP_POINTERS, *PMM_DUMP_POINTERS; - -#define FSCTL_GET_DUMP_BLOCK_MAP (('R' << 24) | 0xF1) -#define IOCTL_GET_DUMP_POINTERS (('R' << 24) | 0xF2) + NTSTATUS STDCALL (*DumpPrepare)(PDEVICE_OBJECT DeviceObject, PDUMP_POINTERS DumpPointers); + NTSTATUS STDCALL (*DumpInit)(VOID); + NTSTATUS STDCALL (*DumpWrite)(LARGE_INTEGER Address, PMDL Mdl); + NTSTATUS STDCALL (*DumpFinish)(VOID); +} MM_CORE_DUMP_FUNCTIONS, *PMM_CORE_DUMP_FUNCTIONS; #endif /* __INCLUDE_NAPI_CORE_H */ diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index aae07039245..9ccd4659c74 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -646,5 +646,9 @@ VOID MmRawDeleteVirtualMapping(PVOID Address); VOID MiStopPagerThread(VOID); +NTSTATUS +MmCreateVirtualMappingDump(PVOID Address, + ULONG flProtect, + PHYSICAL_ADDRESS PhysicalAddress); #endif diff --git a/reactos/ntoskrnl/ke/bug.c b/reactos/ntoskrnl/ke/bug.c index c08d5b2e471..79496636f80 100644 --- a/reactos/ntoskrnl/ke/bug.c +++ b/reactos/ntoskrnl/ke/bug.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: bug.c,v 1.37 2003/08/24 12:08:16 dwelch Exp $ +/* $Id: bug.c,v 1.38 2003/08/27 21:28:08 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/bug.c @@ -94,6 +94,7 @@ KeBugCheckWithTf(ULONG BugCheckCode, { PRTL_MESSAGE_RESOURCE_ENTRY Message; NTSTATUS Status; + KIRQL OldIrql; /* Make sure we're switching back to the blue screen and print messages on it */ HalReleaseDisplayOwnership(); @@ -103,6 +104,10 @@ KeBugCheckWithTf(ULONG BugCheckCode, } __asm__("cli\n\t"); + if (KeGetCurrentIrql() < DISPATCH_LEVEL) + { + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + } DbgPrint("Bug detected (code %x param %x %x %x %x)\n", BugCheckCode, BugCheckParameter1, @@ -174,12 +179,17 @@ KeBugCheckEx(ULONG BugCheckCode, { PRTL_MESSAGE_RESOURCE_ENTRY Message; NTSTATUS Status; + KIRQL OldIrql; /* Make sure we're switching back to the blue screen and print messages on it */ HalReleaseDisplayOwnership(); KdDebugState |= KD_DEBUG_SCREEN; __asm__("cli\n\t"); + if (KeGetCurrentIrql() < DISPATCH_LEVEL) + { + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + } DbgPrint("Bug detected (code %x param %x %x %x %x)\n", BugCheckCode, BugCheckParameter1, diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 4a40ea2937d..e631a94b85b 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: main.c,v 1.169 2003/08/24 12:08:16 dwelch Exp $ +/* $Id: main.c,v 1.170 2003/08/27 21:28:08 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/main.c @@ -51,6 +51,7 @@ #include #include #include +#include #ifdef HALDBG #include @@ -78,6 +79,7 @@ static ULONG FirstKrnlPhysAddr; static ULONG LastKrnlPhysAddr; static ULONG LastKernelAddress; volatile BOOLEAN Initialized = FALSE; +extern ULONG MmCoreDumpType; extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; @@ -384,6 +386,22 @@ ExpInitializeExecutive(VOID) p2 += 12; NoBootScreen = TRUE; } + else if (!_strnicmp(p2, "CRASHDUMP", 9)) + { + p2 += 9; + if (*p2 == ':') + { + p2++; + if (!_strnicmp(p2, "FULL", 4)) + { + MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL; + } + else + { + MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE; + } + } + } p1 = p2; } diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index bd00110b759..ebdcbea2cc2 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: page.c,v 1.58 2003/08/21 04:17:15 royce Exp $ +/* $Id: page.c,v 1.59 2003/08/27 21:28:08 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/i386/page.c @@ -973,6 +973,45 @@ BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address) return((!(Pte & PA_PRESENT)) && Pte != 0); } +NTSTATUS +MmCreateVirtualMappingDump(PVOID Address, + ULONG flProtect, + PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Attributes; + PULONG Pte; + NTSTATUS Status; + + if (Address < (PVOID)KERNEL_BASE) + { + DPRINT1("No process\n"); + KEBUGCHECK(0); + } + + Attributes = ProtectToPTE(flProtect); + if (!(Attributes & PA_PRESENT) && PhysicalAddress.QuadPart != 0) + { + DPRINT1("Setting physical address but not allowing access at address " + "0x%.8X with attributes %x/%x.\n", + Address, Attributes, flProtect); + KEBUGCHECK(0); + } + + Status = MmGetPageEntry2(Address, &Pte, FALSE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT)) + { + KEBUGCHECK(0); + } + *Pte = PhysicalAddress.QuadPart | Attributes; + FLUSH_TLB; + return(STATUS_SUCCESS); +} + + NTSTATUS MmCreateVirtualMappingForKernel(PVOID Address, ULONG flProtect, @@ -1117,6 +1156,8 @@ MmCreatePageFileMapping(PEPROCESS Process, return(STATUS_SUCCESS); } + + NTSTATUS MmCreateVirtualMappingUnsafe(PEPROCESS Process, PVOID Address, diff --git a/reactos/ntoskrnl/mm/pagefile.c b/reactos/ntoskrnl/mm/pagefile.c index ab4098a4e9e..c596366292c 100644 --- a/reactos/ntoskrnl/mm/pagefile.c +++ b/reactos/ntoskrnl/mm/pagefile.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: pagefile.c,v 1.34 2003/08/10 20:03:10 hbirr Exp $ +/* $Id: pagefile.c,v 1.35 2003/08/27 21:28:08 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/pagefile.c @@ -33,6 +33,7 @@ #include #include #include +#include #define NDEBUG #include @@ -92,12 +93,14 @@ static ULONG MiReservedSwapPages; */ #define MM_PAGEFILE_COMMIT_GRACE (256) -static PVOID MmCoreDumpPageFrame; -static PULONG MmCoreDumpBlockMap; +static PVOID MmCoreDumpPageFrame = NULL; static ULONG MmCoreDumpSize; -static PULONG MmCoreDumpBlockMap = NULL; -static MM_DUMP_POINTERS MmCoreDumpDeviceFuncs; -ULONG MmCoreDumpType; +static DUMP_POINTERS MmCoreDumpPointers; +static PMM_CORE_DUMP_FUNCTIONS MmCoreDumpFunctions; +static ULONG MmCoreDumpPageFile = 0xFFFFFFFF; +static ROS_QUERY_LCN_MAPPING MmCoreDumpLcnMapping; + +ULONG MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE; /* * Translate between a swap entry and a file and offset pair. @@ -279,14 +282,17 @@ MmInitPagingFile(VOID) /* * Initialize the crash dump support. */ - MmCoreDumpPageFrame = MmAllocateSection(PAGE_SIZE); - if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL) + if (MmCoreDumpType != MM_CORE_DUMP_TYPE_NONE) { - MmCoreDumpSize = MmStats.NrTotalPages * 4096 + 1024 * 1024; - } - else - { - MmCoreDumpSize = 1024 * 1024; + MmCoreDumpPageFrame = MmAllocateSection(PAGE_SIZE); + if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL) + { + MmCoreDumpSize = MmStats.NrTotalPages * 4096 + 1024 * 1024; + } + else + { + MmCoreDumpSize = 1024 * 1024; + } } } @@ -428,6 +434,33 @@ MmAllocSwapPage(VOID) return(0); } +LARGE_INTEGER STATIC +MmGetOffsetPageFile(PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers, LARGE_INTEGER Offset) +{ + ULONG j; + for (j = 0; j < RetrievalPointers->NumberOfPairs; j++) + { + if (Offset.QuadPart < RetrievalPointers->Pair[j].Vcn) + { + if (j == 0) + { + Offset.QuadPart += RetrievalPointers->Pair[0].Lcn - RetrievalPointers->StartVcn; + } + else + { + Offset.QuadPart += RetrievalPointers->Pair[j].Lcn - RetrievalPointers->Pair[j-1].Vcn; + } + break; + } + } + if (j >= RetrievalPointers->NumberOfPairs) + { + CHECKPOINT1; + KEBUGCHECK(0); + } + return(Offset); +} + NTSTATUS STDCALL MmDumpToPagingFile(ULONG BugCode, ULONG BugCodeParameter1, @@ -437,22 +470,23 @@ MmDumpToPagingFile(ULONG BugCode, PKTRAP_FRAME TrapFrame) { PMM_CORE_DUMP_HEADER Headers; - PVOID Context; NTSTATUS Status; UCHAR MdlBase[sizeof(MDL) + sizeof(PVOID)]; PMDL Mdl = (PMDL)MdlBase; PETHREAD Thread = PsGetCurrentThread(); ULONG StackSize; PULONG MdlMap; - ULONG NextOffset = 0; + LONGLONG NextOffset = 0; ULONG i; + PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers; + LARGE_INTEGER DiskOffset; - if (MmCoreDumpBlockMap == NULL) + if (MmCoreDumpPageFile == 0xFFFFFFFF) { return(STATUS_UNSUCCESSFUL); } - DbgPrint("MM: Dumping core"); + DbgPrint("\nMM: Dumping core: "); /* Prepare the dump headers. */ Headers = (PMM_CORE_DUMP_HEADER)MmCoreDumpPageFrame; @@ -482,8 +516,7 @@ MmDumpToPagingFile(ULONG BugCode, Headers->PhysicalMemorySize = MmStats.NrTotalPages * PAGE_SIZE; /* Initialize the dump device. */ - Context = MmCoreDumpDeviceFuncs.Context; - Status = MmCoreDumpDeviceFuncs.DeviceInit(Context); + MmCoreDumpFunctions->DumpInit(); if (!NT_SUCCESS(Status)) { DPRINT1("MM: Failed to initialize core dump device.\n"); @@ -501,36 +534,24 @@ MmDumpToPagingFile(ULONG BugCode, Mdl->ByteOffset = 0; MdlMap = (PULONG)(Mdl + 1); + + /* Initialize the retrieval offsets. */ + RetrievalPointers = PagingFileList[MmCoreDumpPageFile]->RetrievalPointers; + /* Dump the header. */ MdlMap[0] = MmGetPhysicalAddress(MmCoreDumpPageFrame).u.LowPart; - Status = MmCoreDumpDeviceFuncs.DeviceWrite(Context, - MmCoreDumpBlockMap[NextOffset], - Mdl); + DiskOffset = MmGetOffsetPageFile(RetrievalPointers, (LARGE_INTEGER)0LL); + DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart; + Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl); if (!NT_SUCCESS(Status)) { DPRINT1("MM: Failed to write core dump header\n."); + return(Status); } - NextOffset++; - DbgPrint("."); - - /* Write out the kernel mode stack of the faulting thread. */ - for (i = 0; i < (StackSize / PAGE_SIZE); i++) - { - Mdl->MappedSystemVa = (PVOID)(Thread->Tcb.StackLimit + (i * PAGE_SIZE)); - MdlMap[0] = MmGetPhysicalAddress(Mdl->MappedSystemVa).u.LowPart; - Status = - MmCoreDumpDeviceFuncs.DeviceWrite(Context, - MmCoreDumpBlockMap[NextOffset], - Mdl); - if (!NT_SUCCESS(Status)) - { - DPRINT1("MM: Failed to write page to core dump.\n"); - return(Status); - } - DbgPrint("."); - NextOffset++; - } + NextOffset += PAGE_SIZE;; + DbgPrint("00"); + /* Write out the contents of physical memory. */ if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL) { @@ -539,24 +560,139 @@ MmDumpToPagingFile(ULONG BugCode, LARGE_INTEGER PhysicalAddress; PhysicalAddress.QuadPart = i * PAGE_SIZE; MdlMap[0] = i * PAGE_SIZE; - MmCreateVirtualMappingForKernel(MmCoreDumpPageFrame, - PAGE_READWRITE, - PhysicalAddress); - Status = - MmCoreDumpDeviceFuncs.DeviceWrite(Context, - MmCoreDumpBlockMap[NextOffset], - Mdl); + MmCreateVirtualMappingDump(MmCoreDumpPageFrame, + PAGE_READWRITE, + PhysicalAddress); + DiskOffset = MmGetOffsetPageFile(RetrievalPointers, + (LARGE_INTEGER)NextOffset); + DiskOffset.QuadPart += MmCoreDumpLcnMapping.LcnDiskOffset.QuadPart; + Status = MmCoreDumpFunctions->DumpWrite(DiskOffset, Mdl); if (!NT_SUCCESS(Status)) { DPRINT1("MM: Failed to write page to core dump.\n"); return(Status); } - DbgPrint("."); - NextOffset++; + if ((i % ((1024*1024) / PAGE_SIZE)) == 0) + { + DbgPrint("\b\b%.2d", i / ((1024*1024)/PAGE_SIZE)); + } + NextOffset += PAGE_SIZE; } } DbgPrint("\n"); + MmCoreDumpFunctions->DumpFinish(); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +MmInitializeCrashDump(HANDLE PageFileHandle, ULONG PageFileNum) +{ + PFILE_OBJECT PageFile; + PDEVICE_OBJECT PageFileDevice; + NTSTATUS Status; + PIRP Irp; + KEVENT Event; + IO_STATUS_BLOCK Iosb; + UNICODE_STRING DiskDumpName; + ANSI_STRING ProcName; + PIO_STACK_LOCATION StackPtr; + PMODULE_OBJECT ModuleObject; + + Status = ZwFsControlFile(PageFileHandle, + 0, + NULL, + NULL, + &Iosb, + FSCTL_ROS_QUERY_LCN_MAPPING, + NULL, + 0, + &MmCoreDumpLcnMapping, + sizeof(ROS_QUERY_LCN_MAPPING)); + if (!NT_SUCCESS(Status) || + Iosb.Information != sizeof(ROS_QUERY_LCN_MAPPING)) + { + return(Status); + } + + /* Get the underlying storage device. */ + Status = + ObReferenceObjectByHandle(PageFileHandle, + FILE_ALL_ACCESS, + NULL, + KernelMode, + (PVOID*)&PageFile, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + PageFileDevice = PageFile->Vpb->RealDevice; + + /* Get the dump pointers. */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_DUMP_POINTERS, + PageFileDevice, + NULL, + 0, + &MmCoreDumpPointers, + sizeof(MmCoreDumpPointers), + FALSE, + &Event, + &Iosb); + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = PageFile; + StackPtr->DeviceObject = PageFileDevice; + StackPtr->Parameters.DeviceIoControl.InputBufferLength = 0; + StackPtr->Parameters.DeviceIoControl.OutputBufferLength = sizeof(MmCoreDumpPointers); + + Status = IoCallDriver(PageFileDevice,Irp); + if (Status == STATUS_PENDING) + { + Status = KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + } + if (Status != STATUS_SUCCESS || + Iosb.Information != sizeof(MmCoreDumpPointers)) + { + ObDereferenceObject(PageFile); + return(Status); + } + + /* Load the diskdump driver. */ + RtlInitUnicodeStringFromLiteral(&DiskDumpName, L"DiskDump"); + ModuleObject = LdrGetModuleObject(&DiskDumpName); + if (ModuleObject == NULL) + { + return(STATUS_OBJECT_NAME_NOT_FOUND); + } + RtlInitAnsiString(&ProcName, "DiskDumpFunctions"); + Status = LdrGetProcedureAddress(ModuleObject->Base, + &ProcName, + 0, + (PVOID*)&MmCoreDumpFunctions); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(PageFile); + return(Status); + } + + /* Prepare for disk dumping. */ + Status = MmCoreDumpFunctions->DumpPrepare(PageFileDevice, + &MmCoreDumpPointers); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(PageFile); + return(Status); + } + + MmCoreDumpPageFile = PageFileNum; + ObDereferenceObject(PageFile); + *(PULONG)0 = 0; return(STATUS_SUCCESS); } @@ -795,54 +931,11 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, KeReleaseSpinLock(&PagingFileListLock, oldIrql); /* Check whether this pagefile can be a crash dump target. */ - if (PagingFile->CurrentSize.QuadPart >= MmCoreDumpSize && - MmCoreDumpBlockMap != NULL) + if (MmCoreDumpType != MM_CORE_DUMP_TYPE_NONE && + PagingFile->CurrentSize.QuadPart >= MmCoreDumpSize && + MmCoreDumpPageFile == 0xFFFFFFFF) { - MmCoreDumpBlockMap = - ExAllocatePool(NonPagedPool, - (MmCoreDumpSize / PAGE_SIZE) * sizeof(ULONG)); - if (MmCoreDumpBlockMap == NULL) - { - DPRINT1("Failed to allocate block map.\n"); - NtClose(FileHandle); - return(STATUS_SUCCESS); - } - Status = ZwFsControlFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatus, - FSCTL_GET_DUMP_BLOCK_MAP, - &MmCoreDumpSize, - sizeof(ULONG), - MmCoreDumpBlockMap, - (MmCoreDumpSize / PAGE_SIZE) * sizeof(ULONG)); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get dump block map (Status %X)\n", Status); - NtClose(FileHandle); - ExFreePool(MmCoreDumpBlockMap); - MmCoreDumpBlockMap = NULL; - return(STATUS_SUCCESS); - } - Status = ZwDeviceIoControlFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatus, - IOCTL_GET_DUMP_POINTERS, - NULL, - 0, - &MmCoreDumpDeviceFuncs, - sizeof(MmCoreDumpDeviceFuncs)); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get dump block map (Status %X)\n", Status); - NtClose(FileHandle); - ExFreePool(MmCoreDumpBlockMap); - MmCoreDumpBlockMap = NULL; - return(STATUS_SUCCESS); - } + MmInitializeCrashDump(FileHandle, i); } NtClose(FileHandle); diff --git a/reactos/ntoskrnl/ntoskrnl.def b/reactos/ntoskrnl/ntoskrnl.def index eaa99dd9eb9..c79ac9d2042 100644 --- a/reactos/ntoskrnl/ntoskrnl.def +++ b/reactos/ntoskrnl/ntoskrnl.def @@ -1,4 +1,4 @@ -; $Id: ntoskrnl.def,v 1.162 2003/08/19 23:59:08 dwelch Exp $ +; $Id: ntoskrnl.def,v 1.163 2003/08/27 21:28:08 dwelch Exp $ ; ; reactos/ntoskrnl/ntoskrnl.def ; @@ -771,6 +771,7 @@ RtlGetDefaultCodePage@8 RtlGetGroupSecurityDescriptor@12 RtlGetOwnerSecurityDescriptor@12 RtlImageNtHeader@4 +RtlImageDirectoryEntryToData@16 RtlInitAnsiString@8 RtlInitCodePageTable@8 RtlInitString@8 diff --git a/reactos/ntoskrnl/ntoskrnl.edf b/reactos/ntoskrnl/ntoskrnl.edf index 78912352377..ece5d476d65 100644 --- a/reactos/ntoskrnl/ntoskrnl.edf +++ b/reactos/ntoskrnl/ntoskrnl.edf @@ -1,4 +1,4 @@ -; $Id: ntoskrnl.edf,v 1.150 2003/08/19 23:59:08 dwelch Exp $ +; $Id: ntoskrnl.edf,v 1.151 2003/08/27 21:28:08 dwelch Exp $ ; ; reactos/ntoskrnl/ntoskrnl.def ; @@ -770,6 +770,7 @@ RtlGetDefaultCodePage=RtlGetDefaultCodePage@8 RtlGetGroupSecurityDescriptor=RtlGetGroupSecurityDescriptor@12 RtlGetOwnerSecurityDescriptor=RtlGetOwnerSecurityDescriptor@12 RtlImageNtHeader=RtlImageNtHeader@4 +RtlImageDirectoryEntryToData=RtlImageDirectoryEntryToData@16 RtlInitAnsiString=RtlInitAnsiString@8 RtlInitCodePageTable=RtlInitCodePageTable@8 RtlInitString=RtlInitString@8