您的位置:首页 > 其它

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

2009-04-18 05:02 309 查看
CE5.0 - eboot创建MBR主分区进行LowLevelFormat低格的详细流程
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;

}
*/

发表于: 2009-03-27,修改于: 2009-03-28 09:01,已浏览68次,有评论0条 推荐 投诉

转自http://blog.chinaunix.net/u1/38994/showart_1882193.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