⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bus.c

📁 WinAoE is an open source GPLv3 driver for using AoE (ATA over Ethernet) on Microsoft Windows
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
  Copyright 2006-2008, V.
  For contact information, see http://winaoe.org/

  This file is part of WinAoE.

  WinAoE is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  WinAoE is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with WinAoE.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "portable.h"
#include <ntddk.h>
#include "driver.h"
#include "aoe.h"
#include "mount.h"

// in this file
BOOLEAN STDCALL BusAddChild(IN PDEVICE_OBJECT BusDeviceObject, IN PUCHAR ClientMac, IN ULONG Major, IN ULONG Minor, IN BOOLEAN Boot);
NTSTATUS STDCALL IoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PKEVENT Event);

#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct _ABFT {
  UINT Signature;               // 0x54464261 (aBFT)
  UINT Length;
  UCHAR Revision;
  UCHAR Checksum;
  UCHAR OEMID[6];
  UCHAR OEMTableID[8];
  UCHAR Reserved1[12];
  USHORT Major;
  UCHAR Minor;
  UCHAR Reserved2;
  UCHAR ClientMac[6];
} __attribute__((__packed__)) ABFT, *PABFT;
#ifdef _MSC_VER
#pragma pack()
#endif

typedef struct _TARGETLIST {
  TARGET Target;
  struct _TARGETLIST *Next;
} TARGETLIST, *PTARGETLIST;

PTARGETLIST TargetList = NULL;
KSPIN_LOCK TargetListSpinLock;
ULONG NextDisk = 0;

NTSTATUS STDCALL BusStart() {
  DbgPrint("BusStart\n");
  KeInitializeSpinLock(&TargetListSpinLock);
  return STATUS_SUCCESS;
}

VOID STDCALL BusStop() {
  UNICODE_STRING DosDeviceName;
  PTARGETLIST Walker, Next;
  KIRQL Irql;

  DbgPrint("BusStop\n");
  KeAcquireSpinLock(&TargetListSpinLock, &Irql);
  Walker = TargetList;
  while (Walker != NULL) {
    Next = Walker->Next;
    ExFreePool(Walker);
    Walker = Next;
  }
  KeReleaseSpinLock(&TargetListSpinLock, Irql);
  RtlInitUnicodeString(&DosDeviceName, L"\\DosDevices\\AoE");
  IoDeleteSymbolicLink(&DosDeviceName);
}

