Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15273276
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类:

2009-03-27 18:00:00

CE5.0 - eboot创建MBR主分区进行LowLevelFormat低格的详细流程

eboot
==>main PLATFORM\SMDK2440A\Src\Bootloader\Eboot_usb\main.c|96| BootloaderMain(); //应该是这个

==>BootloaderMain PLATFORM\SMDK2440A\Src\Bootloader\Eboot_usb\blcommon.c|106| if (!OEMPlatformInit ()) //应该是这个

==>OEMPlatformInit PLATFORM\SMDK2440A\Src\Bootloader\Eboot\main.c|722| if ( !BP_Init((LPBYTE)BINFS_RAM_START, BINFS_RAM_LENGTH, NULL, NULL, NULL) )
    =>g_dwImageStartBlock = IMAGE_START_BLOCK;
    =>BP_Init((LPBYTE)BINFS_RAM_START, BINFS_RAM_LENGTH, NULL, NULL, NULL)
        #define BINFS_RAM_START (0x8c021000 | CACHED_TO_UNCACHED_OFFSET) // uncached 在boot.bib中有定义[luther.gliethttp]:BINFS 8c021000 00005000 RESERVED

        g_pbMBRSector = pMemory; //size = g_FlashInfo.wDataBytesPerSector;

        g_pbBlock = pMemory + g_FlashInfo.wDataBytesPerSector; //size = g_dwDataBytesPerBlock;

        g_pSectorInfoBuf = (PSectorInfo)(g_pbBlock + g_dwDataBytesPerBlock); //size = g_FlashInfo.wSectorsPerBlock * sizeof(SectorInfo);

    =>FMD_Init
    =>g_pbMBRSector = pMemory;
==>TOC_Read
    =>FMD_ReadSector(TOC_SECTOR, (PUCHAR)g_pTOC, &si, 1);//从TOC_SECTOR处读取TOC,我定义的是32,即第2个block开始地址

    =>VALID_TOC(g_pTOC)如果TOC无效,那么直接return false;然后OEMPlatformInit将调用TOC_Init()初始化默认数值给TOC;[luther.gliethttp]
    否则
            // update our boot config

            g_pBootCfg = &g_pTOC->BootCfg;
            // update our index

            g_dwTocEntry = g_pBootCfg->ImageIndex;
            // debugger enabled?

            g_bWaitForConnect = (g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DEBUGGER) ? TRUE : FALSE;
            // cache image type

            g_ImageType = g_pTOC->id[g_dwTocEntry].dwImageType;
    =>每个block块第一个sector的info数据区存放了所在block的状态信息
            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;
==>TOC_Init(DEFAULT_IMAGE_DESCRIPTOR, (IMAGE_TYPE_RAMIMAGE), 0, 0, 0);
            // Default image descriptor to load.

            // We store Eboot as image 0, nk.nb0 as image 1

            #define DEFAULT_IMAGE_DESCRIPTOR 1
    =>memset(g_pTOC, 0, sizeof(g_TOC));
    =>BootConfigInit(dwEntry);
            static void BootConfigInit(DWORD dwIndex)
            {

                EdbgOutputDebugString("+BootConfigInit\r\n");

                g_pBootCfg = &g_pTOC->BootCfg;

                memset(g_pBootCfg, 0, sizeof(BOOT_CFG));

                g_pBootCfg->ImageIndex = dwIndex;

                g_pBootCfg->ConfigFlags = BOOT_TYPE_MULTISTAGE | CONFIG_FLAGS_DEBUGGER;

                g_pBootCfg->BootDelay = CONFIG_BOOTDELAY_DEFAULT;

                g_pBootCfg->SubnetMask = inet_addr("255.255.255.0");

                EdbgOutputDebugString("-BootConfigInit\r\n");
                return;
            }
==>dwStartTime = OEMEthGetSecs();//读取2440内部RTC时间

==>while((dwCurrTime - dwStartTime) < g_pBootCfg->BootDelay) //等待BootDelay时间到来,如果debug口有数据输入,那么将退出该while

