WINCE6.0+NAND FLASH分区的实现

WINCE6.0+NAND FLASH分区的实现

 

备注:NAND FLASH为K9K8G08U0D-SCB0。

 

//Nboot(1)+TOC(1)+Eboot(4)+LOGO(3)+SystemInfo(1)+MBR(1)+NK(BINFS)//最新的

Nboot(1)+TOC(1)+Eboot(4)//原始的

+ DOS3_FAT(对应SysDisk盘符的分区)+ DOS32(对应FlashDisk盘符的分区)

Format Boot Mediafor BinFS

 

 

Eboot中,将内核加载到SDRAM之后,启动内核之前,将MBR写入到nand Flash中。

 

Windows CE挂载nand的盘的方式类似于Windows挂载硬盘的方式类似,在nand flash上写如MBR。从MBR的格式可以看出,Windows CE最多支持4各个分区。

       硬盘主引导记录MBR 4个部分组成:主引导程序,数据区,分区表,结束标志字。

 

1.     相关概念

 

1.1  MBR

master boot record(MBR),占用512字节,硬盘主引导记录MBR由 4个部分组成:主引导程序,数据区,分区表,结束标志字。

 

1.2  BINFS

binary ROM imagefile system (BinFS)

 

If a boot loaderincludes support for the binary ROM image file system (BinFS), the boot loadercan partition, format, and write data to a specified media device. Through theBootpart library, the boot loader writes to flash media. The boot loader usesthe Bootpart library to create partitioning. This partitioning is necessary forboth BinFS and another file system, such as FAT, to be flashed on the samemedia device. To accomplish partitioning, the boot loader uses the Bootpartlibrary to create a BinFS partition along with an extended partition. The OSuses these partitions to create one or more data partitions inside of theextended partition. The extended partition is required because the OS cannotmodify the master boot record (MBR) once the boot loader's Bootpart librarypartitions flash memory.

 

The Bootpartlibrary can create a boot partition to store boot arguments. The flash memoryblocks that contain the MBR sector, the BinFS memory region, and the bootarguments partition are marked as read-only. In addition, the BinFS and bootpartitions are marked as read-only so that the partitions cannot be formattedor deleted.

 

Bootpart enablescode for a Flash Media Driver (FMD) to be abstracted from the boot loader. Theboot loader creates the partition and reads or writes to the partition byspecifying a byte offset into the partition, as well as a length value.Bootpart can also perform a low level format on the flash media.

 

To support BinFS,your boot loader must link to the Bootpart library located in the%_WINCEROOT%\Public\Common\Oak\Drivers\EthDbg\Bootpart directory.

 

For moreinformation on the Bootpart library see, Bootpart Library Functions. You canview a sample boot loader that supports BinFS in the%_WINCEROOT%\Platform\SMDK2410\Eboot directory.

 

1.3  相关的结构体

 

(1)  FlashInfo

typedef struct _FlashInfo
{
    FLASH_TYPE  flashType;
    DWORD       dwNumBlocks;
    DWORD       dwBytesPerBlock;
    WORD        wSectorsPerBlock;
    WORD        wDataBytesPerSector;

}FlashInfo, *PFlashInfo;

flashType表示flash的类型,NAND或是NOR。

dwNumBlocks表示一片FLASH总共包含的块数量,这里为8192。

dwBytesPerBlock表示一块中包含多少个字节(不包含spare),这里为64*2048。

wSectorsPerBlock表示一块包含多少页,这里为64。

wDataBytesPerSector表示一页中包含多少字节,这里为2048

一个FlashInfo结构体变量占用13个字节。

 

(2)  SectorInfo

typedef struct _SectorInfo
{
    DWORD dwReserved1;              // Reserved - used by FAL
    BYTE  bOEMReserved;             // For use by OEM
    BYTE  bBadBlock;	            // Indicates if block is BAD
    WORD  wReserved2;               // Reserved - used by FAL
    
}SectorInfo, *PSectorInfo;

dwReserved1 FAL用来保存逻辑页到物理页的映射信息。

bOEMReserved,我们可以用来设置block的属性,比如设置此block为预留block,或是只读block等。

bBadBlock表示坏块信息,如果其值为0xFF表示是好块,如果不是则为坏块。

wReserved2用来为FAL只是数据是否有效(Indicates data is valid for the FAL( flashabstraction layer))。

 

(3)  PARTENTRY

 

// end of master boot record contains 4 partition entries
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;

2.     分区的实现

 

 

2.1  BP_Init

 

Windows CE下的FLASH驱动分为两层,分别为FMD层和FAL层(flash abstraction layer),FMD(Flash Media Driver)属于底层,直接操作Flash硬件,比如读、写和擦除等,不同的Flash硬件则FMD_XXX接口实现函数各不相同,上层则是FAL (Flash Abstraction Layer)层,该层是由微软实现并提供的,是一个与硬件无关的层,可用于FAL层实现扇区的动态分配和坏块管理等。FAL层向应用层(如API)提供DSK接口。例如CreateFile中调用的设备即是调用该FAL层提供的接口。FMD层暴露FMD_XXX让FAL层调用。

微软NAND FLASH块驱动的FAL部分使用此8字节的SectorInfo结构体模拟flash实际扩展区域的典型物理布局,也就是说此结构体描述了spare area所保存的内容。下面是此函数主要实现部分:

WINCE6.0+NAND FLASH分区的实现_第1张图片

图1

BP_Init函数同时初始化了用于记录分区信息的结构体全局数组g_partStateTable,此结构体定义如下:

typedef struct _PARTSTATE {
        PPARTENTRY  pPartEntry;
        DWORD         dwDataPointer;        // Pointer to where next read and write will occur
} PARTSTATE, *PPARTSTATE;

pPartEntry记录每个分区信息的结构体,bootpart默认最大支持4个分区。

dwDataPointer指向解析来要进行的读或是写的地方。

 

调用BP_Init函数后,内存中一些变量被初始化为指向具体的内存单元处,如下图:

WINCE6.0+NAND FLASH分区的实现_第2张图片

图2

 

2.2  BP_LowLevelFormat

如果是新的flash,就需要为保存NK的BINFS格式化flash,这对应于bootloader菜单的“9) Format Boot Media for BinFS\r\n”,如下图:

WINCE6.0+NAND FLASH分区的实现_第3张图片

图3

该函数用于低级格式化,它会格式化Flash设备中的Block,重新创建MBR并将MBR存到第一个Blockd的第一个扇区中。dwStartBlock为起始Block,dwNumBlocks为多少个Block,dwFlags为格式化标记位,表示采用何种格式化方式。该函数会根据需要来由EBOOT中的函数调用,下面来看此函数体:

WINCE6.0+NAND FLASH分区的实现_第4张图片

图4

下面重点介绍CreateMBR,看是如何创建MBR的。

WINCE6.0+NAND FLASH分区的实现_第5张图片

图5

可见WINCE FLASH的MBR和 硬盘的MBR不同,NAND FLASH的MBR没有主引导程序,取而代之的是0xE9、0xfd、0xff开头的标志位,总结WINCE的MBR布局如下:

 WINCE6.0+NAND FLASH分区的实现_第6张图片

图6

接下来看WriteMBR函数

WINCE6.0+NAND FLASH分区的实现_第7张图片

图7

因为我们FLASH的布局是:nboot(第0block)+TOC(第1block)+EBOOT(第2到第5block)+MBR(从第6block开始的第一个好块)+NK+用户数据,而我假设第6block就是好块,结合图15可知,g_dwMBRSectorNum=6*64=384page,也就是第6个block的第0个page。

 

到此已经把eboot之后的所有block格式化了,并且把第一次的MBR数据写入到MBR所在的block中了,虽然此MBR的分区表信息暂时还是空的,因为到此为止还没有创建有效的分区表,后面继续。

 

2.3  BP_OpenPartition

Eboot烧录NK的时候,调用WriteOSImageToBootMedia--->BP_OpenPartition来创建分区,在这里我们总共分别创建PART_BINFS、PART_DOS3_FAT和PART_DOS32这3个分区,此函数是用来打开或是创建一个分区的。

(1)  创建PART_BINFS

此分区是用于保存NK.bin文件的,下面来看创建分区的调用代码

WINCE6.0+NAND FLASH分区的实现_第8张图片

图8

这里说明下BP_OpenPartition函数的第2个参数,原厂BSP是dwBINFSPartLength,也就是实际NK的大小,但存在这样的问题,假如我们的设备默认是烧录了大小为40M的NK.bin之后,我们后面的系统变大了,比如变为43M,那么在升级的时候需要重新创建分区,需要十几分钟的时间,为了解决此问题,我们在这里直接预留大一点,这里的ROM_RAMIMAGE_SIZE大小为59MB。接下来我们看BP_OpenPartition函数的实现,先说明下此函数参数的意义:

HANDLEBP_OpenPartition(

  DWORD dwStartSector,

  DWORD dwNumSectors,

  DWORD dwPartType,

  BOOL fActive,

  DWORD dwCreationFlags

);

dwStartSector表示此分区所在的页开始地址。

dwNumSectors表示此分区所占用的页数量

dwPartType分区类型

fActive 表示是否激活分区,设置为TRUE表示激活分区。

dwCreationFlags保存打开或是创建分区的信息,PART_CREATE_NEW创建一个分区,如果已经存在,则创建失败;PART_OPEN_EXISTING打开一个已经存在的分区,如果分区不存在,则打开失败;PART_OPEN_ALWAYS如果分区不存在,则创建一个分区,如果已经存在,则打开。

 

接下来看具体的实现。

WINCE6.0+NAND FLASH分区的实现_第9张图片

图9

这里重点是调用CreatePartition创建分区,并把分区信息写入到MBR所在的block中。

/*  CreatePartition 
 *
 *  Creates a new partition.  If it is a boot section partition, then it formats
 *  flash.
 *
 *  ENTRY
 *      dwStartSector - Logical sector to start the partition.  NEXT_FREE_LOC if  
 *          none specified.  
 *      dwNumSectors - Number of logical sectors of the partition.  USE_REMAINING_SPACE 
 *          to indicate to take up the rest of the space on the flash for that partition.
 *      dwPartType - Type of partition to create.
 *      fActive - TRUE indicates to create the active partition.  FALSE for
 *          inactive.
 *      dwPartIndex - Index of the partition entry on the MBR
 *
 *  EXIT
 *      Handle to the partition on success.  INVALID_HANDLE_VALUE on error.
 */

