📄 comeml.c
字号:
if (completeTheIrp)
{
IoCompleteRequest(Irp,
IO_NO_INCREMENT);
}
return ntStatus;
}
//////////////////////////////////////////////////////////////////////////
//
// Routine Description:
//
// Allocates non-paged pool memory for use by the comem device. Actual Input
// and Output comes from the IRP system buffer, and are AllocMemoryIn and
// AllocMemoryOut structures (see comemdrv.h).
// This routine keeps track of memory allocations by storing allocation
// information in the device extension. If memory has alrady been allocated
// for the comem device, this routine will return an error.
// If the entire allocation request can not be satisfied, then no allocation is
// performed (actually, the part of the allocaion that succeeds is undone).
// Callers to this funcion should also call CoMemUpdatePagetable().
//
//
// Arguments:
//
// DeviceObject - pointer to a device object
//
// Irp - pointer to an I/O Request Packet
//
// Return Value:
//
// returns status in two places: the return value, and in the output structure's
// status field. The return value is just an NTSTATUS value that most closey resembles
// the status. The output structure's status field is a comem status value as defined in
// comemdrv.h.
//
//////////////////////////////////////////////////////////////////////////
NTSTATUS
CoMemAllocContigMemory(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
AllocContigMemIn allocRequest;
AllocContigMemOut *allocMemoryOut = (AllocContigMemOut *) Irp->AssociatedIrp.SystemBuffer;
int i;
ULONG errors = FALSE;
PVOID ptr = NULL;
PDEVICE_EXTENSION deviceExtension = NULL;
NTSTATUS ntStatus = STATUS_SUCCESS;
PHYSICAL_ADDRESS maxAddress;
PHYSICAL_ADDRESS physicalAddress;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// make a copy of the input structure. The input and output
// structures share the same memory and we don't want to
// trash the input params before we're done with them
//
RtlCopyBytes(&allocRequest,
(AllocContigMemIn *) Irp->AssociatedIrp.SystemBuffer,
sizeof(AllocContigMemIn));
allocMemoryOut->status = NO_ERROR;
//
// Check the device extension to see if memory has already
// been allocated for this Comem device. If so, return an
// error
//
if (deviceExtension->systemAddr)
{
allocMemoryOut->status = ERROR_ALLOC_EXISTS;
return STATUS_UNSUCCESSFUL;
}
//
// allocate a block of RAM
//
maxAddress.LowPart=0xFFFFFFFF;
maxAddress.HighPart=0x0;
deviceExtension->bufferSize = allocRequest.size * PAGE_SIZE;
deviceExtension->systemAddr = MmAllocateContiguousMemory(deviceExtension->bufferSize,
maxAddress);
if (!deviceExtension->systemAddr)
{
CoMemKdPrint (("COMEM.SYS: ExAllocatePool failed\n"));
deviceExtension->bufferSize = 0;
allocMemoryOut->status = ERROR_MEMORY_ALLOC;
ntStatus = STATUS_NO_MEMORY;
errors = TRUE;
goto CLEANUP;
}
//
// now get a physical address and a user mode pointer for the buffer
//
physicalAddress = MmGetPhysicalAddress(deviceExtension->systemAddr);
allocMemoryOut->physAddr =
deviceExtension->physAddr = physicalAddress.LowPart;
deviceExtension->linearAddr = CoMemGetLinearPointer(deviceExtension->systemAddr,
allocRequest.size * PAGE_SIZE);
allocMemoryOut->linearAddr = (DWORD) deviceExtension->linearAddr;
CLEANUP:
if (errors)
{
CoMemDeAllocContigMemory(DeviceObject);
}
return ntStatus;
}
//////////////////////////////////////////////////////////////////////////
//
// Routine Description:
//
// Deallocates all memory that has been allocated for the comem device.
// Note: It is possible that one or more user mode apps have pointers to
// the comem memory. It is also posible that the comem device is still
// running and may be using the allocated memory regions. This routine
// does not safeguard against these conditions. Callers shoud also call
// CoMemUpdatePagetable() after deallocating memory so the comem pagetable
// reflects the true memory situation.
// This routine may be called redundantly (ie. even if no memory is allocate).
//
// Arguments:
//
// DeviceObject - pointer to a device object
//
// Return Value:
//
//
//////////////////////////////////////////////////////////////////////////
void
CoMemDeAllocContigMemory(
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
PMDL pMdl = NULL;
//
// unmap the buffer from user mode
//
if (deviceExtension->linearAddr)
{
pMdl = IoAllocateMdl(deviceExtension->systemAddr,
deviceExtension->bufferSize,
FALSE,
FALSE,
NULL);
MmBuildMdlForNonPagedPool(pMdl);
MmUnmapLockedPages(deviceExtension->linearAddr, pMdl);
deviceExtension->linearAddr = NULL;
IoFreeMdl(pMdl);
}
//
// free the buffer
//
if (deviceExtension->systemAddr)
{
MmFreeContiguousMemory(deviceExtension->systemAddr);
deviceExtension->systemAddr = NULL;
deviceExtension->physAddr = 0,0;
deviceExtension->bufferSize = 0;
}
}
//////////////////////////////////////////////////////////////////////////
//
// Routine Description:
//
// Returns a user mode pointer to the specified System buffer
//
// Warning: All system to user mode mappings must be undone before
// the application that initiated the mapping goes away. Otherwise,
// the system will bugcheck
// Arguments:
// IN PVOID SystemAddress - kernel mode address of the memory buffer to be
// mapped to user mode
// IN ULONG Length - length of the buffer pointed to by SystemAddress
//
//
// Return Value:
// user mode pointer (in the address context of the calling app) to the
// specified system buffer
//
//////////////////////////////////////////////////////////////////////////
PVOID
CoMemGetLinearPointer(
IN PVOID SystemAddress,
IN ULONG Length
)
{
PMDL pMdl = NULL;
PVOID LinearAddress = NULL;
pMdl = IoAllocateMdl(SystemAddress,
Length,
FALSE,
FALSE,
NULL);
if (!pMdl)
{
return NULL;
}
MmBuildMdlForNonPagedPool(pMdl);
//
// Using the MDL, generate a User mode virtual address for
// the allocated buffer.
//
LinearAddress = MmMapLockedPages(pMdl, UserMode);
IoFreeMdl(pMdl);
return LinearAddress;
}
//////////////////////////////////////////////////////////////////////////
//
// Routine Description:
//
// Arguments:
//
// DeviceObject - pointer to a device object
//
// Irp - pointer to an I/O Request Packet
//
// Return Value:
//
//
//////////////////////////////////////////////////////////////////////////
NTSTATUS
CoMemMapBars(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
int i;
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
CreateBarPtrOut * Output;
ULONG barLength[] = {32768,1024,32768,8};
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
Output = (CreateBarPtrOut *) Irp->AssociatedIrp.SystemBuffer;
Output->status = NO_ERROR;
//
// Check if the caller has already gotten a pointer to the BAR. If it has
// fail this call
//
if (deviceExtension->linearBaseAddr[0])
return STATUS_UNSUCCESSFUL;
//
// initialize the bar map info and the output structure
//
for (i = 0; i < COMEM_MAX_BARS; i++)
{
deviceExtension->linearBaseAddr[i] = 0;
Output->linBAR[i] = 0;
}
// MDMBUG - skip the last BAR, it's in IO space
for (i = 0; i < COMEM_MAX_BARS - 1; i++)
{
GetLinearBarPointer(deviceExtension->baseAddresses[i],
barLength[i],
&(deviceExtension->linearBaseAddr[i]));
Output->linBAR[i] = (ULONG) deviceExtension->linearBaseAddr[i];
}
return ntStatus;
}
//////////////////////////////////////////////////////////////////////////
//
// Routine Description:
//
//
// Arguments:
//
// Return Value:
//
//
//////////////////////////////////////////////////////////////////////////
void
CoMemUnmapBars(
IN PDEVICE_OBJECT DeviceObject
)
{
int i;
PDEVICE_EXTENSION deviceExtension = NULL;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// Unmap each BAR pointer
//
for (i = 0; i < COMEM_MAX_BARS; i++)
{
if (deviceExtension->linearBaseAddr[i])
{
ZwUnmapViewOfSection ((HANDLE) -1,
deviceExtension->linearBaseAddr[i]);
deviceExtension->linearBaseAddr[i] = NULL;
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// Routine Description:
//
// This is a direct cut and past from the NT DDK example program called
// mapmem. See ddk\src\general\mapmem\sys for more details.
//
// Arguments:
//
// Return Value:
//
//
//////////////////////////////////////////////////////////////////////////
NTSTATUS
GetLinearBarPointer(
IN ULONG PhysicalBarAddress,
IN ULONG Length,
IN OUT PVOID *LinearBarAddress
)
{
INTERFACE_TYPE interfaceType;
ULONG busNumber;
PHYSICAL_ADDRESS physicalAddress;
ULONG length;
UNICODE_STRING physicalMemoryUnicodeString;
OBJECT_ATTRIBUTES objectAttributes;
HANDLE physicalMemoryHandle = NULL;
PVOID PhysicalMemorySection = NULL;
ULONG inIoSpace, inIoSpace2;
NTSTATUS ntStatus;
PHYSICAL_ADDRESS physicalAddressBase;
PHYSICAL_ADDRESS physicalAddressEnd;
PHYSICAL_ADDRESS viewBase;
PHYSICAL_ADDRESS mappedLength;
BOOLEAN translateBaseAddress;
BOOLEAN translateEndAddress;
PVOID virtualAddress;
interfaceType = PCIBus;
busNumber = 0; // MDMBUG - hardcoded for now. This is the
// bus number where comem shows up on my
// Sony. Don't know about other systems.
physicalAddress.HighPart = 0;
physicalAddress.LowPart = PhysicalBarAddress & 0xFFFFFFFE;
inIoSpace = inIoSpace2 = PhysicalBarAddress & 1;
length = Length;
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -