eboot分区的困惑

传给分区函数BP_LowLevelFormat()的扇区参数是逻辑地址。分完区,在记录分区信息的时候,将写入在IMAGE_START_BLOCK的 第一个扇区,大小是一个扇区大小,即512 byte。开始三个字节须保证为0xE9,0xFD,0xFF。最后两个字节须保证为0x55,0xAA。分区表信息是一个结构体PARTENTRY,默 认四个。位置在最后两个字节之前。
结构体大小为16个字节
typedef struct _PARTENTRY {
        BYTE            Part_BootInd;           // If 80h means this is boot partition
        BYTE            Part_FirstHead;         // Partition starting head based 0
        BYTE            Part_FirstSector;       // Partition starting sector based 1
        BYTE            Part_FirstTrack;        // Partition starting track based 0
        BYTE            Part_FileSystem;        // Partition type signature field
        BYTE            Part_LastHead;          // Partition ending head based 0
        BYTE            Part_LastSector;        // Partition ending sector based 1
        BYTE            Part_LastTrack;         // Partition ending track based 0
        DWORD           Part_StartSector;       // Logical starting sector based 0
        DWORD           Part_TotalSectors;      // Total logical sectors in partition
} PARTENTRY;

这里面的地址信息是一种叫CHS(Cyinder/Head/Sector)的地址。eboot中有将逻辑地址LBS(Logical Block Addr)与这种地址互相转换的函数LBAtoCHS,CHSToLBA。
Addr LBAtoCHS(FlashInfo *pFlashInfo, Addr lba)
{
    Addr chs;
    DWORD tmp = pFlashInfo->dwNumBlocks * pFlashInfo->wSectorsPerBlock;

    chs.type = CHS;
    chs.chs.cylinder = (WORD)(lba.lba / tmp);                                      // 柱面,应该始终是0
    tmp = lba.lba % tmp;
    chs.chs.head = (WORD)(tmp / pFlashInfo->wSectorsPerBlock);                     // 块地址
    chs.chs.sector = (WORD)((tmp % pFlashInfo->wSectorsPerBlock) + 1);     // 扇区+1

    return chs;
}

Addr CHStoLBA(FlashInfo *pFlashInfo, Addr chs)
{
    Addr lba;

    lba.type = LBA;
    lba.lba = ((chs.chs.cylinder * pFlashInfo->dwNumBlocks + chs.chs.head)
        * pFlashInfo->wSectorsPerBlock)+ chs.chs.sector - 1;

    return lba;
}

赋值给PARTENTRY并写入的函数这里:
void AddPartitionTableEntry(DWORD entry, DWORD startSector, DWORD totalSectors, BYTE fileSystem, BYTE bootInd)
{
    PARTENTRY partentry = {0};
    Addr startAddr;
    Addr endAddr;

    partentry.Part_BootInd = bootInd;
    partentry.Part_FileSystem = fileSystem;
    partentry.Part_StartSector = startSector;
    partentry.Part_TotalSectors = totalSectors;

    startAddr.type = LBA;
    startAddr.lba = partentry.Part_StartSector;
    endAddr.type = LBA;
    endAddr.lba = partentry.Part_StartSector + partentry.Part_TotalSectors-1;

    startAddr = LBAtoCHS(&g_FlashInfo, startAddr);
    endAddr = LBAtoCHS(&g_FlashInfo, endAddr);

    partentry.Part_FirstTrack = (BYTE)(startAddr.chs.cylinder & 0xFF);
    partentry.Part_FirstHead = (BYTE)(startAddr.chs.head & 0xFF);
    // lower 6-bits == sector, upper 2-bits = cylinder upper 2-bits of 10-bit cylinder #
    partentry.Part_FirstSector = (BYTE)((startAddr.chs.sector & 0x3F) | ((startAddr.chs.cylinder & 0x0300) >> 2));

    partentry.Part_LastTrack = (BYTE)(endAddr.chs.cylinder & 0xFF);
    partentry.Part_LastHead = (BYTE)(endAddr.chs.head & 0xFF);
    // lower 6-bits == sector, upper 2-bits = cylinder upper 2-bits of 10-bit cylinder #
    partentry.Part_LastSector = (BYTE)((endAddr.chs.sector & 0x3F) | ((endAddr.chs.cylinder & 0x0300) >> 2));

    memcpy(g_pbMBRSector+PARTTABLE_OFFSET+(sizeof(PARTENTRY)*entry), &partentry, sizeof(PARTENTRY));
}

我的疑惑是在LBAToCHS转换的时候,给Head字段赋值只取了8位,在应用中肯定是有超过8位数的情况,比如我使用的是64M NandFlash,
在存储完Nk.bin后将剩余的容量全部分成一个可读写的区,这个区在写分区信息的Head字段时肯定超过了8个字节。那么,在使用CHSToLBA
转换时,不是无法得到有效的逻辑地址吗?实际上第一个分区也是这样的,在上面代码的endAddr中。

我的MBR扇区内空:
xiaoyunsoft/>dump 0x140 1 f
Getting SectorInfo...
Reserved1   : 0x00000000
OEMReserved : 0x000000FD
BadBlock    : 0x000000FF
Reserved2   : 0x0000FFFB
  0x32000000:  E9 FD FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000010:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000020:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000030:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000040:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000050:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000060:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000070:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000080:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000090:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x320000A0:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x320000B0:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x320000C0:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x320000D0:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x320000E0:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x320000F0:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000100:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000110:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000120:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000130:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000140:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000150:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000160:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000170:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000180:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x32000190:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x320001A0:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
  0x320001B0:  FF FF FF FF FF FF FF FF FF FF FF FF FF FF 03 01
  0x320001C0:  01 00 21 16 20 00 20 00 00 00 C0 E2 00 00 01 17
  0x320001D0:  01 00 0B EB 20 00 E0 E2 00 00 A0 1A 01 00 00 00
  0x320001E0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x320001F0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
  0x32000200:  00 00 00 00 FD FF FB FF 00 00 00 00 00 00 00 00
addr:0x32000000,len:0x00000084 dump complete...

分析第一个分区信息结构,地下从0x320001BE开始:
Part_BootInd     :0x03
Part_FirstHead   :0x01
Part_FirstSector :0x01
Part_FirstTrack  :0x00
Part_FileSystem  :0x21
Part_LastHead    :0x16
Part_LastSector  :0x20
Part_LastTrack   :0x00
Part_StartSector :0x00000020
Part_TotalSectors:0x0000E2C0

按照上面的值,套用CHSToLBA()算一下逻辑地址(cylinder==0):
firstAddr=FirstHead*32+FirstSector-1 = 0x20; // 这个值是正确的,因为Head存储是正确的。
lastAddr=LastHead*32+LastSector-1 = 0x2E0-1; // 显然这个值是不正确的(E2E0),这就是我的疑惑。

难道WINCE启动时没有在这里读取分区信息吗?

附Addr结构体的声明:
typedef struct _CHSAddr
{
    WORD cylinder;
    WORD head;
    WORD sector;
} CHSAddr, *PCHSAddr;

typedef DWORD LBAAddr, *PLBAAddr;

typedef enum { CHS, LBA } CHSLBA ;

typedef struct _Addr
{
    CHSLBA type;
    union
    {
        LBAAddr lba;
        CHSAddr chs;
    };
} Addr, *PAddr;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值