==>MainMenu(g_pBootCfg);//通过debug口输入格式化命令'F',然后输入format BinFS命令'9'

        case 'F':
        case 'f':
            // low-level format

            // N.B: this erases images, BinFs, FATFS, user data, etc.

            // However, we don't format Bootloaders & TOC bolcks; use JTAG for this.

            if ( !g_bBootMediaExist ) {
                OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: boot media does not exist.\r\n")));
                continue;
            } else {
                DWORD i;
                SectorInfo si;

                // to keep bootpart off of our reserved blocks we must mark it as bad, reserved & read-only

                si.bOEMReserved = OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY;
                si.bBadBlock = BADBLOCKMARK;
                si.dwReserved1 = 0xffffffff;
                si.wReserved2 = 0xffff;

                OALMSG(TRUE, (TEXT("Reserving Blocks [0x%x - 0x%x] ...\r\n"), 0, IMAGE_START_BLOCK-1));
                for (i = 0; i < IMAGE_START_SECTOR; i++) {//0块--NBOOT;1块--TOC;2块~17块--EBOOT.nb0;IMAGE_START_SECTOR等于18块[luther.gliethttp]

                    FMD_WriteSector(i, NULL, &si, 1);//写0~17块的info区,这样来保留0~17块.

                }
                OALMSG(TRUE, (TEXT("...reserve complete.\r\n")));

                OALMSG(TRUE, (TEXT("Low-level format Blocks [0x%x - 0x%x] ...\r\n"), IMAGE_START_BLOCK, NAND_BLOCK_CNT-1));
                for (i = IMAGE_START_BLOCK; i < NAND_BLOCK_CNT; i++) { //我的一共有64M,即:4K/32/512

                    FMD_EraseBlock(i);//发出erase指令之后,该块是否已经损坏的info信息会被NAND控制器自动存放到了每块的第1个扇区的info空间,未损坏将全部为0xff[luther.gliethttp]

                }
                OALMSG(TRUE, (TEXT("...erase complete.\r\n")));
            } break;
        case '9':
            // format the boot media for BinFS

            // N.B: this does not destroy our OEM reserved sections (TOC, bootloaders, etc)

            if ( !g_bBootMediaExist ) {
                OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: boot media does not exist.\r\n")));
                continue;
            }
            // N.B: format offset by # of reserved blocks,

            // decrease the ttl # blocks available by that amount.

            //低格除0块--NBOOT;1块--TOC;2块~17块--EBOOT.nb0;IMAGE_START_SECTOR等于18块

            //从18块开始格

            if ( !BP_LowLevelFormat( g_dwImageStartBlock,
                                     NAND_BLOCK_CNT - g_dwImageStartBlock,
                                     0) )
            {
                OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: Low-level boot media format failed.\r\n")));
                continue;
            }
            break;
