Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

512 lines
14 KiB

  1. /*++
  2. Copyright (c) 1991 - 2002 Microsoft Corporation
  3. Module Name:
  4. ## ## ### ## # ## ## ##### ### ## ## #### ##### #####
  5. ### ### ## # ### # ## ## ## ## ### ### ### ## # ## ## ## ##
  6. ######## ### #### # ## ## ## ## ## ## ######## ## ## ## ## ##
  7. # ### ## ### # #### #### ##### ## ## # ### ## ## ## ## ## ##
  8. # # ## ### # ### #### #### ####### # # ## ## ##### #####
  9. # ## # ## # ## ## ## ## ## ## # ## ## ## # ## ##
  10. # ## ### # # ## ## ## ## ## # ## ## #### ## ##
  11. Abstract:
  12. This module contains the entire implementation of
  13. the virtual NVRAM miniport.
  14. @@BEGIN_DDKSPLIT
  15. Author:
  16. Wesley Witt (wesw) 1-Oct-2001
  17. @@END_DDKSPLIT
  18. Environment:
  19. Kernel mode only.
  20. Notes:
  21. --*/
  22. #include "msnvram.h"
  23. #ifdef ALLOC_PRAGMA
  24. #pragma alloc_text(INIT,DriverEntry)
  25. #endif
  26. NTSTATUS
  27. ReadNvramData(
  28. IN PDEVICE_EXTENSION DeviceExtension,
  29. IN OUT PUCHAR *NvramDataBuffer,
  30. IN OUT PULONG NvramDataBufferLength
  31. )
  32. {
  33. NTSTATUS Status;
  34. *NvramDataBuffer = NULL;
  35. *NvramDataBufferLength = 0;
  36. Status = SaPortReadBinaryRegistryValue(
  37. DeviceExtension,
  38. L"NvramData",
  39. NULL,
  40. NvramDataBufferLength
  41. );
  42. if (Status != STATUS_BUFFER_TOO_SMALL) {
  43. REPORT_ERROR( SA_DEVICE_NVRAM, "SaPortReadBinaryRegistryValue failed", Status );
  44. goto exit;
  45. }
  46. *NvramDataBuffer = (PUCHAR) SaPortAllocatePool( DeviceExtension, *NvramDataBufferLength );
  47. if (*NvramDataBuffer == NULL) {
  48. Status = STATUS_INSUFFICIENT_RESOURCES;
  49. REPORT_ERROR( SA_DEVICE_NVRAM, "Could not allocate pool for registry read", Status );
  50. goto exit;
  51. }
  52. Status = SaPortReadBinaryRegistryValue(
  53. DeviceExtension,
  54. L"NvramData",
  55. *NvramDataBuffer,
  56. NvramDataBufferLength
  57. );
  58. if (!NT_SUCCESS(Status)) {
  59. REPORT_ERROR( SA_DEVICE_NVRAM, "SaPortReadBinaryRegistryValue failed", Status );
  60. goto exit;
  61. }
  62. Status = STATUS_SUCCESS;
  63. exit:
  64. return Status;
  65. }
  66. VOID
  67. MsNvramIoWorker(
  68. IN PDEVICE_OBJECT DeviceObject,
  69. IN PVOID Context
  70. )
  71. {
  72. NTSTATUS Status;
  73. PMSNVRAM_WORK_ITEM WorkItem = (PMSNVRAM_WORK_ITEM) Context;
  74. PDEVICE_EXTENSION DeviceExtension = WorkItem->DeviceExtension;
  75. PUCHAR RegistryValue = NULL;
  76. ULONG RegistryValueLength = 0;
  77. PUCHAR DataPtr;
  78. if (WorkItem->IoFunction == IRP_MJ_READ) {
  79. Status = ReadNvramData(
  80. DeviceExtension,
  81. &RegistryValue,
  82. &RegistryValueLength
  83. );
  84. if (!NT_SUCCESS(Status)) {
  85. REPORT_ERROR( SA_DEVICE_NVRAM, "ReadNvramData failed", Status );
  86. goto exit;
  87. }
  88. if (WorkItem->StartingOffset > RegistryValueLength) {
  89. Status = STATUS_INVALID_PARAMETER_1;
  90. REPORT_ERROR( SA_DEVICE_NVRAM, "Starting offset is greater than the registry value data length", Status );
  91. goto exit;
  92. }
  93. if (WorkItem->DataBufferLength + WorkItem->StartingOffset > RegistryValueLength) {
  94. Status = STATUS_INVALID_PARAMETER_2;
  95. REPORT_ERROR( SA_DEVICE_NVRAM, "I/O request is past the valid data length", Status );
  96. goto exit;
  97. }
  98. DataPtr = RegistryValue + WorkItem->StartingOffset;
  99. RegistryValueLength = WorkItem->DataBufferLength;
  100. RtlCopyMemory( WorkItem->DataBuffer, DataPtr, RegistryValueLength );
  101. Status = STATUS_SUCCESS;
  102. } else if (WorkItem->IoFunction == IRP_MJ_WRITE) {
  103. Status = ReadNvramData(
  104. DeviceExtension,
  105. &RegistryValue,
  106. &RegistryValueLength
  107. );
  108. if (!NT_SUCCESS(Status)) {
  109. if (RegistryValue != NULL) {
  110. SaPortFreePool( DeviceExtension, RegistryValue );
  111. }
  112. RegistryValueLength = MAX_NVRAM_SIZE_BYTES;
  113. RegistryValue = (PUCHAR) SaPortAllocatePool( DeviceExtension, RegistryValueLength );
  114. if (RegistryValue == NULL) {
  115. Status = STATUS_INSUFFICIENT_RESOURCES;
  116. REPORT_ERROR( SA_DEVICE_NVRAM, "Could not allocate pool for registry read", Status );
  117. goto exit;
  118. }
  119. RtlZeroMemory( RegistryValue, RegistryValueLength );
  120. }
  121. RtlCopyMemory( RegistryValue + WorkItem->StartingOffset, WorkItem->DataBuffer, WorkItem->DataBufferLength );
  122. Status = SaPortWriteBinaryRegistryValue(
  123. DeviceExtension,
  124. L"NvramData",
  125. RegistryValue,
  126. RegistryValueLength
  127. );
  128. }
  129. exit:
  130. if (!NT_SUCCESS(Status)) {
  131. RegistryValueLength = 0;
  132. }
  133. if (RegistryValue != NULL) {
  134. SaPortFreePool( DeviceExtension, RegistryValue );
  135. }
  136. SaPortCompleteRequest( DeviceExtension, NULL, RegistryValueLength, Status, FALSE );
  137. IoFreeWorkItem( WorkItem->WorkItem );
  138. SaPortFreePool( DeviceExtension, WorkItem );
  139. }
  140. NTSTATUS
  141. MsNvramRead(
  142. IN PVOID DeviceExtensionIn,
  143. IN PIRP Irp,
  144. IN PVOID FsContext,
  145. IN LONGLONG StartingOffset,
  146. IN PVOID DataBuffer,
  147. IN ULONG DataBufferLength
  148. )
  149. /*++
  150. Routine Description:
  151. This routine processes the read requests for the local display miniport.
  152. Arguments:
  153. DeviceExtensionIn - Miniport's device extension
  154. StartingOffset - Starting offset for the I/O
  155. DataBuffer - Pointer to the data buffer
  156. DataBufferLength - Length of the data buffer in bytes
  157. Return Value:
  158. NT status code.
  159. --*/
  160. {
  161. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  162. PMSNVRAM_WORK_ITEM WorkItem;
  163. WorkItem = (PMSNVRAM_WORK_ITEM) SaPortAllocatePool( DeviceExtension, sizeof(MSNVRAM_WORK_ITEM) );
  164. if (WorkItem == NULL) {
  165. return STATUS_INSUFFICIENT_RESOURCES;
  166. }
  167. WorkItem->WorkItem = IoAllocateWorkItem( DeviceExtension->DeviceObject );
  168. if (WorkItem->WorkItem == NULL) {
  169. SaPortFreePool( DeviceExtension, WorkItem );
  170. return STATUS_INSUFFICIENT_RESOURCES;
  171. }
  172. WorkItem->IoFunction = IRP_MJ_READ;
  173. WorkItem->DataBuffer = DataBuffer;
  174. WorkItem->DataBufferLength = DataBufferLength;
  175. WorkItem->StartingOffset = StartingOffset;
  176. WorkItem->DeviceExtension = DeviceExtension;
  177. IoQueueWorkItem( WorkItem->WorkItem, MsNvramIoWorker, DelayedWorkQueue, WorkItem );
  178. return STATUS_PENDING;
  179. }
  180. NTSTATUS
  181. MsNvramWrite(
  182. IN PVOID DeviceExtensionIn,
  183. IN PIRP Irp,
  184. IN PVOID FsContext,
  185. IN LONGLONG StartingOffset,
  186. IN PVOID DataBuffer,
  187. IN ULONG DataBufferLength
  188. )
  189. /*++
  190. Routine Description:
  191. This routine processes the write requests for the local display miniport.
  192. Arguments:
  193. DeviceExtensionIn - Miniport's device extension
  194. StartingOffset - Starting offset for the I/O
  195. DataBuffer - Pointer to the data buffer
  196. DataBufferLength - Length of the data buffer in bytes
  197. Return Value:
  198. NT status code.
  199. --*/
  200. {
  201. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  202. PMSNVRAM_WORK_ITEM WorkItem;
  203. WorkItem = (PMSNVRAM_WORK_ITEM) SaPortAllocatePool( DeviceExtension, sizeof(MSNVRAM_WORK_ITEM) );
  204. if (WorkItem == NULL) {
  205. return STATUS_INSUFFICIENT_RESOURCES;
  206. }
  207. WorkItem->WorkItem = IoAllocateWorkItem( DeviceExtension->DeviceObject );
  208. if (WorkItem->WorkItem == NULL) {
  209. SaPortFreePool( DeviceExtension, WorkItem );
  210. return STATUS_INSUFFICIENT_RESOURCES;
  211. }
  212. WorkItem->IoFunction = IRP_MJ_WRITE;
  213. WorkItem->DataBuffer = DataBuffer;
  214. WorkItem->DataBufferLength = DataBufferLength;
  215. WorkItem->StartingOffset = StartingOffset;
  216. WorkItem->DeviceExtension = DeviceExtension;
  217. IoQueueWorkItem( WorkItem->WorkItem, MsNvramIoWorker, DelayedWorkQueue, WorkItem );
  218. return STATUS_PENDING;
  219. }
  220. NTSTATUS
  221. MsNvramDeviceIoctl(
  222. IN PVOID DeviceExtensionIn,
  223. IN PIRP Irp,
  224. IN PVOID FsContext,
  225. IN ULONG FunctionCode,
  226. IN PVOID InputBuffer,
  227. IN ULONG InputBufferLength,
  228. IN PVOID OutputBuffer,
  229. IN ULONG OutputBufferLength
  230. )
  231. /*++
  232. Routine Description:
  233. This function is called by the SAPORT driver so that
  234. the mini-port driver can service an IOCTL call.
  235. Arguments:
  236. DeviceExtension - A pointer to the mini-port's device extension
  237. FunctionCode - The IOCTL function code
  238. InputBuffer - Pointer to the input buffer, contains the data sent down by the I/O
  239. InputBufferLength - Length in bytes of the InputBuffer
  240. OutputBuffer - Pointer to the output buffer, contains the data generated by this call
  241. OutputBufferLength - Length in bytes of the OutputBuffer
  242. Context:
  243. IRQL: IRQL PASSIVE_LEVEL, arbitrary thread context
  244. Return Value:
  245. If the function succeeds, it must return STATUS_SUCCESS.
  246. Otherwise, it must return one of the error status values defined in ntstatus.h.
  247. --*/
  248. {
  249. NTSTATUS Status = STATUS_SUCCESS;
  250. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  251. PSA_NVRAM_CAPS NvramCaps = NULL;
  252. switch (FunctionCode) {
  253. case FUNC_SA_GET_VERSION:
  254. *((PULONG)OutputBuffer) = SA_INTERFACE_VERSION;
  255. break;
  256. case FUNC_SA_GET_CAPABILITIES:
  257. NvramCaps = (PSA_NVRAM_CAPS)OutputBuffer;
  258. NvramCaps->SizeOfStruct = sizeof(SA_NVRAM_CAPS);
  259. NvramCaps->NvramSize = MAX_NVRAM_SIZE;
  260. break;
  261. default:
  262. Status = STATUS_NOT_SUPPORTED;
  263. REPORT_ERROR( SA_DEVICE_NVRAM, "Unsupported device control", Status );
  264. break;
  265. }
  266. return Status;
  267. }
  268. NTSTATUS
  269. MsNvramHwInitialize(
  270. IN PDEVICE_OBJECT DeviceObject,
  271. IN PIRP Irp,
  272. IN PVOID DeviceExtensionIn,
  273. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResources,
  274. IN ULONG PartialResourceCount
  275. )
  276. /*++
  277. Routine Description:
  278. This function is called by the SAPORT driver so that
  279. the mini-port driver can initialize it's hardware
  280. resources.
  281. Arguments:
  282. DeviceObject - Pointer to the target device object.
  283. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  284. DeviceExtension - A pointer to the mini-port's device extension.
  285. PartialResources - Pointer to the translated resources alloacted by the system.
  286. PartialResourceCount - The number of resources in the PartialResources array.
  287. Context:
  288. IRQL: IRQL PASSIVE_LEVEL, system thread context
  289. Return Value:
  290. If the function succeeds, it must return STATUS_SUCCESS.
  291. Otherwise, it must return one of the error status values defined in ntstatus.h.
  292. --*/
  293. {
  294. NTSTATUS Status = STATUS_SUCCESS;
  295. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  296. ULONG RegistryType;
  297. ULONG RegistryDataLength;
  298. PULONG NvramData = NULL;
  299. DeviceExtension->DeviceObject = DeviceObject;
  300. //
  301. // Ensure that the NVRAM store in the registry is actually good
  302. //
  303. Status = SaPortGetRegistryValueInformation(
  304. DeviceExtension,
  305. L"NvramData",
  306. &RegistryType,
  307. &RegistryDataLength
  308. );
  309. if ((!NT_SUCCESS(Status)) || RegistryType != REG_BINARY || RegistryDataLength != MAX_NVRAM_SIZE_BYTES) {
  310. Status = SaPortDeleteRegistryValue(
  311. DeviceExtension,
  312. L"NvramData"
  313. );
  314. if ((!NT_SUCCESS(Status)) && Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  315. REPORT_ERROR( SA_DEVICE_NVRAM, "SaPortDeleteRegistryValue failed", Status );
  316. goto exit;
  317. }
  318. NvramData = (PULONG) SaPortAllocatePool( DeviceExtension, MAX_NVRAM_SIZE_BYTES );
  319. if (NvramData == NULL) {
  320. Status = STATUS_INSUFFICIENT_RESOURCES;
  321. REPORT_ERROR( SA_DEVICE_NVRAM, "Could not allocate pool for registry read", Status );
  322. goto exit;
  323. }
  324. RtlZeroMemory( NvramData, MAX_NVRAM_SIZE_BYTES );
  325. Status = SaPortWriteBinaryRegistryValue(
  326. DeviceExtension,
  327. L"NvramData",
  328. NvramData,
  329. MAX_NVRAM_SIZE_BYTES
  330. );
  331. if (!NT_SUCCESS(Status)) {
  332. REPORT_ERROR( SA_DEVICE_NVRAM, "SaPortWriteBinaryRegistryValue failed", Status );
  333. goto exit;
  334. }
  335. }
  336. exit:
  337. if (NvramData != NULL) {
  338. SaPortFreePool( DeviceExtension, NvramData );
  339. }
  340. return Status;
  341. }
  342. NTSTATUS
  343. DriverEntry(
  344. IN PDRIVER_OBJECT DriverObject,
  345. IN PUNICODE_STRING RegistryPath
  346. )
  347. /*++
  348. Routine Description:
  349. This routine is the driver's entry point, called by the I/O system
  350. to load the driver. The driver's entry points are initialized and
  351. a mutex to control paging is initialized.
  352. In DBG mode, this routine also examines the registry for special
  353. debug parameters.
  354. Arguments:
  355. DriverObject - a pointer to the object that represents this device driver.
  356. RegistryPath - a pointer to this driver's key in the Services tree.
  357. Return Value:
  358. STATUS_SUCCESS
  359. --*/
  360. {
  361. NTSTATUS Status;
  362. SAPORT_INITIALIZATION_DATA SaPortInitData;
  363. RtlZeroMemory( &SaPortInitData, sizeof(SAPORT_INITIALIZATION_DATA) );
  364. SaPortInitData.StructSize = sizeof(SAPORT_INITIALIZATION_DATA);
  365. SaPortInitData.DeviceType = SA_DEVICE_NVRAM;
  366. SaPortInitData.HwInitialize = MsNvramHwInitialize;
  367. SaPortInitData.DeviceIoctl = MsNvramDeviceIoctl;
  368. SaPortInitData.Read = MsNvramRead;
  369. SaPortInitData.Write = MsNvramWrite;
  370. SaPortInitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
  371. Status = SaPortInitialize( DriverObject, RegistryPath, &SaPortInitData );
  372. if (!NT_SUCCESS(Status)) {
  373. REPORT_ERROR( SA_DEVICE_NVRAM, "SaPortInitialize failed\n", Status );
  374. return Status;
  375. }
  376. return STATUS_SUCCESS;
  377. }