+/*
+ * PROJECT: ReactOS Boot Loader (FreeLDR)
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: boot/freeldr/freeldr/disk/scsiport.c
+ * PURPOSE: Interface for SCSI Emulation
+ * PROGRAMMERS: Hervé Poussineau <hpoussin@reactos.org>
+ */
+
+/* INCLUDES *******************************************************************/
+
#include <freeldr.h>
+#include <debug.h>
+DBG_DEFAULT_CHANNEL(SCSIPORT);
+
#define _SCSIPORT_
#include <ntddk.h>
#undef ScsiPortReadRegisterUlong
#undef ScsiPortReadRegisterUshort
-#define NDEBUG
-#include <debug.h>
-
#define SCSI_PORT_NEXT_REQUEST_READY 0x0008
-DBG_DEFAULT_CHANNEL(SCSIPORT);
+#define TAG_SCSI_DEVEXT 'DscS'
+#define TAG_SCSI_ACCESS_RANGES 'AscS'
+
+/* GLOBALS ********************************************************************/
+
+#ifdef _M_IX86
+VOID NTAPI HalpInitializePciStubs(VOID);
+VOID NTAPI HalpInitBusHandler(VOID);
+#endif
typedef struct
{
PVOID MiniPortDeviceExtension;
} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
+typedef struct tagDISKCONTEXT
+{
+ /* Device ID */
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ UCHAR PathId;
+ UCHAR TargetId;
+ UCHAR Lun;
+
+ /* Device characteristics */
+ ULONG SectorSize;
+ ULONGLONG SectorOffset;
+ ULONGLONG SectorCount;
+ ULONGLONG SectorNumber;
+} DISKCONTEXT;
+
PSCSI_PORT_DEVICE_EXTENSION ScsiDeviceExtensions[SCSI_MAXIMUM_BUSES];
+/* FUNCTIONS ******************************************************************/
+
ULONG
ntohl(
IN ULONG Value)
return Dest.AsULong;
}
+static
BOOLEAN
SpiSendSynchronousSrb(
IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
return ret;
}
-typedef struct tagDISKCONTEXT
-{
- /* Device ID */
- PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
-
- /* Device characteristics */
- ULONG SectorSize;
- ULONGLONG SectorOffset;
- ULONGLONG SectorCount;
- ULONGLONG SectorNumber;
-} DISKCONTEXT;
-
-static LONG DiskClose(ULONG FileId)
+static ARC_STATUS DiskClose(ULONG FileId)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
-
ExFreePool(Context);
return ESUCCESS;
}
-static LONG DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
+static ARC_STATUS DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
- RtlZeroMemory(Information, sizeof(FILEINFORMATION));
- Information->EndingAddress.QuadPart = Context->SectorCount * Context->SectorSize;
- Information->CurrentAddress.QuadPart = Context->SectorNumber * Context->SectorSize;
+ RtlZeroMemory(Information, sizeof(*Information));
+
+ /*
+ * The ARC specification mentions that for partitions, StartingAddress and
+ * EndingAddress are the start and end positions of the partition in terms
+ * of byte offsets from the start of the disk.
+ * CurrentAddress is the current offset into (i.e. relative to) the partition.
+ */
+ Information->StartingAddress.QuadPart = Context->SectorOffset * Context->SectorSize;
+ Information->EndingAddress.QuadPart = (Context->SectorOffset + Context->SectorCount) * Context->SectorSize;
+ Information->CurrentAddress.QuadPart = Context->SectorNumber * Context->SectorSize;
return ESUCCESS;
}
-static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
+static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
{
PSCSI_REQUEST_BLOCK Srb;
PCDB Cdb;
return ESUCCESS;
}
-static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
+static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
PSCSI_REQUEST_BLOCK Srb;
/* Read full sectors */
ASSERT(Context->SectorNumber < 0xFFFFFFFF);
- Lba = (ULONG)Context->SectorNumber;
+ Lba = (ULONG)(Context->SectorOffset + Context->SectorNumber);
if (FullSectors > 0)
{
Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
Buffer = (PUCHAR)Buffer + FullSectors * Context->SectorSize;
N -= FullSectors * Context->SectorSize;
*Count += FullSectors * Context->SectorSize;
+ Context->SectorNumber += FullSectors;
Lba += FullSectors;
}
}
RtlCopyMemory(Buffer, Sector, N);
*Count += N;
+ /* Context->SectorNumber remains untouched (incomplete sector read) */
ExFreePool(Sector);
}
return ESUCCESS;
}
-static LONG DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
+static ARC_STATUS DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
+ LARGE_INTEGER NewPosition = *Position;
+
+ switch (SeekMode)
+ {
+ case SeekAbsolute:
+ break;
+ case SeekRelative:
+ NewPosition.QuadPart += (Context->SectorNumber * Context->SectorSize);
+ break;
+ default:
+ ASSERT(FALSE);
+ return EINVAL;
+ }
- if (SeekMode != SeekAbsolute)
+ if (NewPosition.QuadPart & (Context->SectorSize - 1))
return EINVAL;
- if (Position->QuadPart & (Context->SectorSize - 1))
+
+ /* Convert in number of sectors */
+ NewPosition.QuadPart /= Context->SectorSize;
+ if (NewPosition.QuadPart >= Context->SectorCount)
return EINVAL;
- Context->SectorNumber = Position->QuadPart / Context->SectorSize;
+ Context->SectorNumber = NewPosition.QuadPart;
return ESUCCESS;
}
-static const DEVVTBL DiskVtbl = {
+static const DEVVTBL DiskVtbl =
+{
DiskClose,
DiskGetFileInformation,
DiskOpen,
DiskSeek,
};
+static
NTSTATUS
SpiCreatePortConfig(
IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
else
{
/* Nothing */
- *Length = 0;
PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
}
return NULL;
}
+static
NTSTATUS
SpiAllocateCommonBuffer(
IN OUT PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
return NULL;
}
+static
VOID
SpiScanDevice(
IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN ULONG Lun)
{
ULONG FileId, i;
- ULONG Status;
+ ARC_STATUS Status;
NTSTATUS ret;
struct _DRIVE_LAYOUT_INFORMATION *PartitionBuffer;
CHAR PartitionName[64];
/* Register device with partition(0) suffix */
- sprintf(PartitionName, "%spartition(0)", ArcName);
+ RtlStringCbPrintfA(PartitionName, sizeof(PartitionName), "%spartition(0)", ArcName);
FsRegisterDevice(PartitionName, &DiskVtbl);
/* Read device partition table */
{
if (PartitionBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED)
{
- sprintf(PartitionName, "%spartition(%lu)",
- ArcName, PartitionBuffer->PartitionEntry[i].PartitionNumber);
+ RtlStringCbPrintfA(PartitionName,
+ sizeof(PartitionName),
+ "%spartition(%lu)",
+ ArcName,
+ PartitionBuffer->PartitionEntry[i].PartitionNumber);
FsRegisterDevice(PartitionName, &DiskVtbl);
}
}
}
}
+static
VOID
SpiScanAdapter(
IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
}
}
+static
VOID
SpiResourceToConfig(
IN PHW_INITIALIZATION_DATA HwInitializationData,
}
}
+static
BOOLEAN
SpiGetPciConfigData(
- IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
+ IN PHW_INITIALIZATION_DATA HwInitializationData,
IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
IN ULONG BusNumber,
IN OUT PPCI_SLOT_NUMBER NextSlotNumber)
ScsiPortInitialize(
IN PVOID Argument1,
IN PVOID Argument2,
- IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
+ IN PHW_INITIALIZATION_DATA HwInitializationData,
IN PVOID HwContext OPTIONAL)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
Again = FALSE;
DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) + HwInitializationData->DeviceExtensionSize;
- DeviceExtension = MmHeapAlloc(DeviceExtensionSize);
+ DeviceExtension = FrLdrTempAlloc(DeviceExtensionSize, TAG_SCSI_DEVEXT);
if (!DeviceExtension)
{
return STATUS_NO_MEMORY;
FirstConfigCall);
if (Status != STATUS_SUCCESS)
{
- MmHeapFree(DeviceExtension);
+ FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
return Status;
}
PortConfig.NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
- PortConfig.AccessRanges = MmHeapAlloc(sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges);
+ PortConfig.AccessRanges = FrLdrTempAlloc(sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges,
+ TAG_SCSI_ACCESS_RANGES);
if (!PortConfig.AccessRanges)
{
- MmHeapFree(DeviceExtension);
+ FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
return STATUS_NO_MEMORY;
}
RtlZeroMemory(PortConfig.AccessRanges, sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges);
&SlotNumber))
{
/* Continue to the next bus, nothing here */
- MmHeapFree(DeviceExtension);
+ FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
return STATUS_INTERNAL_ERROR;
}
if (!PortConfig.BusInterruptLevel)
{
/* Bypass this slot, because no interrupt was assigned */
- MmHeapFree(DeviceExtension);
+ FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
return STATUS_INTERNAL_ERROR;
}
}
&PortConfig,
&Again) != SP_RETURN_FOUND)
{
- MmHeapFree(DeviceExtension);
+ FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
return STATUS_INTERNAL_ERROR;
}
/* Initialize adapter */
if (!DeviceExtension->HwInitialize(DeviceExtension->MiniPortDeviceExtension))
{
- MmHeapFree(DeviceExtension);
+ FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
return STATUS_INTERNAL_ERROR;
}
ULONG ImportTableSize;
PLDR_DATA_TABLE_ENTRY BootDdDTE, FreeldrDTE;
CHAR NtBootDdPath[MAX_PATH];
- PVOID ImageBase;
+ PVOID ImageBase = NULL;
ULONG (NTAPI *EntryPoint)(IN PVOID DriverObject, IN PVOID RegistryPath);
- BOOLEAN Status;
+ BOOLEAN Success;
+
+ // FIXME: Must be done *INSIDE* the HAL!
+#ifdef _M_IX86
+ HalpInitializePciStubs();
+ HalpInitBusHandler();
+#endif
/* Initialize the loaded module list */
InitializeListHead(&ModuleListHead);
/* Create full ntbootdd.sys path */
- MachDiskGetBootPath(NtBootDdPath, sizeof(NtBootDdPath));
+ strcpy(NtBootDdPath, FrLdrBootPath);
strcat(NtBootDdPath, "\\NTBOOTDD.SYS");
/* Load file */
- Status = WinLdrLoadImage(NtBootDdPath, LoaderBootDriver, &ImageBase);
- if (!Status)
+ Success = PeLdrLoadImage(NtBootDdPath, LoaderBootDriver, &ImageBase);
+ if (!Success)
{
/* That's OK. File simply doesn't exist */
return ESUCCESS;
}
/* Allocate a DTE for ntbootdd */
- Status = WinLdrAllocateDataTableEntry(&ModuleListHead, "ntbootdd.sys",
- "NTBOOTDD.SYS", ImageBase, &BootDdDTE);
- if (!Status)
+ Success = PeLdrAllocateDataTableEntry(&ModuleListHead, "ntbootdd.sys",
+ "NTBOOTDD.SYS", ImageBase, &BootDdDTE);
+ if (!Success)
return EIO;
/* Add the PE part of freeldr.sys to the list of loaded executables, it
- contains Scsiport* exports, imported by ntbootdd.sys */
- Status = WinLdrAllocateDataTableEntry(&ModuleListHead, "scsiport.sys",
- "FREELDR.SYS", &__ImageBase, &FreeldrDTE);
- if (!Status)
+ contains ScsiPort* exports, imported by ntbootdd.sys */
+ Success = PeLdrAllocateDataTableEntry(&ModuleListHead, "scsiport.sys",
+ "FREELDR.SYS", &__ImageBase, &FreeldrDTE);
+ if (!Success)
{
RemoveEntryList(&BootDdDTE->InLoadOrderLinks);
return EIO;
}
/* Fix imports */
- Status = WinLdrScanImportDescriptorTable(&ModuleListHead, "", BootDdDTE);
+ Success = PeLdrScanImportDescriptorTable(&ModuleListHead, "", BootDdDTE);
/* Now unlinkt the DTEs, they won't be valid later */
RemoveEntryList(&BootDdDTE->InLoadOrderLinks);
RemoveEntryList(&FreeldrDTE->InLoadOrderLinks);
- if (!Status)
+ if (!Success)
return EIO;
/* Change imports to PA */
NtHeaders = RtlImageNtHeader(VaToPa(BootDdDTE->DllBase));
if (!NtHeaders)
return EIO;
- Status = (BOOLEAN)LdrRelocateImageWithBias(
- VaToPa(BootDdDTE->DllBase),
- NtHeaders->OptionalHeader.ImageBase - (ULONG_PTR)BootDdDTE->DllBase,
- "FreeLdr",
- TRUE,
- TRUE, /* in case of conflict still return success */
- FALSE);
- if (!Status)
+ Success = (BOOLEAN)LdrRelocateImageWithBias(VaToPa(BootDdDTE->DllBase),
+ NtHeaders->OptionalHeader.ImageBase - (ULONG_PTR)BootDdDTE->DllBase,
+ "FreeLdr",
+ TRUE,
+ TRUE, /* in case of conflict still return success */
+ FALSE);
+ if (!Success)
return EIO;
/* Call the entrypoint */