/*
BOOL BP_LowLevelFormat(DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)
{
    dwNumBlocks = min (dwNumBlocks, g_FlashInfo.dwNumBlocks);

    RETAILMSG(1,(TEXT("Enter LowLevelFormat [0x%x, 0x%x].\r\n"), dwStartBlock, dwStartBlock + dwNumBlocks - 1));

    // Erase all the flash blocks.
    if (!EraseBlocks(dwStartBlock, dwNumBlocks, dwFlags))
        return(FALSE);

    // Determine first good starting block
    //如果dwStartBlock是坏块,那么一直往下找,知道找到第一个好块为止[luther.gliethttp]
    while (IS_BLOCK_UNUSABLE (dwStartBlock) && dwStartBlock < g_FlashInfo.dwNumBlocks) {
        dwStartBlock++;
    }

    if (dwStartBlock >= g_FlashInfo.dwNumBlocks) {
    //说明最变态的情况发生了,竟然全坏了,shit了[luthre.gliethttp]
        RETAILMSG(1,(TEXT("BP_LowLevelFormat: no good blocks\r\n")));
        return FALSE;
    }

    // MBR goes in the first sector of the starting block. This will be logical sector 0.
    // 那么MBR的逻辑扇区就从这个块开始[luther.gliethttp]
    g_dwMBRSectorNum = dwStartBlock * g_FlashInfo.wSectorsPerBlock;

    // Create an MBR.
    CreateMBR();

    RETAILMSG (1, (TEXT("Done.\r\n\r\n")));
    return(TRUE);
}


BOOL EraseBlocks(DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)
{
    DWORD dwSector;
    USHORT nCount;
    LPBYTE WriteSect = g_pbBlock + g_FlashInfo.wDataBytesPerSector;//其地址在在boot.bib中有定义BINFS 8c021000 00005000 RESERVED,分析见上面[luther.gliethttp]
    LPBYTE ReadSect = g_pbBlock + 2 * g_FlashInfo.wDataBytesPerSector;
    SectorInfo WriteSectInfo, ReadSectInfo;

    if (dwStartBlock >= g_FlashInfo.dwNumBlocks || (dwStartBlock + dwNumBlocks - 1) >= g_FlashInfo.dwNumBlocks)
    {
        RETAILMSG (1, (TEXT("EraseBlocks: block number outside valid range [0x%x, 0x%x].\r\n"), dwStartBlock, (dwStartBlock + dwNumBlocks - 1)));
        return(FALSE);
    }

    RETAILMSG (1, (TEXT("Erasing flash block(s) [0x%x, 0x%x] (please wait): "), dwStartBlock, (dwStartBlock + dwNumBlocks - 1)));
    while (dwNumBlocks--)
    {
        DWORD dwStatus = FMD_GetBlockStatus (dwStartBlock);//获取block所在第1扇区的info信息[luther.gliethttp]
        BOOL fBadBlock = FALSE;

        // If the block has already been marked bad, skip it and increase the total number of blocks to be erased by a block. Note that bad
        // blocks do count against the total number of blocks to be erased since the caller has max constraints on the erase region size.
        if (dwStatus & BLOCK_STATUS_BAD)
        {
            RETAILMSG (1, (TEXT("EraseBlocks: found a bad block (0x%x) - skipping...\r\n"), dwStartBlock));
            ++dwStartBlock;//坏块,继续
            continue;
        }

        if ((dwStatus & BLOCK_STATUS_RESERVED) && (dwFlags & FORMAT_SKIP_RESERVED))
        {
            RETAILMSG (1, (TEXT("EraseBlocks: preserving reserved block (0x%x) \r\n"), dwStartBlock));
            ++dwStartBlock;//保留块,继续
            continue;
        }

        if (!FMD_EraseBlock(dwStartBlock))
        {
            RETAILMSG (1, (TEXT("EraseBlocks: unable to erase block (0x%x). Marking bad..\r\n"), dwStartBlock));
            FMD_SetBlockStatus(dwStartBlock, BLOCK_STATUS_BAD);
            ++dwStartBlock;//擦除出现异常,继续
            continue;
        }

        // Optionally skip the bad block check - this speeds up the erase process, especially on NOR flash.
        if (dwFlags & FORMAT_SKIP_BLOCK_CHECK)
        {
            ++dwStartBlock;//不需要进行块检查,比如nor flash
            continue;
        }

        // Because the bits denoting a bad block can be erased, we take the cautious approach - we'll write an read-verify each sector in this
        // block to make sure the block is good. If it's good, we'll re-erase else we'll mark the block bad.
        //使用1.写入 2.读出 3.比较 的方式对该block下的所有扇区进行全方位检测块[luther.gliethttp]
        dwSector = (dwStartBlock * g_FlashInfo.wSectorsPerBlock);
        for (nCount = 0 ; nCount < g_FlashInfo.wSectorsPerBlock ; nCount++)
        {
            // Make sure erase set all bits high.
            //位于BinFS空间的写缓冲区全置1
            memset(WriteSect, 0xFF, g_FlashInfo.wDataBytesPerSector);
            memset(&WriteSectInfo, 0xFF, sizeof(SectorInfo));
            //读该扇区
            FMD_ReadSector((dwSector + nCount), ReadSect, &ReadSectInfo, 1);
            
            if (memcmp(ReadSect, WriteSect, g_FlashInfo.wDataBytesPerSector) ||
                 memcmp(&ReadSectInfo, &WriteSectInfo, sizeof(SectorInfo)))//如果不全1,那么说明该block为坏块,break出去[luther.gliethttp]
            {
                RETAILMSG (1, (TEXT("EraseBlocks: erase didn't set all bits high (marking block 0x%x bad).\r\n"), dwStartBlock));
                FMD_SetBlockStatus(dwStartBlock, BLOCK_STATUS_BAD);
                fBadBlock = TRUE;
                break;
            }

            // Now, make sure we can store zero - this is meant to check for bad blocks (in the event that the bad block marker was erased).
            // Note that we *don't* write sector info data here - this is where bad block data is stored.
            memset(WriteSect, 0, g_FlashInfo.wDataBytesPerSector);//全置0
            if (!FMD_WriteSector((dwSector + nCount), WriteSect, NULL, 1))//在数据区写全0
            {
                RETAILMSG (1, (TEXT("EraseBlocks: write test low data failed (marking block 0x%x bad).\r\n"), dwStartBlock));
                FMD_SetBlockStatus(dwStartBlock, BLOCK_STATUS_BAD);
                fBadBlock = TRUE;
                break;
            }
            // Read back the value and make sure it stored correctly.
            if (!FMD_ReadSector((dwSector + nCount), ReadSect, NULL, 1) ||
                memcmp(ReadSect, WriteSect, g_FlashInfo.wDataBytesPerSector))
            {
                RETAILMSG (1, (TEXT("EraseBlocks: erase didn't set all bits low (marking block 0x%x bad).\r\n"), dwStartBlock));
                FMD_SetBlockStatus(dwStartBlock, BLOCK_STATUS_BAD);
                fBadBlock = TRUE;//如果写全0存在问题,那么说明该block对写全0存在问题,所以标记该block为坏块[luther.gliethttp]
                break;
            }
        }

        // If the block has already been marked bad, skip it and increase the total number of blocks to be erased by a block. Note that bad
        // blocks do count against the total number of blocks to be erased since the caller has max constraints on the erase region size.
        if (fBadBlock)
        {
            RETAILMSG (1, (TEXT("\r\nEraseBlocks: found a bad block (0x%x) - skipping...\r\n"), dwStartBlock));
            ++dwStartBlock;
            continue;
        }

        if (!FMD_EraseBlock(dwStartBlock))
        {
            RETAILMSG (1, (TEXT("EraseBlocks: unable to erase block (0x%x). Marking bad..\r\n"), dwStartBlock));
            FMD_SetBlockStatus(dwStartBlock, BLOCK_STATUS_BAD);
        }

        ++dwStartBlock;//进入下一个block块的检测工作[luthre.gliethtp]
    }
    RETAILMSG (1, (TEXT("Done.\r\n")));
    return(TRUE);
}

static BOOL CreateMBR()
{
    // This, plus a valid partition table, is all the CE partition manager needs to recognize
    // the MBR as valid. It does not contain boot code.
    //g_pbMBRSector地址定义见上面
    //g_pbMBRSector = pMemory = BINFS_RAM_START;位于boot.bib
    memset (g_pbMBRSector, 0xff, g_FlashInfo.wDataBytesPerSector);//置全0xff
    g_pbMBRSector[0] = 0xE9;
    g_pbMBRSector[1] = 0xfd;
    g_pbMBRSector[2] = 0xff;
    g_pbMBRSector[SECTOR_SIZE-2] = 0x55;
    g_pbMBRSector[SECTOR_SIZE-1] = 0xAA;

    // Zero out partition table so that mspart treats entries as empty.
    // 全置0分区表,这样mspart才知道分区表空[lutehr.gliethttp]
    memset (g_pbMBRSector+PARTTABLE_OFFSET, 0, sizeof(PARTENTRY) * NUM_PARTS);

    return WriteMBR();//回写MBR到nand存储器

}

static BOOL WriteMBR()
{
    DWORD dwMBRBlockNum = g_dwMBRSectorNum / g_FlashInfo.wSectorsPerBlock; //g_dwMBRSectorNum为第一个18块开始之后的第一个好块,对该原因的分析见上面[luther.gliethttp]

    RETAILMSG(1, (TEXT("WriteMBR: MBR block = 0x%x.\r\n"), dwMBRBlockNum));
    //置全0xff
    memset (g_pbBlock, 0xff, g_dwDataBytesPerBlock);
    memset (g_pSectorInfoBuf, 0xff, sizeof(SectorInfo) * g_FlashInfo.wSectorsPerBlock);
        
    // No need to check return, since a failed read means data hasn't been written yet.
    // 读到BinFS空间[luther.gliethttp]
    ReadBlock (dwMBRBlockNum, g_pbBlock, g_pSectorInfoBuf);

    if (!FMD_EraseBlock (dwMBRBlockNum)) {//尝试擦,以备后患
        RETAILMSG (1, (TEXT("CreatePartition: error erasing block 0x%x\r\n"), dwMBRBlockNum));
        return FALSE;
    }
    //拷贝g_pbMBRSector中数据,一般g_dwMBRSectorNum % g_FlashInfo.wSectorsPerBlock值为0
    memcpy (g_pbBlock + (g_dwMBRSectorNum % g_FlashInfo.wSectorsPerBlock) * g_FlashInfo.wDataBytesPerSector, g_pbMBRSector, g_FlashInfo.wDataBytesPerSector);
    g_pSectorInfoBuf->bOEMReserved &= ~OEM_BLOCK_READONLY;
    g_pSectorInfoBuf->wReserved2 &= ~SECTOR_WRITE_COMPLETED;
    g_pSectorInfoBuf->dwReserved1 = 0;
    //好了将MBR回写到那个block块,这样我们创建MBR的操作也就到此高一段落了[luther.gliethttp]
    if (!WriteBlock (dwMBRBlockNum, g_pbBlock, g_pSectorInfoBuf)) {
        RETAILMSG (1, (TEXT("CreatePartition: could not write to block 0x%x\r\n"), dwMBRBlockNum));
        return FALSE;
    }

    return TRUE;
    
}
*/

阅读(4386) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-05-20 17:39:30

好文!!! 谢谢博主