NTSTATUS STDCALL BusAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) {
  NTSTATUS Status;
  PHYSICAL_ADDRESS PhysicalAddress;
  PUCHAR PhysicalMemory;
  UINT Offset, Checksum, i;
  ABFT AOEBootRecord;
  BOOLEAN FoundAbft = FALSE;
  UNICODE_STRING DeviceName, DosDeviceName;
  PDEVICEEXTENSION DeviceExtension;
  PDEVICE_OBJECT DeviceObject;

  DbgPrint("BusAddDevice\n");
  RtlInitUnicodeString(&DeviceName, L"\\Device\\AoE");
  RtlInitUnicodeString(&DosDeviceName, L"\\DosDevices\\AoE");
  if (!NT_SUCCESS(Status = IoCreateDevice(DriverObject, sizeof(DEVICEEXTENSION), &DeviceName, FILE_DEVICE_CONTROLLER, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject))) {
    return Error("BusAddDevice IoCreateDevice", Status);
  }
  if (!NT_SUCCESS(Status = IoCreateSymbolicLink(&DosDeviceName, &DeviceName))) {
    IoDeleteDevice(DeviceObject);
    return Error("BusAddDevice IoCreateSymbolicLink", Status);
  }

  DeviceExtension = (PDEVICEEXTENSION)DeviceObject->DeviceExtension;
  RtlZeroMemory(DeviceExtension, sizeof(DEVICEEXTENSION));
  DeviceExtension->IsBus = TRUE;
  DeviceExtension->DriverObject = DriverObject;
  DeviceExtension->Self = DeviceObject;
  DeviceExtension->State = NotStarted;
  DeviceExtension->OldState = NotStarted;
  DeviceExtension->Bus.PhysicalDeviceObject = PhysicalDeviceObject;
  DeviceExtension->Bus.Children = 0;
  DeviceExtension->Bus.ChildList = NULL;
  KeInitializeSpinLock(&DeviceExtension->Bus.SpinLock);
  DeviceObject->Flags |= DO_DIRECT_IO;                  // FIXME?
  DeviceObject->Flags |= DO_POWER_INRUSH;               // FIXME?
  if (PhysicalDeviceObject != NULL) {
    if ((DeviceExtension->Bus.LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject)) == NULL) {
      IoDeleteDevice(DeviceObject);
      return Error("AddDevice IoAttachDeviceToDeviceStack", STATUS_NO_SUCH_DEVICE);
    }
  }
  DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

  PhysicalAddress.QuadPart = 0LL;
  PhysicalMemory = MmMapIoSpace(PhysicalAddress, 0xa0000, MmNonCached);
  if (!PhysicalMemory) {
    DbgPrint("Could not map low memory\n");
  } else {
    for (Offset = 0; Offset < 0xa0000; Offset += 0x10) {
      if (((PABFT)&PhysicalMemory[Offset])->Signature == 0x54464261) {
        Checksum = 0;
        for (i = 0; i < ((PABFT)&PhysicalMemory[Offset])->Length; i++) Checksum += PhysicalMemory[Offset + i];
        if (Checksum & 0xff) continue;
        if (((PABFT)&PhysicalMemory[Offset])->Revision != 1) {
          DbgPrint("Found aBFT with mismatched revision v%d at segment 0x%4x. want v1.\n", ((PABFT)&PhysicalMemory[Offset])->Revision, (Offset / 0x10));
          continue;
        }
        DbgPrint("Found aBFT at segment: 0x%04x\n", (Offset / 0x10));
        RtlCopyMemory(&AOEBootRecord, &PhysicalMemory[Offset], sizeof(ABFT));
        FoundAbft = TRUE;
        break;
      }
    }
    MmUnmapIoSpace(PhysicalMemory, 0xa0000);
  }

#ifdef RIS
  FoundAbft = TRUE;
  RtlCopyMemory(AOEBootRecord.ClientMac, "\x00\x0c\x29\x34\x69\x34", 6);
  AOEBootRecord.Major = 0;
  AOEBootRecord.Minor = 10;
#endif

  if (FoundAbft) {
    DbgPrint("Boot from client NIC %02x:%02x:%02x:%02x:%02x:%02x to major: %d minor: %d\n", AOEBootRecord.ClientMac[0], AOEBootRecord.ClientMac[1], AOEBootRecord.ClientMac[2], AOEBootRecord.ClientMac[3], AOEBootRecord.ClientMac[4], AOEBootRecord.ClientMac[5], AOEBootRecord.Major, AOEBootRecord.Minor);
    if (!BusAddChild(DeviceObject, AOEBootRecord.ClientMac, AOEBootRecord.Major, AOEBootRecord.Minor, TRUE)) {
      DbgPrint("BusAddChild failed\n");
    } else {
      if (DeviceExtension->Bus.PhysicalDeviceObject != NULL) IoInvalidateDeviceRelations(DeviceExtension->Bus.PhysicalDeviceObject, BusRelations);
    }
  } else {
    DbgPrint("Not booting...\n");
  }
#ifdef RIS
  DeviceExtension->State = Started;
#endif
  return STATUS_SUCCESS;
}

