|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
ramdisk.h
Abstract:
This file includes extension declaration for the RAM Disk driver for Whistler.
Author:
Chuck Lenzmeier (chuckl) 2001
Environment:
Kernel mode only.
Notes:
Revision History:
--*/
//
// Pool allocation tag.
//
// ISSUE: Add this to pooltags.txt.
//
#define RAMDISK_TAG_GENERAL 'dmaR'
//
// I/O completion macro. Set the IoStatus field of the IRP and complete it.
//
// Note: IO_NO_INCREMENT is used to complete the IRP. If you want an
// increment (such as IO_DISK_INCREMENT), do it manually.
//
#define COMPLETE_REQUEST( _status, _information, _irp ) { \
ASSERT( (_irp) != NULL ); \ ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); \ _irp->IoStatus.Status = (_status); \ _irp->IoStatus.Information = (_information); \ IoCompleteRequest( (_irp), IO_NO_INCREMENT ); \ }
//
// Types of devices serviced by this driver. BusFdo is the bus enumeration
// FDO. DiskPdo is a RAM disk device PDO.
//
typedef enum { RamdiskDeviceTypeBusFdo, RamdiskDeviceTypeDiskPdo } RAMDISK_DEVICE_TYPE;
//
// States that a device can be in.
//
typedef enum { RamdiskDeviceStateStopped, RamdiskDeviceStateWorking, RamdiskDeviceStatePendingStop, RamdiskDeviceStatePendingRemove, RamdiskDeviceStateSurpriseRemoved, RamdiskDeviceStateRemoved, RamdiskDeviceStateRemovedAndNotReported, RamdiskDeviceStateDeleted, RamdiskDeviceStateMaximum } RAMDISK_DEVICE_STATE;
//
// Bits for the DISK_EXTENSION.Status field.
//
#define RAMDISK_STATUS_PREVENT_REMOVE 0x00000001
#define RAMDISK_STATUS_CLAIMED 0x00000002
//
// Saved path to the driver's registry key.
//
extern UNICODE_STRING DriverRegistryPath;
//
// Should RAM disks be marked as removable? TRUE makes the hotplug applet play
// a sound when RAM disks appear and disappear. FALSE (the default) keeps it
// quiet.
//
extern BOOLEAN MarkRamdisksAsRemovable;
#if SUPPORT_DISK_NUMBERS
//
// Disk numbering. The disk number is only maintained so that it can be
// returned from IOCTL_STORAGE_GET_DEVICE_NUMBER.
//
#define MINIMUM_DISK_NUMBERS_BITMAP_SIZE 64
#define DEFAULT_DISK_NUMBERS_BITMAP_SIZE 256
#define MAXIMUM_DISK_NUMBERS_BITMAP_SIZE (64 * 1024)
extern ULONG DiskNumbersBitmapSize;
#endif // SUPPORT_DISK_NUMBERS
//
// Disk image windowing.
//
#define MINIMUM_MINIMUM_VIEW_COUNT 2
#define MAXIMUM_MINIMUM_VIEW_COUNT MAXIMUM_MAXIMUM_VIEW_COUNT
#define DEFAULT_DEFAULT_VIEW_COUNT 16
#define MAXIMUM_DEFAULT_VIEW_COUNT MAXIMUM_MAXIMUM_VIEW_COUNT
#define DEFAULT_MAXIMUM_VIEW_COUNT 64
#define MAXIMUM_MAXIMUM_VIEW_COUNT 256
#define MINIMUM_MINIMUM_VIEW_LENGTH (64 * 1024)
#define MAXIMUM_MINIMUM_VIEW_LENGTH MAXIMUM_MAXIMUM_VIEW_LENGTH
#define DEFAULT_DEFAULT_VIEW_LENGTH ( 1 * 1024 * 1024)
#define MAXIMUM_DEFAULT_VIEW_LENGTH MAXIMUM_MAXIMUM_VIEW_LENGTH
#define DEFAULT_MAXIMUM_VIEW_LENGTH (256 * 1024 * 1024)
#define MAXIMUM_MAXIMUM_VIEW_LENGTH ( 1 * 1024 * 1024 * 1024)
#define MINIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH ( 16 * 1024 * 1024)
#define DEFAULT_MAXIMUM_PER_DISK_VIEW_LENGTH (256 * 1024 * 1024)
#define MAXIMUM_MAXIMUM_PER_DISK_VIEW_LENGTH MAXULONG
extern ULONG MinimumViewCount; extern ULONG DefaultViewCount; extern ULONG MaximumViewCount; extern ULONG MinimumViewLength; extern ULONG DefaultViewLength; extern ULONG MaximumViewLength; extern ULONG MaximumPerDiskViewLength;
typedef struct _VIEW {
//
// Views are kept in two lists.
//
// The by-offset list is sorted in ascending order by the base offset of
// the view. (Unmapped views have offset and length both 0 and are always
// at the front of the by-offset list.)
//
// The MRU list is sorted with the most recently used views at the front.
// When we need to unmap a view and remap a new view, we take a free view
// from the back of the MRU list.
//
LIST_ENTRY ByOffsetListEntry; LIST_ENTRY ByMruListEntry;
//
// Address is the virtual address at which the view is mapped.
//
// Offset is the offset from the start of the file that backs the RAM disk.
//
// Length if the length of the view. Normally this is the same as the
// ViewLength field in the disk extension, but it can be less for the
// view at the end of the disk image. (If we permanently map the first
// few pages of the disk image [to keep the boot sector mapped], then the
// first view will also be "short".
//
PUCHAR Address;
ULONGLONG Offset; ULONG Length;
//
// ReferenceCount indicates how many active operations are using the view.
// When ReferenceCount is 0, the view is a candidate for replacement.
//
// Permanent indicates whether the view is to remain mapped permanently.
// If Permanent is TRUE, the ReferenceCount field is not used. (Permanent
// is intended to be used to keep a view permanently mapped to the boot
// sector. Currently we don't implement any permanent views.)
//
ULONG ReferenceCount;
BOOLEAN Permanent;
} VIEW, *PVIEW;
//
// The device extensions for BusFdo and DiskPdo devices have a common header.
//
typedef struct _COMMON_EXTENSION {
//
// Device type and state.
//
RAMDISK_DEVICE_TYPE DeviceType; RAMDISK_DEVICE_STATE DeviceState;
//
// Fdo points to the FDO for the device. For the BusFdo, Fdo is the device
// that we created for the BusFdo (see RamdiskAddDevice()). For a DiskPdo,
// Fdo is the BusFdo.
//
// Pdo points to the PDO for the device. For the BusFdo, Pdo is the PDO
// that was passed in to RamdiskAddDevice(). For a DiskPdo, Pdo is the
// device that we created for the DiskPdo (see RamdiskCreateDiskDevice()).
//
// LowerDeviceObject points to the device object below this device in the
// device stack. For the BusFdo, LowerDeviceObject is returned by the call
// to IoAttachDeviceToDeviceStack() in RamdiskAddDevice(). For a DiskPdo,
// LowerDeviceObject is the BusFdo.
//
PDEVICE_OBJECT Fdo; PDEVICE_OBJECT Pdo; PDEVICE_OBJECT LowerDeviceObject;
//
// RemoveLock prevents removal of a device while it is busy.
//
IO_REMOVE_LOCK RemoveLock;
//
// InterfaceString is returned by IoRegisterDeviceInterface().
//
UNICODE_STRING InterfaceString;
//
// DeviceName is the name of the device.
//
UNICODE_STRING DeviceName;
//
// Mutex controls access to various fields in the device extension.
//
FAST_MUTEX Mutex;
} COMMON_EXTENSION, *PCOMMON_EXTENSION;
//
// The BusFdo has the following device extension. (Must start with a
// COMMON_EXTENSION!)
//
typedef struct _BUS_EXTENSION {
COMMON_EXTENSION ;
#if SUPPORT_DISK_NUMBERS
//
// DiskNumbersBitmap is a bitmap indicating which disk numbers are in
// use by active RAM disks. Bit number 0 of the bitmap corresponds to
// disk number 1.
//
RTL_BITMAP DiskNumbersBitmap; PULONG DiskNumbersBitmapBuffer;
#endif // SUPPORT_DISK_NUMBERS
//
// DiskPdoList is a list of all existing RAM disk devices.
//
LIST_ENTRY DiskPdoList;
} BUS_EXTENSION, *PBUS_EXTENSION;
//
// Each DiskPdo has the following device extension. (Must start with a
// COMMON_EXTENSION!)
//
typedef struct _DISK_EXTENSION {
COMMON_EXTENSION ;
//
// DiskPdoListEntry links the DiskPdo into the BusFdo's DiskPdoList.
//
LIST_ENTRY DiskPdoListEntry;
//
// DiskGuid is the GUID assigned to the disk by the creator.
// DiskGuidFormatted is the GUID in printable format.
//
GUID DiskGuid; UNICODE_STRING DiskGuidFormatted;
//
// DosSymLink is the DosDevices name associated with the device. This is
// only valid if Options.NoDosDevice is FALSE.
//
UNICODE_STRING DosSymLink;
#if SUPPORT_DISK_NUMBERS
//
// DiskNumber is the number of the disk.
//
ULONG DiskNumber;
#endif // SUPPORT_DISK_NUMBERS
//
// DiskType indicates what type of disk is being emulated. (See
// RAMDISK_TYPE_xxx in ramdisku.h.)
//
ULONG DiskType;
//
// Status indicates whether the disk has been claimed and whether removal
// is prevented. (See RAMDISK_STATUS_xxx above.)
//
ULONG Status;
//
// Options specifies various create options for the disk: is it readonly;
// is it fixed or removable; does it have a drive letter; etc.
//
RAMDISK_CREATE_OPTIONS Options;
//
// DiskLength is the length of the disk image. DiskOffset is the offset
// from the start of the backing file or memory block to the actual start
// of the disk image. (DiskLength does NOT include DiskOffset.)
//
// FileRelativeEndOfDisk is the sum of DiskOffset + DiskLength. It is
// calculated once to avoid recalculating it every time a view is mapped.
//
ULONGLONG DiskLength; ULONG DiskOffset;
ULONGLONG FileRelativeEndOfDisk;
//
// BasePage indicates the base physical page when DiskType is
// RAMDISK_TYPE_BOOT_DISK. For file-backed RAM disks, SectionObject
// is a referenced pointer to the section. For virtual floppies,
// BaseAddress indicates the base virtual address.
//
ULONG_PTR BasePage; PVOID SectionObject; PVOID BaseAddress;
//
// DriveLetter is the drive letter assigned to the boot disk.
//
WCHAR DriveLetter;
//
// MarkedForDeletion indicates whether user mode has informed us
// that it is about to delete the device.
//
BOOLEAN MarkedForDeletion;
//
// Mapped image windowing.
//
// ViewCount is the number of views that are available. ViewLength is
// length of each view.
//
ULONG ViewCount; ULONG ViewLength;
//
// ViewDescriptors points to an array of view descriptors allocated when
// the disk was created.
//
PVIEW ViewDescriptors;
//
// ViewsByOffset and ViewsByMru are lists of view descriptors (see the
// description of the VIEW struct).
//
LIST_ENTRY ViewsByOffset; LIST_ENTRY ViewsByMru;
//
// ViewSemaphore is used to wake up threads that are waiting for a free
// view (so they can remap a new view). ViewWaiterCount is the number of
// threads that are currently waiting for a free view. The semaphore is
// "kicked" by this amount when a view is freed.
//
KSEMAPHORE ViewSemaphore; ULONG ViewWaiterCount;
//
// ISSUE: Do we really need XIP_BOOT_PARAMETERS?
//
//XIP_BOOT_PARAMETERS BootParameters;
//
// ViewSemaphore is used to wake up threads that are waiting for a free
// view (so they can remap a new view). ViewWaiterCount is the number of
//BIOS_PARAMETER_BLOCK BiosParameters;
//
// Disk geometry.
//
ULONG BytesPerSector; ULONG SectorsPerTrack;
ULONG NumberOfCylinders; ULONG TracksPerCylinder; ULONG BytesPerCylinder;
ULONG HiddenSectors;
//
// For file-backed RAM disks, FileName is the NT name of the backing file.
//
WCHAR FileName[1];
} DISK_EXTENSION, *PDISK_EXTENSION;
#if !defined( _UCHAR_DEFINED_ )
#define _UCHAR_DEFINED_
//
// The following types and macros are used to help unpack the packed and
// misaligned fields found in the Bios parameter block
//
typedef union _UCHAR1 { UCHAR Uchar[1]; UCHAR ForceAlignment; } UCHAR1, *PUCHAR1;
typedef union _UCHAR2 { UCHAR Uchar[2]; USHORT ForceAlignment; } UCHAR2, *PUCHAR2;
typedef union _UCHAR4 { UCHAR Uchar[4]; ULONG ForceAlignment; } UCHAR4, *PUCHAR4;
#define CopyUchar1(Dst,Src) { \
*((UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src)); \ }
#define CopyUchar2(Dst,Src) { \
*((UCHAR2 *)(Dst)) = *((UNALIGNED UCHAR2 *)(Src)); \ }
#define CopyU2char(Dst,Src) { \
*((UNALIGNED UCHAR2 *)(Dst)) = *((UCHAR2 *)(Src)); \ }
#define CopyUchar4(Dst,Src) { \
*((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)((ULONG_PTR)(Src))); \ }
#define CopyU4char(Dst, Src) { \
*((UNALIGNED UCHAR4 *)(Dst)) = *((UCHAR4 *)(Src)); \ }
#endif // _UCHAR_DEFINED_
#define cOEM 8
#define cLABEL 11
#define cSYSID 8
//
// Defines the packet and unpacked BPB structs used for extraction of geometry
// from the boot sector of the ramdisk image
//
typedef struct _PACKED_BIOS_PARAMETER_BLOCK { UCHAR BytesPerSector[2]; // offset = 0x000
UCHAR SectorsPerCluster[1]; // offset = 0x002
UCHAR ReservedSectors[2]; // offset = 0x003
UCHAR Fats[1]; // offset = 0x005
UCHAR RootEntries[2]; // offset = 0x006
UCHAR Sectors[2]; // offset = 0x008
UCHAR Media[1]; // offset = 0x00A
UCHAR SectorsPerFat[2]; // offset = 0x00B
UCHAR SectorsPerTrack[2]; // offset = 0x00D
UCHAR Heads[2]; // offset = 0x00F
UCHAR HiddenSectors[4]; // offset = 0x011
UCHAR LargeSectors[4]; // offset = 0x015
UCHAR BigSectorsPerFat[4]; // offset = 0x019 25
UCHAR ExtFlags[2]; // offset = 0x01D 29
UCHAR FS_Version[2]; // offset = 0x01F 31
UCHAR RootDirStrtClus[4]; // offset = 0x021 33
UCHAR FSInfoSec[2]; // offset = 0x025 37
UCHAR BkUpBootSec[2]; // offset = 0x027 39
UCHAR Reserved[12]; // offset = 0x029 41
} PACKED_BIOS_PARAMETER_BLOCK; // sizeof = 0x035 53
typedef PACKED_BIOS_PARAMETER_BLOCK *PPACKED_BIOS_PARAMETER_BLOCK;
typedef struct BIOS_PARAMETER_BLOCK { USHORT BytesPerSector; UCHAR SectorsPerCluster; USHORT ReservedSectors; UCHAR Fats; USHORT RootEntries; USHORT Sectors; UCHAR Media; USHORT SectorsPerFat; USHORT SectorsPerTrack; USHORT Heads; ULONG HiddenSectors; ULONG LargeSectors; ULONG BigSectorsPerFat; USHORT ExtFlags; USHORT FS_Version; ULONG RootDirStrtClus; USHORT FSInfoSec; USHORT BkUpBootSec; } BIOS_PARAMETER_BLOCK; typedef BIOS_PARAMETER_BLOCK *PBIOS_PARAMETER_BLOCK;
//
// Macro to unpack packed bpb
//
#define UnpackBios(Bios,Pbios) { \
CopyUchar2(&((Bios)->BytesPerSector), (Pbios)->BytesPerSector ); \ CopyUchar1(&((Bios)->SectorsPerCluster), (Pbios)->SectorsPerCluster); \ CopyUchar2(&((Bios)->ReservedSectors), (Pbios)->ReservedSectors ); \ CopyUchar1(&((Bios)->Fats), (Pbios)->Fats ); \ CopyUchar2(&((Bios)->RootEntries), (Pbios)->RootEntries ); \ CopyUchar2(&((Bios)->Sectors), (Pbios)->Sectors ); \ CopyUchar1(&((Bios)->Media), (Pbios)->Media ); \ CopyUchar2(&((Bios)->SectorsPerFat), (Pbios)->SectorsPerFat ); \ CopyUchar2(&((Bios)->SectorsPerTrack), (Pbios)->SectorsPerTrack ); \ CopyUchar2(&((Bios)->Heads), (Pbios)->Heads ); \ CopyUchar4(&((Bios)->HiddenSectors), (Pbios)->HiddenSectors ); \ CopyUchar4(&((Bios)->LargeSectors), (Pbios)->LargeSectors ); \ }
typedef struct _PACKED_EXTENDED_BIOS_PARAMETER_BLOCK { UCHAR IntelNearJumpCommand[1]; UCHAR BootStrapJumpOffset[2]; UCHAR OemData[cOEM]; PACKED_BIOS_PARAMETER_BLOCK Bpb; UCHAR PhysicalDrive[1]; // 0 = removable, 80h = fixed
UCHAR CurrentHead[1]; // used for dirty partition info
UCHAR Signature[1]; // boot signature
UCHAR SerialNumber[4]; // volume serial number
UCHAR Label[cLABEL]; // volume label, padded with spaces
UCHAR SystemIdText[cSYSID]; // system ID, (e.g. FAT or HPFS)
UCHAR StartBootCode; // first byte of boot code
} PACKED_EXTENDED_BIOS_PARAMETER_BLOCK, *PPACKED_EXTENDED_BIOS_PARAMETER_BLOCK;
//
// Global variables.
//
extern PDEVICE_OBJECT RamdiskBusFdo;
//
// External functions implemented in ioctl.c.
//
NTSTATUS RamdiskDeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS RamdiskCreateRamDisk ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN BOOLEAN AccessCheckOnly );
NTSTATUS RamdiskCreateDiskDevice ( IN PBUS_EXTENSION BusExtension, IN PRAMDISK_CREATE_INPUT CreateInput, IN BOOLEAN AccessCheckOnly, OUT PDISK_EXTENSION *DiskExtension );
NTSTATUS RamdiskGetDriveLayout ( PIRP Irp, PDISK_EXTENSION DiskExtension );
NTSTATUS RamdiskGetPartitionInfo ( PIRP Irp, PDISK_EXTENSION DiskExtension );
NTSTATUS RamdiskSetPartitionInfo ( PIRP Irp, PDISK_EXTENSION DiskExtension );
//
// External functions implemented in pnp.c.
//
NTSTATUS RamdiskPnp ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS RamdiskPower ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS RamdiskAddDevice ( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo );
BOOLEAN CreateRegistryDisks ( IN BOOLEAN CheckPresenceOnly );
//
// External functions implemented in ramdisk.c.
//
VOID RamdiskWorkerThread ( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context );
NTSTATUS RamdiskFlushBuffersReal ( IN PDISK_EXTENSION DiskExtension );
//
// External functions implemented in readwrite.c.
//
NTSTATUS RamdiskReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS RamdiskReadWriteReal ( IN PIRP Irp, IN PDISK_EXTENSION DiskExtension );
//
// External functions implemented in scsi.c.
//
NTSTATUS RamdiskScsi ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS RamdiskScsiExecuteNone ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PSCSI_REQUEST_BLOCK Srb, ULONG ControlCode );
NTSTATUS RamdiskScsiExecuteIo ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PSCSI_REQUEST_BLOCK Srb, ULONG ControlCode );
//
// External functions implemented in utils.c.
//
NTSTATUS SendIrpToThread ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
PUCHAR RamdiskMapPages ( IN PDISK_EXTENSION DiskExtension, IN ULONGLONG Offset, IN ULONG RequestedLength, OUT PULONG ActualLength );
VOID RamdiskUnmapPages ( IN PDISK_EXTENSION DiskExtension, IN PUCHAR Va, IN ULONGLONG Offset, IN ULONG Length );
NTSTATUS RamdiskFlushViews ( IN PDISK_EXTENSION DiskExtension );
|