Beispiel #1
0
static PCM_PARTIAL_RESOURCE_LIST
GetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
{
  PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
  PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
  //EXTENDED_GEOMETRY ExtGeometry;
  GEOMETRY Geometry;
  ULONG Size;

    //
    // Initialize returned size
    //
    *pSize = 0;

  /* Set 'Configuration Data' value */
  Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
	 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
  PartialResourceList = MmHeapAlloc(Size);
  if (PartialResourceList == NULL)
    {
      ERR("Failed to allocate a full resource descriptor\n");
      return NULL;
    }

  memset(PartialResourceList, 0, Size);
  PartialResourceList->Version = 1;
  PartialResourceList->Revision = 1;
  PartialResourceList->Count = 1;
  PartialResourceList->PartialDescriptors[0].Type =
    CmResourceTypeDeviceSpecific;
//  PartialResourceList->PartialDescriptors[0].ShareDisposition =
//  PartialResourceList->PartialDescriptors[0].Flags =
  PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
    sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);

  /* Get pointer to geometry data */
  DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));

  /* Get the disk geometry */
  //ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);

  if(MachDiskGetDriveGeometry(DriveNumber, &Geometry))
    {
      DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
      DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
      DiskGeometry->SectorsPerTrack = Geometry.Sectors;
      DiskGeometry->NumberOfHeads = Geometry.Heads;
    }
  else
    {
      ERR("Reading disk geometry failed\n");
      MmHeapFree(PartialResourceList);
      return NULL;
    }
  TRACE("Disk %x: %u Cylinders  %u Heads  %u Sectors  %u Bytes\n",
	    DriveNumber,
	    DiskGeometry->NumberOfCylinders,
	    DiskGeometry->NumberOfHeads,
	    DiskGeometry->SectorsPerTrack,
	    DiskGeometry->BytesPerSector);

    //
    // Return configuration data
    //
    *pSize = Size;
    return PartialResourceList;
}
Beispiel #2
0
BOOLEAN CacheInitializeDrive(UCHAR DriveNumber)
{
    PCACHE_BLOCK    NextCacheBlock;
    GEOMETRY    DriveGeometry;

    // If we already have a cache for this drive then
    // by all means lets keep it, unless it is a removable
    // drive, in which case we'll invalidate the cache
    if ((CacheManagerInitialized == TRUE) &&
        (DriveNumber == CacheManagerDrive.DriveNumber) &&
        (DriveNumber >= 0x80) &&
        (CacheManagerDataInvalid != TRUE))
    {
        return TRUE;
    }

    CacheManagerDataInvalid = FALSE;

    //
    // If we have already been initialized then free
    // the old data
    //
    if (CacheManagerInitialized)
    {
        CacheManagerInitialized = FALSE;

        TRACE("CacheBlockCount: %d\n", CacheBlockCount);
        TRACE("CacheSizeLimit: %d\n", CacheSizeLimit);
        TRACE("CacheSizeCurrent: %d\n", CacheSizeCurrent);
        //
        // Loop through and free the cache blocks
        //
        while (!IsListEmpty(&CacheManagerDrive.CacheBlockHead))
        {
            NextCacheBlock = CONTAINING_RECORD(RemoveHeadList(&CacheManagerDrive.CacheBlockHead),
                                               CACHE_BLOCK,
                                               ListEntry);

            FrLdrTempFree(NextCacheBlock->BlockData, TAG_CACHE_DATA);
            FrLdrTempFree(NextCacheBlock, TAG_CACHE_BLOCK);
        }
    }

    // Initialize the structure
    RtlZeroMemory(&CacheManagerDrive, sizeof(CACHE_DRIVE));
    InitializeListHead(&CacheManagerDrive.CacheBlockHead);
    CacheManagerDrive.DriveNumber = DriveNumber;
    if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry))
    {
        return FALSE;
    }
    CacheManagerDrive.BytesPerSector = DriveGeometry.BytesPerSector;

    // Get the number of sectors in each cache block
    CacheManagerDrive.BlockSize = MachDiskGetCacheableBlockCount(DriveNumber);

    CacheBlockCount = 0;
    CacheSizeLimit = TotalPagesInLookupTable / 8 * MM_PAGE_SIZE;
    CacheSizeCurrent = 0;
    if (CacheSizeLimit > TEMP_HEAP_SIZE - (128 * 1024))
    {
        CacheSizeLimit = TEMP_HEAP_SIZE - (128 * 1024);
    }

    CacheManagerInitialized = TRUE;

    TRACE("Initializing BIOS drive 0x%x.\n", DriveNumber);
    TRACE("BytesPerSector: %d.\n", CacheManagerDrive.BytesPerSector);
    TRACE("BlockSize: %d.\n", CacheManagerDrive.BlockSize);
    TRACE("CacheSizeLimit: %d.\n", CacheSizeLimit);

    return TRUE;
}
Beispiel #3
0
static VOID
DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
                PCONFIGURATION_COMPONENT_DATA BusKey)
{
    PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
    PCM_INT13_DRIVE_PARAMETER Int13Drives;
    GEOMETRY Geometry;
    PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey;
    UCHAR DiskCount, i;
    ULONG Size;
    BOOLEAN Changed;
    
    /* Count the number of visible drives */
    DiskReportError(FALSE);
    DiskCount = 0;
    
    /* There are some really broken BIOSes out there. There are even BIOSes
        * that happily report success when you ask them to read from non-existent
        * harddisks. So, we set the buffer to known contents first, then try to
        * read. If the BIOS reports success but the buffer contents haven't
        * changed then we fail anyway */
    memset((PVOID) DISKREADBUFFER, 0xcd, 512);
    while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER))
    {
        Changed = FALSE;
        for (i = 0; ! Changed && i < 512; i++)
        {
            Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
        }
        if (! Changed)
        {
            TRACE("BIOS reports success for disk %d but data didn't change\n",
                  (int)DiskCount);
            break;
        }
        DiskCount++;
        memset((PVOID) DISKREADBUFFER, 0xcd, 512);
    }
    DiskReportError(TRUE);
    TRACE("BIOS reports %d harddisk%s\n",
          (int)DiskCount, (DiskCount == 1) ? "": "s");
    
    //DetectBiosFloppyController(BusKey);
    
    /* Allocate resource descriptor */
    Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
        sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
    PartialResourceList = MmHeapAlloc(Size);
    if (PartialResourceList == NULL)
    {
        ERR("Failed to allocate resource descriptor\n");
        return;
    }
    
    /* Initialize resource descriptor */
    memset(PartialResourceList, 0, Size);
    PartialResourceList->Version = 1;
    PartialResourceList->Revision = 1;
    PartialResourceList->Count = 1;
    PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific;
    PartialResourceList->PartialDescriptors[0].ShareDisposition = 0;
    PartialResourceList->PartialDescriptors[0].Flags = 0;
    PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
        sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
    
    /* Get harddisk Int13 geometry data */
    Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
    for (i = 0; i < DiskCount; i++)
    {
        if (MachDiskGetDriveGeometry(0x80 + i, &Geometry))
        {
            Int13Drives[i].DriveSelect = 0x80 + i;
            Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
            Int13Drives[i].SectorsPerTrack = (USHORT)Geometry.Sectors;
            Int13Drives[i].MaxHeads = (USHORT)Geometry.Heads - 1;
            Int13Drives[i].NumberDrives = DiskCount;
            
            TRACE(
                      "Disk %x: %u Cylinders  %u Heads  %u Sectors  %u Bytes\n",
                      0x80 + i,
                      Geometry.Cylinders - 1,
                      Geometry.Heads -1,
                      Geometry.Sectors,
                      Geometry.BytesPerSector);
        }
    }
    
    FldrCreateComponentKey(BusKey,
                           ControllerClass,
                           DiskController,
                           Output | Input,
                           0,
                           0xFFFFFFFF,
                           NULL,
                           PartialResourceList,
                           Size,
                           &ControllerKey);
    TRACE("Created key: DiskController\\0\n");
    
    MmHeapFree(PartialResourceList);
    
    /* Create and fill subkey for each harddisk */
    for (i = 0; i < DiskCount; i++)
    {
        PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
        ULONG Size;
        CHAR Identifier[20];

        /* Get disk values */
        PartialResourceList = GetHarddiskConfigurationData(0x80 + i, &Size);
        GetHarddiskIdentifier(Identifier, 0x80 + i);

        /* Create disk key */
        FldrCreateComponentKey(ControllerKey,
                               PeripheralClass,
                               DiskPeripheral,
                               Output | Input,
                               0,
                               0xFFFFFFFF,
                               Identifier,
                               PartialResourceList,
                               Size,
                               &DiskKey);

        if (PartialResourceList)
            MmHeapFree(PartialResourceList);
    }
}
Beispiel #4
0
static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{
    UCHAR PhysicalSector;
    UCHAR PhysicalHead;
    ULONG PhysicalTrack;
    GEOMETRY DriveGeometry;
    ULONG NumberOfSectorsToRead;
    REGS RegsIn, RegsOut;
    ULONG RetryCount;

    TRACE("PcDiskReadLogicalSectorsCHS()\n");

    /* Get the drive geometry */
    if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
        DriveGeometry.Sectors == 0 ||
        DriveGeometry.Heads == 0)
    {
        return FALSE;
    }

    while (SectorCount)
    {
        /*
         * Calculate the physical disk offsets.
         * Note: DriveGeometry.Sectors < 64
         */
        PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.Sectors);
        PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads);
        PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads);

        /* Calculate how many sectors we need to read this round */
        if (PhysicalSector > 1)
        {
            if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
                NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
            else
                NumberOfSectorsToRead = SectorCount;
        }
        else
        {
            if (SectorCount >= DriveGeometry.Sectors)
                NumberOfSectorsToRead = DriveGeometry.Sectors;
            else
                NumberOfSectorsToRead = SectorCount;
        }

        /* Make sure the read is within the geometry boundaries */
        if ((PhysicalHead >= DriveGeometry.Heads) ||
            (PhysicalTrack >= DriveGeometry.Cylinders) ||
            ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
            (PhysicalSector > DriveGeometry.Sectors))
        {
            DiskError("Disk read exceeds drive geometry limits.", 0);
            return FALSE;
        }

        /*
         * BIOS Int 13h, function 2 - Read Disk Sectors
         * AH = 02h
         * AL = number of sectors to read (must be nonzero)
         * CH = low eight bits of cylinder number
         * CL = sector number 1-63 (bits 0-5)
         *      high two bits of cylinder (bits 6-7, hard disk only)
         * DH = head number
         * DL = drive number (bit 7 set for hard disk)
         * ES:BX -> data buffer
         * Return:
         * CF set on error
         * if AH = 11h (corrected ECC error), AL = burst length
         * CF clear if successful
         * AH = status
         * AL = number of sectors transferred
         *  (only valid if CF set for some BIOSes)
         */
        RegsIn.b.ah = 0x02;
        RegsIn.b.al = (UCHAR)NumberOfSectorsToRead;
        RegsIn.b.ch = (PhysicalTrack & 0xFF);
        RegsIn.b.cl = (UCHAR)(PhysicalSector + ((PhysicalTrack & 0x300) >> 2));
        RegsIn.b.dh = PhysicalHead;
        RegsIn.b.dl = DriveNumber;
        RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
        RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F;

        /* Perform the read. Retry 3 times. */
        for (RetryCount=0; RetryCount<3; RetryCount++)
        {
            Int386(0x13, &RegsIn, &RegsOut);

            /* If it worked break out */
            if (INT386_SUCCESS(RegsOut))
            {
                break;
            }
            /* If it was a corrected ECC error then the data is still good */
            else if (RegsOut.b.ah == 0x11)
            {
                break;
            }
            /* If it failed the do the next retry */
            else
            {
                DiskResetController(DriveNumber);
                continue;
            }
        }

        /* If we retried 3 times then fail */
        if (RetryCount >= 3)
        {
            ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x\n", RegsOut.b.ah);
            return FALSE;
        }

        // I have learned that not all BIOSes return
        // the sector read count in the AL register (at least mine doesn't)
        // even if the sectors were read correctly. So instead
        // of checking the sector read count we will rely solely
        // on the carry flag being set on error

        Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfSectorsToRead * DriveGeometry.BytesPerSector));
        SectorCount -= NumberOfSectorsToRead;
        SectorNumber += NumberOfSectorsToRead;
    }

    return TRUE;
}