VOID STDCALL BusAddTarget(IN PUCHAR ClientMac, IN PUCHAR ServerMac, USHORT Major, UCHAR Minor, LONGLONG LBASize) {
  PTARGETLIST Walker, Last;
  KIRQL Irql;

  KeAcquireSpinLock(&TargetListSpinLock, &Irql);
  Last = TargetList;
  Walker = TargetList;
  while (Walker != NULL) {
    if ((RtlCompareMemory(&Walker->Target.ClientMac, ClientMac, 6) == 6) && (RtlCompareMemory(&Walker->Target.ServerMac, ServerMac, 6) == 6) && Walker->Target.Major == Major && Walker->Target.Minor == Minor) {
      if (Walker->Target.LBASize != LBASize) {
        DbgPrint("BusAddTarget LBASize changed for e%d.%d (%I64u->%I64u)\n", Major, Minor, Walker->Target.LBASize, LBASize);
        Walker->Target.LBASize = LBASize;
      }
      KeQuerySystemTime(&Walker->Target.ProbeTime);
      KeReleaseSpinLock(&TargetListSpinLock, Irql);
      return;
    }
    Last = Walker;
    Walker = Walker->Next;
  }

  if ((Walker = (PTARGETLIST)ExAllocatePool(NonPagedPool, sizeof(TARGETLIST))) == NULL) {
    DbgPrint("BusAddTarget ExAllocatePool Target\n");
    KeReleaseSpinLock(&TargetListSpinLock, Irql);
    return;
  }
  Walker->Next = NULL;
  RtlCopyMemory(Walker->Target.ClientMac, ClientMac, 6);
  RtlCopyMemory(Walker->Target.ServerMac, ServerMac, 6);
  Walker->Target.Major = Major;
  Walker->Target.Minor = Minor;
  Walker->Target.LBASize = LBASize;
  KeQuerySystemTime(&Walker->Target.ProbeTime);

  if (Last == NULL) {
    TargetList = Walker;
  } else {
    Last->Next = Walker;
  }
  KeReleaseSpinLock(&TargetListSpinLock, Irql);
}

VOID STDCALL BusCleanupTargetList() {
}

BOOLEAN STDCALL BusAddChild(IN PDEVICE_OBJECT BusDeviceObject, IN PUCHAR ClientMac, IN ULONG Major, IN ULONG Minor, IN BOOLEAN Boot) {
  NTSTATUS Status;
  PDEVICEEXTENSION BusDeviceExtension = (PDEVICEEXTENSION)BusDeviceObject->DeviceExtension;
  PDEVICE_OBJECT DeviceObject;
  PDEVICEEXTENSION DeviceExtension, Walker;

  DbgPrint("BusAddChild\n");
  if (!NT_SUCCESS(Status = IoCreateDevice(BusDeviceExtension->DriverObject, sizeof(DEVICEEXTENSION), NULL, FILE_DEVICE_DISK, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject))) {
    Error("BusAddChild IoCreateDevice", Status);
    return FALSE;
  }
  DeviceExtension = (PDEVICEEXTENSION)DeviceObject->DeviceExtension;
  RtlZeroMemory(DeviceExtension, sizeof(DEVICEEXTENSION));

  DeviceExtension->IsBus = FALSE;
  DeviceExtension->Self = DeviceObject;
  DeviceExtension->DriverObject = BusDeviceExtension->DriverObject;
  DeviceExtension->State = NotStarted;
  DeviceExtension->OldState = NotStarted;

  DeviceExtension->Disk.Parent = BusDeviceObject;
  DeviceExtension->Disk.Next = NULL;
  KeInitializeEvent(&DeviceExtension->Disk.SearchEvent, SynchronizationEvent, FALSE);
  KeInitializeSpinLock(&DeviceExtension->Disk.SpinLock);
  DeviceExtension->Disk.BootDrive = Boot;
  DeviceExtension->Disk.Unmount = FALSE;
  DeviceExtension->Disk.DiskNumber = InterlockedIncrement(&NextDisk) - 1;
  RtlCopyMemory(DeviceExtension->Disk.ClientMac, ClientMac, 6);
  RtlFillMemory(DeviceExtension->Disk.ServerMac, 6, 0xff);
  DeviceExtension->Disk.Major = Major;
  DeviceExtension->Disk.Minor = Minor;
  DeviceExtension->Disk.MaxSectorsPerPacket = 1;
  DeviceExtension->Disk.Timeout = 200000;               // 20 ms.

  DeviceObject->Flags |= DO_DIRECT_IO;                  // FIXME?
  DeviceObject->Flags |= DO_POWER_INRUSH;               // FIXME?
  AoESearchDrive(DeviceExtension);
  DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  if (BusDeviceExtension->Bus.ChildList == NULL) {
    BusDeviceExtension->Bus.ChildList = DeviceExtension;
  } else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -