2 * PROJECT: ReactOS Boot Loader (FreeLDR)
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: boot/freeldr/freeldr/disk/scsiport.c
5 * PURPOSE: Interface for SCSI Emulation
6 * PROGRAMMERS: Hervé Poussineau <hpoussin@reactos.org>
9 /* INCLUDES *******************************************************************/
14 DBG_DEFAULT_CHANNEL(SCSIPORT
);
26 #undef ScsiPortLogError
27 #undef ScsiPortMoveMemory
28 #undef ScsiPortWritePortBufferUchar
29 #undef ScsiPortWritePortBufferUlong
30 #undef ScsiPortWritePortBufferUshort
31 #undef ScsiPortWritePortUchar
32 #undef ScsiPortWritePortUlong
33 #undef ScsiPortWritePortUshort
34 #undef ScsiPortWriteRegisterBufferUchar
35 #undef ScsiPortWriteRegisterBufferUlong
36 #undef ScsiPortWriteRegisterBufferUshort
37 #undef ScsiPortWriteRegisterUchar
38 #undef ScsiPortWriteRegisterUlong
39 #undef ScsiPortWriteRegisterUshort
40 #undef ScsiPortReadPortBufferUchar
41 #undef ScsiPortReadPortBufferUlong
42 #undef ScsiPortReadPortBufferUshort
43 #undef ScsiPortReadPortUchar
44 #undef ScsiPortReadPortUlong
45 #undef ScsiPortReadPortUshort
46 #undef ScsiPortReadRegisterBufferUchar
47 #undef ScsiPortReadRegisterBufferUlong
48 #undef ScsiPortReadRegisterBufferUshort
49 #undef ScsiPortReadRegisterUchar
50 #undef ScsiPortReadRegisterUlong
51 #undef ScsiPortReadRegisterUshort
53 #define SCSI_PORT_NEXT_REQUEST_READY 0x0008
55 #define TAG_SCSI_DEVEXT 'DscS'
56 #define TAG_SCSI_ACCESS_RANGES 'AscS'
58 /* GLOBALS ********************************************************************/
61 VOID NTAPI
HalpInitializePciStubs(VOID
);
62 VOID NTAPI
HalpInitBusHandler(VOID
);
67 PVOID NonCachedExtension
;
74 /* SRB extension stuff */
75 ULONG SrbExtensionSize
;
76 PVOID SrbExtensionBuffer
;
78 IO_SCSI_CAPABILITIES PortCapabilities
;
80 PHW_INITIALIZE HwInitialize
;
81 PHW_STARTIO HwStartIo
;
82 PHW_INTERRUPT HwInterrupt
;
83 PHW_RESET_BUS HwResetBus
;
85 /* DMA related stuff */
86 PADAPTER_OBJECT AdapterObject
;
88 ULONG CommonBufferLength
;
90 PVOID MiniPortDeviceExtension
;
91 } SCSI_PORT_DEVICE_EXTENSION
, *PSCSI_PORT_DEVICE_EXTENSION
;
93 typedef struct tagDISKCONTEXT
96 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
101 /* Device characteristics */
103 ULONGLONG SectorOffset
;
104 ULONGLONG SectorCount
;
105 ULONGLONG SectorNumber
;
108 PSCSI_PORT_DEVICE_EXTENSION ScsiDeviceExtensions
[SCSI_MAXIMUM_BUSES
];
110 /* FUNCTIONS ******************************************************************/
117 PFOUR_BYTE Source
= (PFOUR_BYTE
)&Value
;
119 Dest
.Byte0
= Source
->Byte3
;
120 Dest
.Byte1
= Source
->Byte2
;
121 Dest
.Byte2
= Source
->Byte1
;
122 Dest
.Byte3
= Source
->Byte0
;
129 SpiSendSynchronousSrb(
130 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
131 IN PSCSI_REQUEST_BLOCK Srb
)
135 ASSERT(!(Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
));
137 /* HACK: handle lack of interrupts */
138 while (!(DeviceExtension
->InterruptFlags
& SCSI_PORT_NEXT_REQUEST_READY
))
140 KeStallExecutionProcessor(100 * 1000);
141 if (!DeviceExtension
->HwInterrupt(DeviceExtension
->MiniPortDeviceExtension
))
148 DeviceExtension
->InterruptFlags
&= ~SCSI_PORT_NEXT_REQUEST_READY
;
149 Srb
->SrbFlags
|= SRB_FLAGS_IS_ACTIVE
;
151 if (!DeviceExtension
->HwStartIo(
152 DeviceExtension
->MiniPortDeviceExtension
,
159 /* HACK: handle lack of interrupts */
160 while (Srb
->SrbFlags
& SRB_FLAGS_IS_ACTIVE
)
162 KeStallExecutionProcessor(100 * 1000);
163 if (!DeviceExtension
->HwInterrupt(DeviceExtension
->MiniPortDeviceExtension
))
170 ret
= SRB_STATUS(Srb
->SrbStatus
) == SRB_STATUS_SUCCESS
;
176 static ARC_STATUS
DiskClose(ULONG FileId
)
178 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
183 static ARC_STATUS
DiskGetFileInformation(ULONG FileId
, FILEINFORMATION
* Information
)
185 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
187 RtlZeroMemory(Information
, sizeof(*Information
));
190 * The ARC specification mentions that for partitions, StartingAddress and
191 * EndingAddress are the start and end positions of the partition in terms
192 * of byte offsets from the start of the disk.
193 * CurrentAddress is the current offset into (i.e. relative to) the partition.
195 Information
->StartingAddress
.QuadPart
= Context
->SectorOffset
* Context
->SectorSize
;
196 Information
->EndingAddress
.QuadPart
= (Context
->SectorOffset
+ Context
->SectorCount
) * Context
->SectorSize
;
197 Information
->CurrentAddress
.QuadPart
= Context
->SectorNumber
* Context
->SectorSize
;
202 static ARC_STATUS
DiskOpen(CHAR
* Path
, OPENMODE OpenMode
, ULONG
* FileId
)
204 PSCSI_REQUEST_BLOCK Srb
;
206 READ_CAPACITY_DATA ReadCapacityBuffer
;
208 DISKCONTEXT
* Context
;
209 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
210 ULONG ScsiBus
, PathId
, TargetId
, Lun
, Partition
, PathSyntax
;
212 ULONGLONG SectorOffset
= 0;
213 ULONGLONG SectorCount
;
216 if (!DissectArcPath2(Path
, &ScsiBus
, &TargetId
, &Lun
, &Partition
, &PathSyntax
))
218 if (PathSyntax
!= 0) /* scsi() format */
220 DeviceExtension
= ScsiDeviceExtensions
[ScsiBus
];
221 PathId
= ScsiBus
- DeviceExtension
->BusNum
;
223 /* Get disk capacity and sector size */
224 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
227 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
228 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
229 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
230 Srb
->PathId
= (UCHAR
)PathId
;
231 Srb
->TargetId
= (UCHAR
)TargetId
;
232 Srb
->Lun
= (UCHAR
)Lun
;
234 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
235 Srb
->DataTransferLength
= sizeof(READ_CAPACITY_DATA
);
236 Srb
->TimeOutValue
= 5; /* in seconds */
237 Srb
->DataBuffer
= &ReadCapacityBuffer
;
238 Cdb
= (PCDB
)Srb
->Cdb
;
239 Cdb
->CDB10
.OperationCode
= SCSIOP_READ_CAPACITY
;
240 if (!SpiSendSynchronousSrb(DeviceExtension
, Srb
))
245 /* Transform result to host endianness */
246 SectorCount
= ntohl(ReadCapacityBuffer
.LogicalBlockAddress
);
247 SectorSize
= ntohl(ReadCapacityBuffer
.BytesPerBlock
);
251 /* Need to offset start of disk and length */
256 Context
= ExAllocatePool(PagedPool
, sizeof(DISKCONTEXT
));
259 Context
->DeviceExtension
= DeviceExtension
;
260 Context
->PathId
= (UCHAR
)PathId
;
261 Context
->TargetId
= (UCHAR
)TargetId
;
262 Context
->Lun
= (UCHAR
)Lun
;
263 Context
->SectorSize
= SectorSize
;
264 Context
->SectorOffset
= SectorOffset
;
265 Context
->SectorCount
= SectorCount
;
266 Context
->SectorNumber
= 0;
267 FsSetDeviceSpecific(*FileId
, Context
);
272 static ARC_STATUS
DiskRead(ULONG FileId
, VOID
* Buffer
, ULONG N
, ULONG
* Count
)
274 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
275 PSCSI_REQUEST_BLOCK Srb
;
277 ULONG FullSectors
, NbSectors
;
285 FullSectors
= N
/ Context
->SectorSize
;
286 NbSectors
= (N
+ Context
->SectorSize
- 1) / Context
->SectorSize
;
287 if (Context
->SectorNumber
+ NbSectors
>= Context
->SectorCount
)
289 if (FullSectors
> 0xffff)
292 /* Read full sectors */
293 ASSERT(Context
->SectorNumber
< 0xFFFFFFFF);
294 Lba
= (ULONG
)(Context
->SectorOffset
+ Context
->SectorNumber
);
297 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
301 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
302 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
303 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
304 Srb
->PathId
= Context
->PathId
;
305 Srb
->TargetId
= Context
->TargetId
;
306 Srb
->Lun
= Context
->Lun
;
308 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
309 Srb
->DataTransferLength
= FullSectors
* Context
->SectorSize
;
310 Srb
->TimeOutValue
= 5; /* in seconds */
311 Srb
->DataBuffer
= Buffer
;
312 Cdb
= (PCDB
)Srb
->Cdb
;
313 Cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
314 Cdb
->CDB10
.LogicalUnitNumber
= Srb
->Lun
;
315 Cdb
->CDB10
.LogicalBlockByte0
= (Lba
>> 24) & 0xff;
316 Cdb
->CDB10
.LogicalBlockByte1
= (Lba
>> 16) & 0xff;
317 Cdb
->CDB10
.LogicalBlockByte2
= (Lba
>> 8) & 0xff;
318 Cdb
->CDB10
.LogicalBlockByte3
= Lba
& 0xff;
319 Cdb
->CDB10
.TransferBlocksMsb
= (FullSectors
>> 8) & 0xff;
320 Cdb
->CDB10
.TransferBlocksLsb
= FullSectors
& 0xff;
321 if (!SpiSendSynchronousSrb(Context
->DeviceExtension
, Srb
))
325 Buffer
= (PUCHAR
)Buffer
+ FullSectors
* Context
->SectorSize
;
326 N
-= FullSectors
* Context
->SectorSize
;
327 *Count
+= FullSectors
* Context
->SectorSize
;
328 Context
->SectorNumber
+= FullSectors
;
332 /* Read incomplete last sector */
337 Sector
= ExAllocatePool(PagedPool
, Context
->SectorSize
);
341 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
348 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
349 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
350 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
351 Srb
->PathId
= Context
->PathId
;
352 Srb
->TargetId
= Context
->TargetId
;
353 Srb
->Lun
= Context
->Lun
;
355 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
356 Srb
->DataTransferLength
= Context
->SectorSize
;
357 Srb
->TimeOutValue
= 5; /* in seconds */
358 Srb
->DataBuffer
= Sector
;
359 Cdb
= (PCDB
)Srb
->Cdb
;
360 Cdb
->CDB10
.OperationCode
= SCSIOP_READ
;
361 Cdb
->CDB10
.LogicalUnitNumber
= Srb
->Lun
;
362 Cdb
->CDB10
.LogicalBlockByte0
= (Lba
>> 24) & 0xff;
363 Cdb
->CDB10
.LogicalBlockByte1
= (Lba
>> 16) & 0xff;
364 Cdb
->CDB10
.LogicalBlockByte2
= (Lba
>> 8) & 0xff;
365 Cdb
->CDB10
.LogicalBlockByte3
= Lba
& 0xff;
366 Cdb
->CDB10
.TransferBlocksMsb
= 0;
367 Cdb
->CDB10
.TransferBlocksLsb
= 1;
368 if (!SpiSendSynchronousSrb(Context
->DeviceExtension
, Srb
))
373 RtlCopyMemory(Buffer
, Sector
, N
);
375 /* Context->SectorNumber remains untouched (incomplete sector read) */
382 static ARC_STATUS
DiskSeek(ULONG FileId
, LARGE_INTEGER
* Position
, SEEKMODE SeekMode
)
384 DISKCONTEXT
* Context
= FsGetDeviceSpecific(FileId
);
385 LARGE_INTEGER NewPosition
= *Position
;
392 NewPosition
.QuadPart
+= (Context
->SectorNumber
* Context
->SectorSize
);
399 if (NewPosition
.QuadPart
& (Context
->SectorSize
- 1))
402 /* Convert in number of sectors */
403 NewPosition
.QuadPart
/= Context
->SectorSize
;
404 if (NewPosition
.QuadPart
>= Context
->SectorCount
)
407 Context
->SectorNumber
= NewPosition
.QuadPart
;
411 static const DEVVTBL DiskVtbl
=
414 DiskGetFileInformation
,
423 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
424 IN PHW_INITIALIZATION_DATA HwInitData
,
425 OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
426 IN BOOLEAN ZeroStruct
)
430 /* Zero out the struct if told so */
433 /* First zero the portconfig */
434 RtlZeroMemory(ConfigInfo
, sizeof(PORT_CONFIGURATION_INFORMATION
));
436 /* Initialize the struct */
437 ConfigInfo
->Length
= sizeof(PORT_CONFIGURATION_INFORMATION
);
438 ConfigInfo
->AdapterInterfaceType
= HwInitData
->AdapterInterfaceType
;
439 ConfigInfo
->InterruptMode
= Latched
;
440 ConfigInfo
->DmaChannel
= SP_UNINITIALIZED_VALUE
;
441 ConfigInfo
->DmaPort
= SP_UNINITIALIZED_VALUE
;
442 ConfigInfo
->MaximumTransferLength
= SP_UNINITIALIZED_VALUE
;
443 ConfigInfo
->MaximumNumberOfTargets
= SCSI_MAXIMUM_TARGETS_PER_BUS
;
445 /* Store parameters */
446 ConfigInfo
->NeedPhysicalAddresses
= HwInitData
->NeedPhysicalAddresses
;
447 ConfigInfo
->MapBuffers
= HwInitData
->MapBuffers
;
448 ConfigInfo
->AutoRequestSense
= HwInitData
->AutoRequestSense
;
449 ConfigInfo
->ReceiveEvent
= HwInitData
->ReceiveEvent
;
450 ConfigInfo
->TaggedQueuing
= HwInitData
->TaggedQueuing
;
451 ConfigInfo
->MultipleRequestPerLu
= HwInitData
->MultipleRequestPerLu
;
453 /* Get the disk usage */
454 ConfigInfo
->AtdiskPrimaryClaimed
= FALSE
; // FIXME
455 ConfigInfo
->AtdiskSecondaryClaimed
= FALSE
; // FIXME
457 /* Initiator bus id is not set */
458 for (Bus
= 0; Bus
< RTL_NUMBER_OF(ConfigInfo
->InitiatorBusId
); Bus
++)
460 ConfigInfo
->InitiatorBusId
[Bus
] = (CCHAR
)SP_UNINITIALIZED_VALUE
;
464 ConfigInfo
->NumberOfPhysicalBreaks
= 17;
466 return STATUS_SUCCESS
;
472 IN ULONG DebugPrintLevel
,
473 IN PCCHAR DebugMessage
,
480 if (DebugPrintLevel
> 10)
483 va_start(ap
, DebugMessage
);
485 /* Construct a string */
486 Length
= _vsnprintf(Buffer
, 512, DebugMessage
, ap
);
488 /* Check if we went past the buffer */
489 if (Length
== MAXULONG
)
491 /* Terminate it if we went over-board */
492 Buffer
[sizeof(Buffer
) - 1] = '\0';
495 Length
= sizeof(Buffer
);
498 /* Print the message */
507 ScsiPortCompleteRequest(
508 IN PVOID HwDeviceExtension
,
518 #undef ScsiPortConvertPhysicalAddressToUlong
521 ScsiPortConvertPhysicalAddressToUlong(
522 IN SCSI_PHYSICAL_ADDRESS Address
)
524 return Address
.LowPart
;
527 SCSI_PHYSICAL_ADDRESS
529 ScsiPortConvertUlongToPhysicalAddress(
530 IN ULONG_PTR UlongAddress
)
532 SCSI_PHYSICAL_ADDRESS Address
;
534 Address
.QuadPart
= UlongAddress
;
541 IN PVOID DeviceExtension
)
549 ScsiPortFreeDeviceBase(
550 IN PVOID HwDeviceExtension
,
551 IN PVOID MappedAddress
)
559 IN PVOID DeviceExtension
,
560 IN ULONG BusDataType
,
561 IN ULONG SystemIoBusNumber
,
566 return HalGetBusDataByOffset(BusDataType
, SystemIoBusNumber
, SlotNumber
, Buffer
, 0, Length
);
571 ScsiPortGetDeviceBase(
572 IN PVOID HwDeviceExtension
,
573 IN INTERFACE_TYPE BusType
,
574 IN ULONG SystemIoBusNumber
,
575 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
576 IN ULONG NumberOfBytes
,
577 IN BOOLEAN InIoSpace
)
579 PHYSICAL_ADDRESS TranslatedAddress
;
582 AddressSpace
= (ULONG
)InIoSpace
;
583 if (HalTranslateBusAddress(BusType
,
587 &TranslatedAddress
) == FALSE
)
593 if (AddressSpace
!= 0)
594 return (PVOID
)(ULONG_PTR
)TranslatedAddress
.u
.LowPart
;
598 return MmMapIoSpace(TranslatedAddress
,
603 return (PVOID
)(ULONG_PTR
)IoAddress
.LowPart
;
609 ScsiPortGetLogicalUnit(
610 IN PVOID HwDeviceExtension
,
620 SCSI_PHYSICAL_ADDRESS
622 ScsiPortGetPhysicalAddress(
623 IN PVOID HwDeviceExtension
,
624 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
625 IN PVOID VirtualAddress
,
628 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
629 SCSI_PHYSICAL_ADDRESS PhysicalAddress
;
630 ULONG BufferLength
= 0;
633 TRACE("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
634 HwDeviceExtension
, Srb
, VirtualAddress
, Length
);
636 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
638 if (Srb
== NULL
|| Srb
->SenseInfoBuffer
== VirtualAddress
)
640 /* Simply look it up in the allocated common buffer */
641 Offset
= (PUCHAR
)VirtualAddress
- (PUCHAR
)DeviceExtension
->SrbExtensionBuffer
;
643 BufferLength
= DeviceExtension
->CommonBufferLength
- Offset
;
644 PhysicalAddress
.QuadPart
= Offset
;
649 PhysicalAddress
.QuadPart
= (LONGLONG
)SP_UNINITIALIZED_VALUE
;
652 *Length
= BufferLength
;
653 return PhysicalAddress
;
659 IN PVOID DeviceExtension
,
672 SpiAllocateCommonBuffer(
673 IN OUT PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
674 IN ULONG NonCachedSize
)
677 ULONG CommonBufferLength
, BufSize
;
679 /* If size is 0, set it to 16 */
680 if (!DeviceExtension
->SrbExtensionSize
)
681 DeviceExtension
->SrbExtensionSize
= 16;
684 BufSize
= DeviceExtension
->SrbExtensionSize
;
687 BufSize
= (BufSize
+ sizeof(LONGLONG
) - 1) & ~(sizeof(LONGLONG
) - 1);
689 /* Sum up into the total common buffer length, and round it to page size */
691 ROUND_TO_PAGES(NonCachedSize
);
694 if (!DeviceExtension
->AdapterObject
)
696 /* From nonpaged pool if there is no DMA */
697 CommonBuffer
= ExAllocatePool(NonPagedPool
, CommonBufferLength
);
701 /* Perform a full request since we have a DMA adapter*/
706 /* Fail in case of error */
708 return STATUS_INSUFFICIENT_RESOURCES
;
711 RtlZeroMemory(CommonBuffer
, CommonBufferLength
);
713 /* Store its size in Device Extension */
714 DeviceExtension
->CommonBufferLength
= CommonBufferLength
;
716 /* SrbExtension buffer is located at the beginning of the buffer */
717 DeviceExtension
->SrbExtensionBuffer
= CommonBuffer
;
719 /* Non-cached extension buffer is located at the end of
723 CommonBufferLength
-= NonCachedSize
;
724 DeviceExtension
->NonCachedExtension
= (PUCHAR
)CommonBuffer
+ CommonBufferLength
;
728 DeviceExtension
->NonCachedExtension
= NULL
;
731 return STATUS_SUCCESS
;
736 ScsiPortGetUncachedExtension(
737 IN PVOID HwDeviceExtension
,
738 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
739 IN ULONG NumberOfBytes
)
741 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
742 DEVICE_DESCRIPTION DeviceDescription
;
743 ULONG MapRegistersCount
;
746 TRACE("ScsiPortGetUncachedExtension(%p %p %lu)\n",
747 HwDeviceExtension
, ConfigInfo
, NumberOfBytes
);
749 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
751 /* Check for allocated common DMA buffer */
752 if (DeviceExtension
->SrbExtensionBuffer
!= NULL
)
757 /* Check for DMA adapter object */
758 if (DeviceExtension
->AdapterObject
== NULL
)
760 /* Initialize DMA adapter description */
761 RtlZeroMemory(&DeviceDescription
, sizeof(DEVICE_DESCRIPTION
));
763 DeviceDescription
.Version
= DEVICE_DESCRIPTION_VERSION
;
764 DeviceDescription
.Master
= ConfigInfo
->Master
;
765 DeviceDescription
.ScatterGather
= ConfigInfo
->ScatterGather
;
766 DeviceDescription
.DemandMode
= ConfigInfo
->DemandMode
;
767 DeviceDescription
.Dma32BitAddresses
= ConfigInfo
->Dma32BitAddresses
;
768 DeviceDescription
.BusNumber
= ConfigInfo
->SystemIoBusNumber
;
769 DeviceDescription
.DmaChannel
= ConfigInfo
->DmaChannel
;
770 DeviceDescription
.InterfaceType
= ConfigInfo
->AdapterInterfaceType
;
771 DeviceDescription
.DmaWidth
= ConfigInfo
->DmaWidth
;
772 DeviceDescription
.DmaSpeed
= ConfigInfo
->DmaSpeed
;
773 DeviceDescription
.MaximumLength
= ConfigInfo
->MaximumTransferLength
;
774 DeviceDescription
.DmaPort
= ConfigInfo
->DmaPort
;
776 /* Get a DMA adapter object */
778 DeviceExtension
->AdapterObject
=
779 HalGetAdapter(&DeviceDescription
, &MapRegistersCount
);
781 /* Fail in case of error */
782 if (DeviceExtension
->AdapterObject
== NULL
)
787 MapRegistersCount
= 0;
790 /* Set number of physical breaks */
791 if (ConfigInfo
->NumberOfPhysicalBreaks
!= 0 &&
792 MapRegistersCount
> ConfigInfo
->NumberOfPhysicalBreaks
)
794 DeviceExtension
->PortCapabilities
.MaximumPhysicalPages
=
795 ConfigInfo
->NumberOfPhysicalBreaks
;
799 DeviceExtension
->PortCapabilities
.MaximumPhysicalPages
= MapRegistersCount
;
803 /* Update Srb extension size */
804 if (DeviceExtension
->SrbExtensionSize
!= ConfigInfo
->SrbExtensionSize
)
805 DeviceExtension
->SrbExtensionSize
= ConfigInfo
->SrbExtensionSize
;
807 /* Allocate a common DMA buffer */
808 Status
= SpiAllocateCommonBuffer(DeviceExtension
, NumberOfBytes
);
810 if (!NT_SUCCESS(Status
))
812 TRACE("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status
);
816 return DeviceExtension
->NonCachedExtension
;
821 ScsiPortGetVirtualAddress(
822 IN PVOID HwDeviceExtension
,
823 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
)
833 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
842 struct _DRIVE_LAYOUT_INFORMATION
*PartitionBuffer
;
843 CHAR PartitionName
[64];
845 /* Register device with partition(0) suffix */
846 RtlStringCbPrintfA(PartitionName
, sizeof(PartitionName
), "%spartition(0)", ArcName
);
847 FsRegisterDevice(PartitionName
, &DiskVtbl
);
849 /* Read device partition table */
850 Status
= ArcOpen(PartitionName
, OpenReadOnly
, &FileId
);
851 if (Status
== ESUCCESS
)
853 ret
= HALDISPATCH
->HalIoReadPartitionTable((PDEVICE_OBJECT
)(ULONG_PTR
)FileId
,
854 512, FALSE
, &PartitionBuffer
);
857 for (i
= 0; i
< PartitionBuffer
->PartitionCount
; i
++)
859 if (PartitionBuffer
->PartitionEntry
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
)
861 RtlStringCbPrintfA(PartitionName
,
862 sizeof(PartitionName
),
865 PartitionBuffer
->PartitionEntry
[i
].PartitionNumber
);
866 FsRegisterDevice(PartitionName
, &DiskVtbl
);
869 ExFreePool(PartitionBuffer
);
878 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
,
883 PSCSI_REQUEST_BLOCK Srb
;
885 INQUIRYDATA InquiryBuffer
;
889 if (!DeviceExtension
->HwResetBus(DeviceExtension
->MiniPortDeviceExtension
, PathId
))
894 /* Remember the extension */
895 ScsiDeviceExtensions
[ScsiBus
] = DeviceExtension
;
897 for (TargetId
= 0; TargetId
< DeviceExtension
->MaxTargedIds
; TargetId
++)
902 TRACE("Scanning SCSI device %d.%d.%d\n",
903 ScsiBus
, TargetId
, Lun
);
905 Srb
= ExAllocatePool(PagedPool
, sizeof(SCSI_REQUEST_BLOCK
));
908 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
909 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
910 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
911 Srb
->PathId
= PathId
;
912 Srb
->TargetId
= TargetId
;
915 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
;
916 Srb
->DataTransferLength
= INQUIRYDATABUFFERSIZE
;
917 Srb
->TimeOutValue
= 5; /* in seconds */
918 Srb
->DataBuffer
= &InquiryBuffer
;
919 Cdb
= (PCDB
)Srb
->Cdb
;
920 Cdb
->CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
921 Cdb
->CDB6INQUIRY
.LogicalUnitNumber
= Srb
->Lun
;
922 Cdb
->CDB6INQUIRY
.AllocationLength
= (UCHAR
)Srb
->DataTransferLength
;
923 if (!SpiSendSynchronousSrb(DeviceExtension
, Srb
))
925 /* Don't check next LUNs */
929 /* Device exists, create its ARC name */
930 if (InquiryBuffer
.RemovableMedia
)
932 sprintf(ArcName
, "scsi(%ld)cdrom(%d)fdisk(%d)",
933 ScsiBus
, TargetId
, Lun
);
934 FsRegisterDevice(ArcName
, &DiskVtbl
);
938 sprintf(ArcName
, "scsi(%ld)disk(%d)rdisk(%d)",
939 ScsiBus
, TargetId
, Lun
);
940 /* Now, check if it has partitions */
941 SpiScanDevice(DeviceExtension
, ArcName
, PathId
, TargetId
, Lun
);
946 } while (Lun
< SCSI_MAXIMUM_LOGICAL_UNITS
);
953 IN PHW_INITIALIZATION_DATA HwInitializationData
,
954 IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor
,
955 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
)
957 PACCESS_RANGE AccessRange
;
958 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData
;
964 /* Loop through all entries */
965 for (Index
= 0; Index
< ResourceDescriptor
->PartialResourceList
.Count
; Index
++)
967 PartialData
= &ResourceDescriptor
->PartialResourceList
.PartialDescriptors
[Index
];
969 switch (PartialData
->Type
)
971 case CmResourceTypePort
:
972 /* Copy access ranges */
973 if (RangeNumber
< HwInitializationData
->NumberOfAccessRanges
)
975 TRACE("Got port at 0x%I64x, len 0x%x\n",
976 PartialData
->u
.Port
.Start
.QuadPart
, PartialData
->u
.Port
.Length
);
977 AccessRange
= &((*(PortConfig
->AccessRanges
))[RangeNumber
]);
979 AccessRange
->RangeStart
= PartialData
->u
.Port
.Start
;
980 AccessRange
->RangeLength
= PartialData
->u
.Port
.Length
;
982 AccessRange
->RangeInMemory
= FALSE
;
987 case CmResourceTypeMemory
:
988 /* Copy access ranges */
989 if (RangeNumber
< HwInitializationData
->NumberOfAccessRanges
)
991 TRACE("Got memory at 0x%I64x, len 0x%x\n",
992 PartialData
->u
.Memory
.Start
.QuadPart
, PartialData
->u
.Memory
.Length
);
993 AccessRange
= &((*(PortConfig
->AccessRanges
))[RangeNumber
]);
995 AccessRange
->RangeStart
= PartialData
->u
.Memory
.Start
;
996 AccessRange
->RangeLength
= PartialData
->u
.Memory
.Length
;
998 AccessRange
->RangeInMemory
= TRUE
;
1003 case CmResourceTypeInterrupt
:
1004 /* Copy interrupt data */
1005 TRACE("Got interrupt level %d, vector %d\n",
1006 PartialData
->u
.Interrupt
.Level
, PartialData
->u
.Interrupt
.Vector
);
1007 PortConfig
->BusInterruptLevel
= PartialData
->u
.Interrupt
.Level
;
1008 PortConfig
->BusInterruptVector
= PartialData
->u
.Interrupt
.Vector
;
1010 /* Set interrupt mode accordingly to the resource */
1011 if (PartialData
->Flags
== CM_RESOURCE_INTERRUPT_LATCHED
)
1013 PortConfig
->InterruptMode
= Latched
;
1015 else if (PartialData
->Flags
== CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
)
1017 PortConfig
->InterruptMode
= LevelSensitive
;
1021 case CmResourceTypeDma
:
1022 TRACE("Got DMA channel %d, port %d\n",
1023 PartialData
->u
.Dma
.Channel
, PartialData
->u
.Dma
.Port
);
1024 PortConfig
->DmaChannel
= PartialData
->u
.Dma
.Channel
;
1025 PortConfig
->DmaPort
= PartialData
->u
.Dma
.Port
;
1033 SpiGetPciConfigData(
1034 IN PHW_INITIALIZATION_DATA HwInitializationData
,
1035 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig
,
1037 IN OUT PPCI_SLOT_NUMBER NextSlotNumber
)
1039 PCI_COMMON_CONFIG PciConfig
;
1040 PCI_SLOT_NUMBER SlotNumber
;
1043 ULONG FunctionNumber
;
1044 CHAR VendorIdString
[8];
1045 CHAR DeviceIdString
[8];
1046 PCM_RESOURCE_LIST ResourceList
= NULL
;
1049 SlotNumber
.u
.AsULONG
= 0;
1051 /* Loop through all devices */
1052 for (DeviceNumber
= NextSlotNumber
->u
.bits
.DeviceNumber
; DeviceNumber
< PCI_MAX_DEVICES
; DeviceNumber
++)
1054 SlotNumber
.u
.bits
.DeviceNumber
= DeviceNumber
;
1056 /* Loop through all functions */
1057 for (FunctionNumber
= NextSlotNumber
->u
.bits
.FunctionNumber
; FunctionNumber
< PCI_MAX_FUNCTION
; FunctionNumber
++)
1059 SlotNumber
.u
.bits
.FunctionNumber
= FunctionNumber
;
1061 /* Get PCI config bytes */
1062 DataSize
= HalGetBusDataByOffset(
1065 SlotNumber
.u
.AsULONG
,
1070 /* If result of HalGetBusData is 0, then the bus is wrong */
1074 /* If result is PCI_INVALID_VENDORID, then this device has no more
1076 if (PciConfig
.VendorID
== PCI_INVALID_VENDORID
)
1079 sprintf(VendorIdString
, "%04hx", PciConfig
.VendorID
);
1080 sprintf(DeviceIdString
, "%04hx", PciConfig
.DeviceID
);
1082 if (_strnicmp(VendorIdString
, HwInitializationData
->VendorId
, HwInitializationData
->VendorIdLength
) ||
1083 _strnicmp(DeviceIdString
, HwInitializationData
->DeviceId
, HwInitializationData
->DeviceIdLength
))
1085 /* It is not our device */
1089 TRACE( "Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1090 PciConfig
.VendorID
, PciConfig
.DeviceID
,
1092 SlotNumber
.u
.bits
.DeviceNumber
, SlotNumber
.u
.bits
.FunctionNumber
);
1094 Status
= HalAssignSlotResources(NULL
,
1100 SlotNumber
.u
.AsULONG
,
1103 if (!NT_SUCCESS(Status
))
1106 /* Create configuration information */
1107 SpiResourceToConfig(HwInitializationData
,
1111 /* Free the resource list */
1112 ExFreePool(ResourceList
);
1114 /* Set dev & fn numbers */
1115 NextSlotNumber
->u
.bits
.DeviceNumber
= DeviceNumber
;
1116 NextSlotNumber
->u
.bits
.FunctionNumber
= FunctionNumber
+ 1;
1118 /* Save the slot number */
1119 PortConfig
->SlotNumber
= SlotNumber
.u
.AsULONG
;
1123 NextSlotNumber
->u
.bits
.FunctionNumber
= 0;
1126 NextSlotNumber
->u
.bits
.DeviceNumber
= 0;
1136 IN PHW_INITIALIZATION_DATA HwInitializationData
,
1137 IN PVOID HwContext OPTIONAL
)
1139 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1140 ULONG DeviceExtensionSize
;
1141 PORT_CONFIGURATION_INFORMATION PortConfig
;
1143 BOOLEAN FirstConfigCall
= TRUE
;
1144 PCI_SLOT_NUMBER SlotNumber
;
1148 if (HwInitializationData
->HwInitializationDataSize
!= sizeof(HW_INITIALIZATION_DATA
))
1150 return STATUS_INVALID_PARAMETER
;
1153 /* Check params for validity */
1154 if ((HwInitializationData
->HwInitialize
== NULL
) ||
1155 (HwInitializationData
->HwStartIo
== NULL
) ||
1156 (HwInitializationData
->HwInterrupt
== NULL
) ||
1157 (HwInitializationData
->HwFindAdapter
== NULL
) ||
1158 (HwInitializationData
->HwResetBus
== NULL
))
1160 return STATUS_INVALID_PARAMETER
;
1163 /* Zero starting slot number */
1164 SlotNumber
.u
.AsULONG
= 0;
1170 DeviceExtensionSize
= sizeof(SCSI_PORT_DEVICE_EXTENSION
) + HwInitializationData
->DeviceExtensionSize
;
1171 DeviceExtension
= FrLdrTempAlloc(DeviceExtensionSize
, TAG_SCSI_DEVEXT
);
1172 if (!DeviceExtension
)
1174 return STATUS_NO_MEMORY
;
1176 RtlZeroMemory(DeviceExtension
, DeviceExtensionSize
);
1177 DeviceExtension
->InterruptFlags
= SCSI_PORT_NEXT_REQUEST_READY
;
1178 DeviceExtension
->HwInitialize
= HwInitializationData
->HwInitialize
;
1179 DeviceExtension
->HwStartIo
= HwInitializationData
->HwStartIo
;
1180 DeviceExtension
->HwInterrupt
= HwInitializationData
->HwInterrupt
;
1181 DeviceExtension
->HwResetBus
= HwInitializationData
->HwResetBus
;
1182 DeviceExtension
->MiniPortDeviceExtension
= (PVOID
)(DeviceExtension
+ 1);
1184 Status
= SpiCreatePortConfig(DeviceExtension
,
1185 HwInitializationData
,
1188 if (Status
!= STATUS_SUCCESS
)
1190 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1194 PortConfig
.NumberOfAccessRanges
= HwInitializationData
->NumberOfAccessRanges
;
1195 PortConfig
.AccessRanges
= FrLdrTempAlloc(sizeof(ACCESS_RANGE
) * HwInitializationData
->NumberOfAccessRanges
,
1196 TAG_SCSI_ACCESS_RANGES
);
1197 if (!PortConfig
.AccessRanges
)
1199 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1200 return STATUS_NO_MEMORY
;
1202 RtlZeroMemory(PortConfig
.AccessRanges
, sizeof(ACCESS_RANGE
) * HwInitializationData
->NumberOfAccessRanges
);
1204 /* Search for matching PCI device */
1205 if ((HwInitializationData
->AdapterInterfaceType
== PCIBus
) &&
1206 (HwInitializationData
->VendorIdLength
> 0) &&
1207 (HwInitializationData
->VendorId
!= NULL
) &&
1208 (HwInitializationData
->DeviceIdLength
> 0) &&
1209 (HwInitializationData
->DeviceId
!= NULL
))
1211 PortConfig
.BusInterruptLevel
= 0;
1213 /* Get PCI device data */
1214 TRACE("VendorId '%.*s' DeviceId '%.*s'\n",
1215 HwInitializationData
->VendorIdLength
,
1216 HwInitializationData
->VendorId
,
1217 HwInitializationData
->DeviceIdLength
,
1218 HwInitializationData
->DeviceId
);
1220 if (!SpiGetPciConfigData(HwInitializationData
,
1225 /* Continue to the next bus, nothing here */
1226 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1227 return STATUS_INTERNAL_ERROR
;
1230 if (!PortConfig
.BusInterruptLevel
)
1232 /* Bypass this slot, because no interrupt was assigned */
1233 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1234 return STATUS_INTERNAL_ERROR
;
1238 if (HwInitializationData
->HwFindAdapter(
1239 DeviceExtension
->MiniPortDeviceExtension
,
1244 &Again
) != SP_RETURN_FOUND
)
1246 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1247 return STATUS_INTERNAL_ERROR
;
1250 /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
1251 if (PortConfig
.MaximumNumberOfTargets
> SCSI_MAXIMUM_TARGETS_PER_BUS
)
1252 DeviceExtension
->MaxTargedIds
= SCSI_MAXIMUM_TARGETS_PER_BUS
;
1254 DeviceExtension
->MaxTargedIds
= PortConfig
.MaximumNumberOfTargets
;
1256 DeviceExtension
->BusNum
= PortConfig
.SystemIoBusNumber
;
1258 TRACE("Adapter found: buses = %d, targets = %d\n",
1259 PortConfig
.NumberOfBuses
, DeviceExtension
->MaxTargedIds
);
1261 /* Initialize adapter */
1262 if (!DeviceExtension
->HwInitialize(DeviceExtension
->MiniPortDeviceExtension
))
1264 FrLdrTempFree(DeviceExtension
, TAG_SCSI_DEVEXT
);
1265 return STATUS_INTERNAL_ERROR
;
1269 for (ScsiBus
= 0; ScsiBus
< PortConfig
.NumberOfBuses
; ScsiBus
++)
1271 SpiScanAdapter(DeviceExtension
, PortConfig
.SystemIoBusNumber
, ScsiBus
);
1272 PortConfig
.SystemIoBusNumber
++;
1275 FirstConfigCall
= FALSE
;
1282 return STATUS_SUCCESS
;
1287 ScsiPortIoMapTransfer(
1288 IN PVOID HwDeviceExtension
,
1289 IN PSCSI_REQUEST_BLOCK Srb
,
1290 IN PVOID LogicalAddress
,
1300 IN PVOID HwDeviceExtension
,
1301 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL
,
1315 IN PVOID WriteBuffer
,
1316 IN PVOID ReadBuffer
,
1319 RtlMoveMemory(WriteBuffer
, ReadBuffer
, Length
);
1324 ScsiPortNotification(
1325 IN SCSI_NOTIFICATION_TYPE NotificationType
,
1326 IN PVOID HwDeviceExtension
,
1329 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension
;
1330 PSCSI_REQUEST_BLOCK Srb
;
1333 DeviceExtension
= ((PSCSI_PORT_DEVICE_EXTENSION
)HwDeviceExtension
) - 1;
1335 va_start(ap
, HwDeviceExtension
);
1337 switch (NotificationType
)
1339 case RequestComplete
:
1340 /* Mask the SRB as completed */
1341 Srb
= va_arg(ap
, PSCSI_REQUEST_BLOCK
);
1342 Srb
->SrbFlags
&= ~SRB_FLAGS_IS_ACTIVE
;
1346 /* Say that device is ready */
1347 DeviceExtension
->InterruptFlags
|= SCSI_PORT_NEXT_REQUEST_READY
;
1360 ScsiPortReadPortBufferUchar(
1365 __inbytestring(H2I(Port
), Buffer
, Count
);
1370 ScsiPortReadPortBufferUlong(
1375 __indwordstring(H2I(Port
), Buffer
, Count
);
1380 ScsiPortReadPortBufferUshort(
1385 __inwordstring(H2I(Port
), Buffer
, Count
);
1390 ScsiPortReadPortUchar(
1393 TRACE("ScsiPortReadPortUchar(%p)\n", Port
);
1395 return READ_PORT_UCHAR(Port
);
1400 ScsiPortReadPortUlong(
1403 return READ_PORT_ULONG(Port
);
1408 ScsiPortReadPortUshort(
1411 return READ_PORT_USHORT(Port
);
1416 ScsiPortReadRegisterBufferUchar(
1427 ScsiPortReadRegisterBufferUlong(
1438 ScsiPortReadRegisterBufferUshort(
1439 IN PUSHORT Register
,
1449 ScsiPortReadRegisterUchar(
1452 return READ_REGISTER_UCHAR(Register
);
1457 ScsiPortReadRegisterUlong(
1460 return READ_REGISTER_ULONG(Register
);
1465 ScsiPortReadRegisterUshort(
1466 IN PUSHORT Register
)
1468 return READ_REGISTER_USHORT(Register
);
1473 ScsiPortSetBusDataByOffset(
1474 IN PVOID DeviceExtension
,
1475 IN ULONG BusDataType
,
1476 IN ULONG SystemIoBusNumber
,
1477 IN ULONG SlotNumber
,
1489 ScsiPortStallExecution(
1492 KeStallExecutionProcessor(Delay
);
1497 ScsiPortValidateRange(
1498 IN PVOID HwDeviceExtension
,
1499 IN INTERFACE_TYPE BusType
,
1500 IN ULONG SystemIoBusNumber
,
1501 IN SCSI_PHYSICAL_ADDRESS IoAddress
,
1502 IN ULONG NumberOfBytes
,
1503 IN BOOLEAN InIoSpace
)
1517 ScsiPortWritePortBufferUchar(
1522 __outbytestring(H2I(Port
), Buffer
, Count
);
1527 ScsiPortWritePortBufferUlong(
1532 __outdwordstring(H2I(Port
), Buffer
, Count
);
1537 ScsiPortWritePortBufferUshort(
1542 __outwordstring(H2I(Port
), Buffer
, Count
);
1547 ScsiPortWritePortUchar(
1551 WRITE_PORT_UCHAR(Port
, Value
);
1556 ScsiPortWritePortUlong(
1560 WRITE_PORT_ULONG(Port
, Value
);
1565 ScsiPortWritePortUshort(
1569 WRITE_PORT_USHORT(Port
, Value
);
1574 ScsiPortWriteRegisterBufferUchar(
1585 ScsiPortWriteRegisterBufferUlong(
1596 ScsiPortWriteRegisterBufferUshort(
1597 IN PUSHORT Register
,
1607 ScsiPortWriteRegisterUchar(
1611 WRITE_REGISTER_UCHAR(Register
, Value
);
1616 ScsiPortWriteRegisterUlong(
1620 WRITE_REGISTER_ULONG(Register
, Value
);
1625 ScsiPortWriteRegisterUshort(
1626 IN PUSHORT Register
,
1629 WRITE_REGISTER_USHORT(Register
, Value
);
1632 extern char __ImageBase
;
1635 LoadBootDeviceDriver(VOID
)
1637 PIMAGE_NT_HEADERS NtHeaders
;
1638 LIST_ENTRY ModuleListHead
;
1639 PIMAGE_IMPORT_DESCRIPTOR ImportTable
;
1640 ULONG ImportTableSize
;
1641 PLDR_DATA_TABLE_ENTRY BootDdDTE
, FreeldrDTE
;
1642 CHAR NtBootDdPath
[MAX_PATH
];
1643 PVOID ImageBase
= NULL
;
1644 ULONG (NTAPI
*EntryPoint
)(IN PVOID DriverObject
, IN PVOID RegistryPath
);
1647 // FIXME: Must be done *INSIDE* the HAL!
1649 HalpInitializePciStubs();
1650 HalpInitBusHandler();
1653 /* Initialize the loaded module list */
1654 InitializeListHead(&ModuleListHead
);
1656 /* Create full ntbootdd.sys path */
1657 strcpy(NtBootDdPath
, FrLdrBootPath
);
1658 strcat(NtBootDdPath
, "\\NTBOOTDD.SYS");
1661 Success
= PeLdrLoadImage(NtBootDdPath
, LoaderBootDriver
, &ImageBase
);
1664 /* That's OK, file simply doesn't exist */
1668 /* Allocate a DTE for ntbootdd */
1669 Success
= PeLdrAllocateDataTableEntry(&ModuleListHead
, "ntbootdd.sys",
1670 "NTBOOTDD.SYS", ImageBase
, &BootDdDTE
);
1673 /* Cleanup and bail out */
1674 MmFreeMemory(ImageBase
);
1678 /* Add the PE part of freeldr.sys to the list of loaded executables, it
1679 contains ScsiPort* exports, imported by ntbootdd.sys */
1680 Success
= PeLdrAllocateDataTableEntry(&ModuleListHead
, "scsiport.sys",
1681 "FREELDR.SYS", &__ImageBase
, &FreeldrDTE
);
1684 /* Cleanup and bail out */
1685 PeLdrFreeDataTableEntry(BootDdDTE
);
1686 MmFreeMemory(ImageBase
);
1691 Success
= PeLdrScanImportDescriptorTable(&ModuleListHead
, "", BootDdDTE
);
1694 /* Cleanup and bail out */
1695 PeLdrFreeDataTableEntry(FreeldrDTE
);
1696 PeLdrFreeDataTableEntry(BootDdDTE
);
1697 MmFreeMemory(ImageBase
);
1701 /* Now unlink the DTEs, they won't be valid later */
1702 RemoveEntryList(&BootDdDTE
->InLoadOrderLinks
);
1703 RemoveEntryList(&FreeldrDTE
->InLoadOrderLinks
);
1705 /* Change imports to PA */
1706 ImportTable
= (PIMAGE_IMPORT_DESCRIPTOR
)RtlImageDirectoryEntryToData(VaToPa(BootDdDTE
->DllBase
),
1707 TRUE
, IMAGE_DIRECTORY_ENTRY_IMPORT
, &ImportTableSize
);
1708 for (;(ImportTable
->Name
!= 0) && (ImportTable
->FirstThunk
!= 0);ImportTable
++)
1710 PIMAGE_THUNK_DATA ThunkData
= (PIMAGE_THUNK_DATA
)VaToPa(RVA(BootDdDTE
->DllBase
, ImportTable
->FirstThunk
));
1712 while (((PIMAGE_THUNK_DATA
)ThunkData
)->u1
.AddressOfData
!= 0)
1714 ThunkData
->u1
.Function
= (ULONG_PTR
)VaToPa((PVOID
)ThunkData
->u1
.Function
);
1719 /* Relocate image to PA */
1720 NtHeaders
= RtlImageNtHeader(VaToPa(BootDdDTE
->DllBase
));
1723 Success
= (BOOLEAN
)LdrRelocateImageWithBias(VaToPa(BootDdDTE
->DllBase
),
1724 NtHeaders
->OptionalHeader
.ImageBase
- (ULONG_PTR
)BootDdDTE
->DllBase
,
1727 TRUE
, /* In case of conflict still return success */
1732 /* Call the entrypoint */
1733 EntryPoint
= VaToPa(BootDdDTE
->EntryPoint
);
1734 (*EntryPoint
)(NULL
, NULL
);