[FREELDR] Advance the file pointers every time a read operation is performed, in...
[reactos.git] / boot / freeldr / freeldr / disk / scsiport.c
index 8dc1a0b..c9cff4b 100644 (file)
@@ -1,5 +1,18 @@
+/*
+ * 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
 
 #define TAG_SCSI_DEVEXT 'DscS'
 #define TAG_SCSI_ACCESS_RANGES 'AscS'
 
-DBG_DEFAULT_CHANNEL(SCSIPORT);
+/* GLOBALS ********************************************************************/
+
+#ifdef _M_IX86
+VOID NTAPI HalpInitializePciStubs(VOID);
+VOID NTAPI HalpInitBusHandler(VOID);
+#endif
 
 typedef struct
 {
@@ -76,8 +91,25 @@ 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)
@@ -93,6 +125,7 @@ ntohl(
     return Dest.AsULong;
 }
 
+static
 BOOLEAN
 SpiSendSynchronousSrb(
     IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
@@ -133,41 +166,33 @@ SpiSendSynchronousSrb(
     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;
@@ -237,7 +262,7 @@ static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
     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;
@@ -259,7 +284,7 @@ static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
 
     /* 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));
@@ -293,6 +318,7 @@ static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
         Buffer = (PUCHAR)Buffer + FullSectors * Context->SectorSize;
         N -= FullSectors * Context->SectorSize;
         *Count += FullSectors * Context->SectorSize;
+        Context->SectorNumber += FullSectors;
         Lba += FullSectors;
     }
 
@@ -339,26 +365,44 @@ static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
         }
         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,
@@ -366,6 +410,7 @@ static const DEVVTBL DiskVtbl = {
     DiskSeek,
 };
 
+static
 NTSTATUS
 SpiCreatePortConfig(
     IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
@@ -586,7 +631,6 @@ ScsiPortGetPhysicalAddress(
     else
     {
         /* Nothing */
-        *Length = 0;
         PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
     }
 
@@ -608,6 +652,7 @@ ScsiPortGetSrb(
     return NULL;
 }
 
+static
 NTSTATUS
 SpiAllocateCommonBuffer(
     IN OUT PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
@@ -767,6 +812,7 @@ ScsiPortGetVirtualAddress(
     return NULL;
 }
 
+static
 VOID
 SpiScanDevice(
     IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
@@ -776,13 +822,13 @@ SpiScanDevice(
     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 */
@@ -796,8 +842,11 @@ SpiScanDevice(
             {
                 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);
                 }
             }
@@ -807,6 +856,7 @@ SpiScanDevice(
     }
 }
 
+static
 VOID
 SpiScanAdapter(
     IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
@@ -881,6 +931,7 @@ SpiScanAdapter(
     }
 }
 
+static
 VOID
 SpiResourceToConfig(
     IN PHW_INITIALIZATION_DATA HwInitializationData,
@@ -961,9 +1012,10 @@ SpiResourceToConfig(
     }
 }
 
+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)
@@ -1065,7 +1117,7 @@ NTAPI
 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;
@@ -1574,47 +1626,53 @@ LoadBootDeviceDriver(VOID)
     CHAR NtBootDdPath[MAX_PATH];
     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 */
@@ -1635,14 +1693,13 @@ LoadBootDeviceDriver(VOID)
     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 */