无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 3203|回复: 6
打印 上一主题 下一主题

目前在做一个跟HPA有关的Project,遇到一些问题,请教各位

[复制链接]
跳转到指定楼层
1#
发表于 2008-12-9 17:04:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我目前在做一个跟HPA有关的Project,遇到一些问题,请教各位。。。
我想在Windows里面动态unhide HPA partition,然后从里面读取一些资料。
发现Windows XP sp2 后提供了一个接口可以直接发送ATA command。就是用DeviceIoControl这个function和IOCTL_ATA_PASS_THROUGH这个parameter。但在实际使用时发现这种方法的确可以发送ATA Command 到磁盘控制器。但是只有Set Max address这个命令不能够成功执行。我已经按照ATA-7 standard里面的要求先发送一个Get native max address到硬盘了,结果也是正确的。但是就是下面的这个命令不能成功执行,不知道为什么?

下面是我的code:
typedef struct {
    char a0;
    char a1;
    char a2;
    char a3;
} ualign;


BOOL SetMax(HANDLE hDevice, unsigned max, bool temperary, unsigned *currentValue) {
    BOOL status = FALSE;
    PATA_PASS_THROUGH_EX pATAData, pATADataOut;
    DWORD dataSize = sizeof(ATA_PASS_THROUGH_EX) + 512;
    DWORD bytescopied = 0;
    UCHAR DriveNum = 1; //Need to be changed to the actual drive number
    DWORD lastError = ERROR_SUCCESS; //Allocate memory for ATA_PASS_THROUGH_EX and clear the contents
    pATAData = (PATA_PASS_THROUGH_EX) VirtualAlloc(NULL, dataSize, MEM_COMMIT, PAGE_READWRITE);
    pATADataOut = (PATA_PASS_THROUGH_EX) VirtualAlloc(NULL, dataSize, MEM_COMMIT, PAGE_READWRITE);
    ZeroMemory(pATAData,dataSize); //Fill in the IDENTIFY DEVICE query data
    ZeroMemory(pATADataOut, dataSize);
    pATAData->Length = sizeof(ATA_PASS_THROUGH_EX);
    pATAData->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
    pATAData->DataTransferLength = 512;
    pATAData->AtaFlags = ATA_FLAGS_DATA_IN;
    pATAData->TimeOutValue = 2; //Seconds

    pATADataOut->Length = sizeof(ATA_PASS_THROUGH_EX);
    pATADataOut->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
    pATADataOut->DataTransferLength = 512;
    pATADataOut->AtaFlags = ATA_FLAGS_DATA_OUT;
    pATADataOut->TimeOutValue = 2; //Seconds

    // Set input buf
    if (temperary)
        pATAData->CurrentTaskFile[1] = 0x00;
    else
        pATAData->CurrentTaskFile[1] = 0x01;

    ualign *p = (ualign*)&max;
    pATAData->CurrentTaskFile[2] = p->a0;
    pATAData->CurrentTaskFile[3] = p->a1;
    pATAData->CurrentTaskFile[4] = p->a2;
    pATAData->CurrentTaskFile[5] = p->a3;
    pATAData->CurrentTaskFile[5] |= 0x40;
    pATAData->CurrentTaskFile[6] = 0xF9;    // Sex max address

    pATADataOut->CurrentTaskFile[6] = 0x40;
    /* send the command*/
    status = DeviceIoControl( hDevice,
        IOCTL_ATA_PASS_THROUGH,
        pATAData,
        dataSize, /* input buffer and size */
        pATADataOut,
        dataSize, /* output buffer and size */
        &bytescopied, /* bytes copied to output buffer*/
        NULL ); /* no overlapping */
    if(!status)
        lastError = GetLastError();
    if (pATADataOut->CurrentTaskFile[0] == 0x04 || pATADataOut->CurrentTaskFile[0] == 0x14) {
        status = 0;
    }

    // Get current Value
    ualign length;
    length.a0 = pATADataOut->CurrentTaskFile[2];
    length.a1 = pATADataOut->CurrentTaskFile[3];
    length.a2 = pATADataOut->CurrentTaskFile[4];
    length.a3 = pATADataOut->CurrentTaskFile[5];
    length.a3 &= 0x0F;
    memcpy((void *)currentValue, (void *)&length, 4);
    VirtualFree(pATAData, dataSize, MEM_RELEASE);
    VirtualFree(pATADataOut, dataSize, MEM_RELEASE);
    return status;
}

上面的code应该没有问题,在一个很老旧的hard disk (IBM 4GB)上,我是可以动态改变HPA分区的大小的,但是新的硬盘却不行。但是这些新的硬盘本身肯定是支持hpa的。用IDENTIFY device看过,这些新硬盘支持ATA-7 standard, 48bit-addressing等等。Hpa是在ATA-4中引入的。。。然后我用mhdd还可以成功create hpa partition.
我还写了一个48bit version的类似的function,结果是一样的。
这个function返回的错误不是DeviceIoControl这个function本身出错,而是ata command发送到硬盘后,硬盘本身返回的result有error.
不知道有没有人做过类似的东西,如有请赐教~~
先谢过~~

[ 本帖最后由 dgxhls 于 2008-12-9 21:08 编辑 ]

评分

参与人数 1无忧币 +30 收起 理由
netwinxp + 30 我很赞同

查看全部评分

2#
发表于 2008-12-10 11:06:06 | 只看该作者
48Bits的硬盘要用SET_MAX_EXT( 0x37)和READ_NATIVE_MAX_EXT(0x27)这两条新的ATA指令。这两条指令好像出自ATA文档的PATCHER版本。
***PS:SET_MAX、SET_MAX_EXT好像要在重新启动后才生效***
***看来LZ对win下面操作硬件颇有研究,+点分数,欢迎LZ在这方面参与更多的探讨***

[ 本帖最后由 netwinxp 于 2008-12-10 11:22 编辑 ]
回复

使用道具 举报

3#
 楼主| 发表于 2008-12-11 10:58:32 | 只看该作者
多谢回复~~
这些天看了很多forum,发现问题可能是windows提供的IOCTL_ATA_PASS_THROUGH没有发送命令。MSDN上说Allows an application to send almost any ATA command to a target device。貌似windows的driver上层有一个filer来过滤ATA command。像IDENTIFY Device和READ NATIVE MAX等等non-destructive的command,filter会pass through,但是像set max address这样的destructive command就过不了filter了。。。
看来需要绕开windows的driver才能将这些command发送过去。。。
P.S.:我也试过用48bit的command,但是也不成功。。我对48bit command的理解是如果硬盘大于128GB(maximum addressing space in 28bit),就一定要用。其他情况下,用28bit的command设置的HPA只能用28bit的command修改,反之亦然~~
回复

使用道具 举报

4#
发表于 2008-12-11 15:14:40 | 只看该作者
应该不是Filer的问题,如果由application向device发送命令也失败的话,也许可能是I/O特权指令的权限问题,或许用设备驱动级而不仅仅是application级就可以了。
回复

使用道具 举报

5#
发表于 2008-12-12 18:19:35 | 只看该作者
楼主历厉害!俺水平不够!
回复

使用道具 举报

6#
发表于 2008-12-13 09:08:22 | 只看该作者
帮你顶一下,不要沉了
回复

使用道具 举报

7#
发表于 2009-5-10 14:07:37 | 只看该作者
楼主能否发源文件给我看看呀  CRCOK@tom.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-11-15 23:32

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表