static HANDLE CreatePartition (DWORD dwStartSector, DWORD dwNumSectors, DWORD dwPartType, BOOL fActive, DWORD dwPartIndex)
{
    DWORD dwBootInd = 0;

    RETAILMSG(1, (TEXT("CreatePartition: Enter CreatePartition for 0x%x.\r\n"), dwPartType));
    
    if (fActive)
        dwBootInd |= PART_IND_ACTIVE;
    if (dwPartType == PART_BOOTSECTION || dwPartType == PART_BINFS || dwPartType == PART_XIP)
        dwBootInd |= PART_IND_READ_ONLY;    

     // If start sector is invalid, it means find next free sector
    if (dwStartSector == NEXT_FREE_LOC) {        
        
        dwStartSector = FindFreeSector();
        if (dwStartSector == INVALID_ADDR) {
            RETAILMSG(1, (TEXT("CreatePartition: can't find free sector.\r\n")));
            return INVALID_HANDLE_VALUE;
        }

        // Start partitions on the next block if they are currently on the wrong block type.
        if (dwStartSector % g_FlashInfo.wSectorsPerBlock) {            
            DWORD dwBlock = dwStartSector / g_FlashInfo.wSectorsPerBlock;
            if (IS_PART_READONLY(dwBootInd) != IS_BLOCK_READONLY(dwBlock)) {
                dwStartSector = (dwBlock+1) * g_FlashInfo.wSectorsPerBlock;
            }
        }
    }

    if (IS_PART_READONLY(dwBootInd)) {

        // Allow read-only partitions to go to the end of disk, if requested.
        if (dwNumSectors == USE_REMAINING_SPACE) {

            DWORD dwLastLogSector = LastLogSector();
            if (dwLastLogSector == INVALID_ADDR)
                return INVALID_HANDLE_VALUE;

            dwNumSectors = dwLastLogSector - dwStartSector + 1;
        }
    }
    else {

        DWORD dwLastLogSector = LastLogSector();
        if (dwLastLogSector == INVALID_ADDR)
            return INVALID_HANDLE_VALUE;

        // Determine the number of blocks to reserve for the FAL compaction when creating an extended partition.
        DWORD dwReservedBlocks = g_FlashInfo.dwNumBlocks / PERCENTAGE_OF_MEDIA_TO_RESERVE;
        if((dwReservedBlocks = g_FlashInfo.dwNumBlocks / PERCENTAGE_OF_MEDIA_TO_RESERVE) < MINIMUM_FLASH_BLOCKS_TO_RESERVE) {
            dwReservedBlocks = MINIMUM_FLASH_BLOCKS_TO_RESERVE;
        }
        
        DWORD dwNumMaxSectors = dwLastLogSector - dwStartSector + 1 - dwReservedBlocks * g_FlashInfo.wSectorsPerBlock;

        // If dwNumSectors was provided, validate it isn't past the max.
        // If dwNumSectors is USE_REMAINING_SPACE, fill disk with max sectors.
        if ((dwNumSectors == USE_REMAINING_SPACE)  || (dwNumMaxSectors <  dwNumSectors)) {
            RETAILMSG(1, (TEXT("CreatePartition: Num sectors set to 0x%x to allow for compaction blocks.\r\n"), dwNumMaxSectors));
            dwNumSectors = dwNumMaxSectors ;    
        }
    }

    
    if (!AreSectorsFree (dwStartSector, dwNumSectors)){
        RETAILMSG (1, (TEXT("CreatePartition: sectors [0x%x, 0x%x] requested are out of range or taken by another partition\r\n"), dwStartSector, dwNumSectors));
        return INVALID_HANDLE_VALUE;
    }

    RETAILMSG(1, (TEXT("CreatePartition: Start = 0x%x, Num = 0x%x.\r\n"), dwStartSector, dwNumSectors));
    
    AddPartitionTableEntry (dwPartIndex, dwStartSector, dwNumSectors, (BYTE)dwPartType, (BYTE)dwBootInd);

    if (IS_PART_READONLY(dwBootInd)) {
        if (!WriteLogicalNumbers (dwStartSector, dwNumSectors, TRUE)) {
            RETAILMSG(1, (TEXT("CreatePartition: can't mark sector info.\r\n")));
            return INVALID_HANDLE_VALUE;
        }
    }

    if (!WriteMBR())
        return INVALID_HANDLE_VALUE;

    g_partStateTable[dwPartIndex].pPartEntry = (PPARTENTRY)(g_pbMBRSector + PARTTABLE_OFFSET + sizeof(PARTENTRY)*dwPartIndex);
    g_partStateTable[dwPartIndex].dwDataPointer = 0;

    return (HANDLE)&g_partStateTable[dwPartIndex];            
}


 

(2)  另外两个PART_DOS3_FAT和PART_DOS32分区的创建类似

 

 

参考:

NandFlash的分区实现

http://blog.csdn.net/paul73022/article/details/6092897

 

 

WinCE EBOOT中的BootPart分析

http://blog.csdn.net/nanjianhui/article/details/3391583

 

 

WinCE上BINFS实现详解(快速启动Wince) 

http://blog.chinaunix.net/uid-8087110-id-1989057.html

 

 

你可能感兴趣的:(WINCE6.0+NAND FLASH分区的实现)