从eboot菜单分析eboot功能实现原理

时间:2021-05-01 18:04:40

作者:wogoyixikexie@gliet 2008-12-10

============================================================

        一直在用优龙的ADS bootloader,对eboot的认识还停留在在刚来公司时候的水平,貌似我只看过eboot的startup.s,现在

使用优龙的bootloader遇到很多障碍,最大缺陷就是不支持binfs以及FAT分区,这个导致了不能实现multibin,FAT的问题还可以配置注册表实现自动化分区功能,但是这样还是不理想,但是优龙的bootloader太好用了,不想放弃这块肥肉,所以决定参考eboot增加优龙bootloader的binfs以及FAT分区功能。我的一贯做法是查找关键字眼,然后从关键点入手看程序。现在就看实现eboot功能的菜单程序吧。

============================================================

平台描述:2440+64M flash/SDRAM + 5.0BSP

  1. 0) IP address: 192.168.0.12
  2. 1) Subnet mask: 255.255.255.0
  3. 2) DHCP: Disabled
  4. 3) Boot delay: 5 seconds
  5. 4) Reset to factory default configuration
  6. 5) Startup image: DOWNLOAD NEW
  7. 6) Program disk image into SmartMedia card: Disabled
  8. 7) Program CS8900 MAC address (11:12:22:33:44:55)
  9. 8) Kernel Debugger: DISABLED
  10. 9) Format Boot Media for BinFS//------------
  11. E) Erase Reserved Block 
  12. B) Mark Bad Block at Reserved Block 
  13. F) Low-level format the Smart Media card//---------------
  14. D) Download image now
  15. L) LAUNCH existing Boot Media image
  16. R) Read Configuration 
  17. U) DOWNLOAD image now(USB)
  18. W) Write Configuration Right Now
  19. A) Erase All Blocks
  20. Enter your selection: 
  1. /*
  2.     @func   BOOL | MainMenu | Manages the Samsung bootloader main menu.
  3.     @rdesc  TRUE == Success and FALSE == Failure.
  4.     @comm    
  5.     @xref   
  6. */
  7. static BOOL MainMenu(PBOOT_CFG pBootCfg)
  8. {
  9.     BYTE KeySelect = 0;
  10.     BOOL bConfigChanged = FALSE;
  11.     BOOLEAN bDownload = TRUE;
  12.     DWORD i;
  13.     while(TRUE)
  14.     {
  15.         KeySelect = 0;
  16.         EdbgOutputDebugString ( "/r/nEthernet Boot Loader Configuration:/r/n/r/n");
  17.         EdbgOutputDebugString ( "0) IP address: %s/r/n",inet_ntoa(pBootCfg->EdbgAddr.dwIP));
  18.         EdbgOutputDebugString ( "1) Subnet mask: %s/r/n", inet_ntoa(pBootCfg->SubnetMask));
  19.         EdbgOutputDebugString ( "2) DHCP: %s/r/n", (pBootCfg->ConfigFlags & CONFIG_FLAGS_DHCP)?"Enabled":"Disabled");
  20.         EdbgOutputDebugString ( "3) Boot delay: %d seconds/r/n", pBootCfg->BootDelay);
  21.         EdbgOutputDebugString ( "4) Reset to factory default configuration/r/n");
  22.         EdbgOutputDebugString ( "5) Startup image: %s/r/n", (g_pBootCfg->ConfigFlags & BOOT_TYPE_DIRECT) ? "LAUNCH EXISTING" : "DOWNLOAD NEW");
  23.         EdbgOutputDebugString ( "6) Program disk image into SmartMedia card: %s/r/n", (pBootCfg->ConfigFlags & TARGET_TYPE_NAND)?"Enabled":"Disabled");
  24.         EdbgOutputDebugString ( "7) Program CS8900 MAC address (%B:%B:%B:%B:%B:%B)/r/n",
  25.                                g_pBootCfg->EdbgAddr.wMAC[0] & 0x00FF, g_pBootCfg->EdbgAddr.wMAC[0] >> 8,
  26.                                g_pBootCfg->EdbgAddr.wMAC[1] & 0x00FF, g_pBootCfg->EdbgAddr.wMAC[1] >> 8,
  27.                                g_pBootCfg->EdbgAddr.wMAC[2] & 0x00FF, g_pBootCfg->EdbgAddr.wMAC[2] >> 8);
  28.         EdbgOutputDebugString ( "8) Kernel Debugger: %s/r/n", (g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DEBUGGER) ? "ENABLED" : "DISABLED");
  29.         EdbgOutputDebugString ( "9) Format Boot Media for BinFS/r/n");
  30.         // N.B: we need this option here since BinFS is really a RAM image, where you "format" the media
  31.         // with an MBR. There is no way to parse the image to say it's ment to be BinFS enabled.
  32.         EdbgOutputDebugString ( "E) Erase Reserved Block /r/n");
  33.         EdbgOutputDebugString ( "B) Mark Bad Block at Reserved Block /r/n");
  34.         EdbgOutputDebugString ( "F) Low-level format the Smart Media card/r/n");
  35.         EdbgOutputDebugString ( "D) Download image now/r/n");
  36.         EdbgOutputDebugString ( "L) LAUNCH existing Boot Media image/r/n");
  37.         EdbgOutputDebugString ( "R) Read Configuration /r/n");
  38.         EdbgOutputDebugString ( "U) DOWNLOAD image now(USB)/r/n");
  39.         EdbgOutputDebugString ( "W) Write Configuration Right Now/r/n");
  40.         EdbgOutputDebugString ( "A) Erase All Blocks/r/n");
  41.         EdbgOutputDebugString ( "/r/nEnter your selection: ");
  42.         while (! ( ( (KeySelect >= '0') && (KeySelect <= '9') ) ||
  43.                    ( (KeySelect == 'A') || (KeySelect == 'a') ) ||
  44.                    ( (KeySelect == 'D') || (KeySelect == 'd') ) ||
  45.                    ( (KeySelect == 'B') || (KeySelect == 'b') ) ||
  46.                    ( (KeySelect == 'E') || (KeySelect == 'e') ) ||
  47.                    ( (KeySelect == 'F') || (KeySelect == 'f') ) ||
  48.                    ( (KeySelect == 'L') || (KeySelect == 'l') ) ||
  49.                    ( (KeySelect == 'R') || (KeySelect == 'r') ) ||
  50.                    ( (KeySelect == 'U') || (KeySelect == 'u') ) ||
  51.                    ( (KeySelect == 'W') || (KeySelect == 'w') ) ||
  52.                    ( (KeySelect == 'X') || (KeySelect == 'x') ) ))
  53.         {
  54.             KeySelect = OEMReadDebugByte();
  55.         }
  56.         EdbgOutputDebugString ( "%c/r/n", KeySelect);
  57.         switch(KeySelect)
  58.         {
  59.         case '0':           // Change IP address.
  60.             SetIP(pBootCfg);
  61.             pBootCfg->ConfigFlags &= ~CONFIG_FLAGS_DHCP;   // clear DHCP flag
  62.             bConfigChanged = TRUE;
  63.             break;
  64.         case '1':           // Change subnet mask.
  65.             SetMask(pBootCfg);
  66.             bConfigChanged = TRUE;
  67.             break;
  68.         case '2':           // Toggle static/DHCP mode.
  69.             pBootCfg->ConfigFlags = (pBootCfg->ConfigFlags ^ CONFIG_FLAGS_DHCP);
  70.             bConfigChanged = TRUE;
  71.             break;
  72.         case '3':           // Change autoboot delay.
  73.             SetDelay(pBootCfg);
  74.             bConfigChanged = TRUE;
  75.             break;
  76.         case '4':           // Reset the bootloader configuration to defaults.
  77.             OALMSG(TRUE, (TEXT("Resetting default TOC.../r/n")));
  78.             TOC_Init(DEFAULT_IMAGE_DESCRIPTOR, (IMAGE_TYPE_RAMIMAGE|IMAGE_TYPE_BINFS), 0, 0, 0);
  79.             if ( !TOC_Write() ) {
  80.                 OALMSG(OAL_WARN, (TEXT("TOC_Write Failed!/r/n")));
  81.             }
  82.             OALMSG(TRUE, (TEXT("...TOC complete/r/n")));
  83.             break;
  84.         case '5':           // Toggle download/launch status.
  85.             pBootCfg->ConfigFlags = (pBootCfg->ConfigFlags ^ BOOT_TYPE_DIRECT);
  86.             bConfigChanged = TRUE;
  87.             break;
  88.         case '6':           // Toggle image storage to Smart Media.
  89.             pBootCfg->ConfigFlags = (pBootCfg->ConfigFlags ^ TARGET_TYPE_NAND);
  90.             bConfigChanged = TRUE;
  91.             break;
  92.         case '7':           // Configure Crystal CS8900 MAC address.
  93.             SetCS8900MACAddress(pBootCfg);
  94.             bConfigChanged = TRUE;
  95.             break;
  96.         case '8':           // Toggle KD
  97.             g_pBootCfg->ConfigFlags = (g_pBootCfg->ConfigFlags ^ CONFIG_FLAGS_DEBUGGER);
  98.             g_bWaitForConnect = (g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DEBUGGER) ? TRUE : FALSE;
  99.             bConfigChanged = TRUE;
  100.             continue;
  101.             break;            
  102.         case '9':
  103.             // format the boot media for BinFS
  104.             // N.B: this does not destroy our OEM reserved sections (TOC, bootloaders, etc)
  105.             if ( !g_bBootMediaExist ) {
  106.                 OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: boot media does not exist./r/n")));
  107.                 continue;
  108.             }
  109.             // N.B: format offset by # of reserved blocks,
  110.             // decrease the ttl # blocks available by that amount.
  111.             if ( !BP_LowLevelFormat( g_dwImageStartBlock,
  112.                                      wNUM_BLOCKS - g_dwImageStartBlock,
  113.                                      0) )
  114.             {
  115.                 OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: Low-level boot media format failed./r/n")));
  116.                 continue;
  117.             }
  118.             break;
  119.         case 'F':
  120.         case 'f':
  121.             // low-level format
  122.             // N.B: this erases images, BinFs, FATFS, user data, etc.
  123.             // However, we don't format Bootloaders & TOC bolcks; use JTAG for this.
  124.             if ( !g_bBootMediaExist ) {
  125.                 OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: boot media does not exist./r/n")));
  126.                 continue;
  127.             } else {
  128.                 SectorInfo si;
  129.                 // to keep bootpart off of our reserved blocks we must mark it as bad, reserved & read-only
  130.                 si.bOEMReserved = OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY;
  131.                 si.bBadBlock    = BADBLOCKMARK;
  132.                 si.dwReserved1  = 0xffffffff;
  133.                 si.wReserved2   = 0xffff;
  134.                 OALMSG(TRUE, (TEXT("Reserving Blocks [0x%x - 0x%x] .../r/n"), 0, IMAGE_START_BLOCK-1));
  135.                 for (i = 0; i < IMAGE_START_SECTOR; i++) {
  136.                     FMD_WriteSector(i, NULL, &si, 1);
  137.                 }
  138.                 OALMSG(TRUE, (TEXT("...reserve complete./r/n")));
  139.                 OALMSG(TRUE, (TEXT("Low-level format Blocks [0x%x - 0x%x] .../r/n"), IMAGE_START_BLOCK, wNUM_BLOCKS-1));
  140.                 for (i = IMAGE_START_BLOCK; i < wNUM_BLOCKS; i++) {
  141.                     FMD_EraseBlock(i);
  142.                 }
  143.                 OALMSG(TRUE, (TEXT("...erase complete./r/n")));
  144.             } break;
  145.         case 'A':
  146.         case 'a':
  147.                 OALMSG(TRUE, (TEXT("All block Erase.../r/n")));
  148.                 for (i = 0; i < wNUM_BLOCKS; i++) {
  149.                     FMD_EraseBlock(i);
  150.                 }
  151.             break;
  152.         case 'B':
  153.         case 'b':
  154.             // low-level format
  155.             // N.B: this erases images, BinFs, FATFS, user data, etc.
  156.             // However, we don't format Bootloaders & TOC bolcks; use JTAG for this.
  157.             if ( !g_bBootMediaExist ) {
  158.                 OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: boot media does not exist./r/n")));
  159.                 continue;
  160.             } else {
  161.                 DWORD i;
  162.                 SectorInfo si;
  163.                 // to keep bootpart off of our reserved blocks we must mark it as bad, reserved & read-only
  164.                 si.bOEMReserved = OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY;
  165.                 si.bBadBlock    = BADBLOCKMARK;
  166. //              si.bBadBlock    = 0xff;
  167.                 si.dwReserved1  = 0xffffffff;
  168.                 si.wReserved2   = 0xffff;
  169.                 OALMSG(TRUE, (TEXT("Reserving Blocks [0x%x - 0x%x] .../r/n"), 0, IMAGE_START_BLOCK-1));
  170.                 for (i = 0; i < IMAGE_START_SECTOR; i++) {
  171.                     FMD_WriteSector(i, NULL, &si, 1);
  172.                 }
  173.                 OALMSG(TRUE, (TEXT("...reserve complete./r/n")));
  174.             } break;
  175.         case 'E':
  176.         case 'e':
  177.             // low-level format
  178.             // N.B: this erases images, BinFs, FATFS, user data, etc.
  179.             // However, we don't format Bootloaders & TOC bolcks; use JTAG for this.
  180.             if ( !g_bBootMediaExist ) {
  181.                 OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: boot media does not exist./r/n")));
  182.                 continue;
  183.             } else {
  184.                 int i;
  185.                 OALMSG(TRUE, (TEXT("Low-level format Blocks [0x%x - 0x%x] .../r/n"), 0, IMAGE_START_BLOCK-1));
  186.                 for (i = NBOOT_BLOCK; i < (NBOOT_BLOCK+NBOOT_BLOCK_SIZE); i++) {
  187.                     FMD_EraseBlock(i);
  188.                 }
  189.                 for (i = EBOOT_BLOCK; i < (EBOOT_BLOCK+EBOOT_BLOCK_SIZE); i++) {
  190.                     FMD_EraseBlock(i);
  191.                 }
  192.                 OALMSG(TRUE, (TEXT("...erase complete./r/n")));
  193.             } break;
  194.         case 'D':           // Download? Yes.
  195.         case 'd':
  196.             bDownload = TRUE;
  197.             goto MENU_DONE;
  198.         case 'L':           // Download? No.
  199.         case 'l':
  200.             bDownload = FALSE;
  201.             goto MENU_DONE;
  202.         case 'R':
  203.         case 'r':
  204.             TOC_Read();
  205.             TOC_Print();
  206.             // TODO
  207.             break;
  208.         case 'U':           // Download? No.
  209.         case 'u':
  210.             bConfigChanged = TRUE;
  211.             g_bUSBDownload = TRUE;
  212.             bDownload = TRUE;
  213.             goto MENU_DONE;
  214.         case 'W':           // Configuration Write
  215.         case 'w':
  216.             if (!TOC_Write())
  217.             {
  218.                 OALMSG(OAL_WARN, (TEXT("WARNING: MainMenu: Failed to store updated eboot configuration in flash./r/n")));
  219.             }
  220.             else
  221.             {
  222.                 OALMSG(OAL_INFO, (TEXT("Successfully Written/r/n")));
  223.                 bConfigChanged = FALSE;
  224.             }
  225.             break;
  226.         default:
  227.             break;
  228.         }
  229.     }
  230. MENU_DONE:
  231.     // If eboot settings were changed by user, save them to flash.
  232.     //
  233.     if (bConfigChanged && !TOC_Write())
  234.     {
  235.         OALMSG(OAL_WARN, (TEXT("WARNING: MainMenu: Failed to store updated bootloader configuration to flash./r/n")));
  236.     }
  237.     return(bDownload);    
  238. }

我现在要关注的是9和f选项

F) Low-level format the Smart Media card

从上面的代码可以看到,这个是给那些nboot和TOC以及eboot所占用的flash  block做个标记

 

  1. //
  2. //在eboot中的loader.h中有如下定义
  3. //
  4. #define RESERVED_BOOT_BLOCKS        (NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE + EBOOT_BLOCK_SIZE)
  5. // Images start after OEM Reserved Blocks
  6. #define IMAGE_START_BLOCK           RESERVED_BOOT_BLOCKS
  7. #define IMAGE_START_SECTOR          BLOCK_TO_SECTOR(IMAGE_START_BLOCK)
  8. //
  9. // OEM Reserved (Nand) Blocks for TOC and various bootloaders
  10. //
  11. // NAND Boot (loads into SteppingStone) @ Block 0
  12. #define NBOOT_BLOCK                 0
  13. #define NBOOT_BLOCK_SIZE            1
  14. #define NBOOT_SECTOR                BLOCK_TO_SECTOR(NBOOT_BLOCK)
  15. // TOC @ Block 1
  16. #define TOC_BLOCK                   1
  17. #define TOC_BLOCK_SIZE              1
  18. #define TOC_SECTOR                  BLOCK_TO_SECTOR(TOC_BLOCK)
  19. // Eboot @ Block 2
  20. #define EBOOT_BLOCK                 2
  21. #define EBOOT_SECTOR_SIZE           FILE_TO_SECTOR_SIZE(EBOOT_RAM_IMAGE_SIZE)
  22. #define EBOOT_BLOCK_SIZE            SECTOR_TO_BLOCK(EBOOT_SECTOR_SIZE)
  23. #define EBOOT_SECTOR                BLOCK_TO_SECTOR(EBOOT_BLOCK)
  24. #define RESERVED_BOOT_BLOCKS        (NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE + EBOOT_BLOCK_SIZE)
  25. // Images start after OEM Reserved Blocks
  26. #define IMAGE_START_BLOCK           RESERVED_BOOT_BLOCKS
  27. #define IMAGE_START_SECTOR          BLOCK_TO_SECTOR(IMAGE_START_BLOCK)

对于64M nand flash 扇区(page)和block关系转换如下。

//#ifndef SECTOR_TO_BLOCK
#define SECTOR_TO_BLOCK(sector)     ((sector) >> 8 )
//#endif
//#ifndef BLOCK_TO_SECTOR
#define BLOCK_TO_SECTOR(block)      ((block)  << 8 )
//#endif

================================================

 

#define EBOOT_RAM_IMAGE_SIZE        0x00040000               //256K

 

#define EBOOT_SECTOR_SIZE           FILE_TO_SECTOR_SIZE(EBOOT_RAM_IMAGE_SIZE)

#define EBOOT_BLOCK_SIZE            SECTOR_TO_BLOCK(EBOOT_SECTOR_SIZE)//求出block数目,eboot.nb0占据2个block

// fs: file size in bytes
// returns sector aligned value 求出EBOOT_RAM_IMAGE_SIZE 占用的flash页数
__inline DWORD FILE_TO_SECTOR_SIZE(DWORD fs) {
    return ( (fs / SECTOR_SIZE) + ( (fs % SECTOR_SIZE) ? 1 : 0) );//#define SECTOR_SIZE    512
}

 

从上面可以看出IMAGE_START_SECTOR=(NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE + EBOOT_BLOCK_SIZE)

=1+1+2=4(block)

===================================================

根据上面的准备,我现在把这个F菜单程序摘抄下来详细分析

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));

                //

                //给非FAT区域写入标志 
                for (i = 0; i < IMAGE_START_SECTOR; i++) {
                    FMD_WriteSector(i, NULL, &si, 1);
                }
                OALMSG(TRUE, (TEXT("...reserve complete./r/n")));

                OALMSG(TRUE, (TEXT("Low-level format Blocks [0x%x - 0x%x] .../r/n"), IMAGE_START_BLOCK, wNUM_BLOCKS-1));
                for (i = IMAGE_START_BLOCK; i < wNUM_BLOCKS; i++) {
                    FMD_EraseBlock(i);
                }
                OALMSG(TRUE, (TEXT("...erase complete./r/n")));

我看了eboot的sources文件,发现 FMD_WriteSector函数居然是来自$(_TARGETPLATROOT)/Src/Common/Smartmedia/Fmd

也就是说这个FMD驱动是Src/Common/Smartmedia/Fmd的代码(充分利用了代码)

——FMD_WriteSector(i, NULL, &si, 1)这个函数到底做了什么呢?现在就要详细看看这个函数的各个参数的作用

3. BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors): 这个函数用于写nandflash的一个扇区。对于nandflash来说,分大page和小page,大page是2048个bytes一页,小page是512个bytes一页。所以大page每个扇区有2048 bytes,小page每个扇区有512 bytes。

    startSectorAddr: nandflash物理扇区的起始地址,对于nandflash来说,就是nandflash中从哪个page开始。

    pSectorBuff:扇区数据buffer,从nandflash中写入的每一个扇区的数据都存放在这个buffer中。

    pSectorInfoBuff:扇区信息buffer,一般每个扇区的信息会被保存在nandflash的带外数据中,针对小page,带外数据有16 bytes,大page有64 bytes。从nandflash的带外数据将该扇区的相关信息读出来,存放在这个buffer中。

    dwNumSectors:读取多少个扇区,对于nandflash来说相当于读取多少个page。

——再来摘抄一下慕水大哥的文章

对NANDFLASH的结构认识,其中忽略了非常重要的一块,就是NAND用来保存其它信息的一块区域,这些信息包括块好坏的标记,块的逻辑地址,还有页内数据的ECC校验和等。。。。

这部分数据通过结构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;

在读写NAND时通过

BOOL  FMD_ReadSector (SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors);
BOOL  FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors);

pSectorInfoBuff参数读取相应sector状态,如果pSectorInfoBuff参数为NULL则读写sector数据。pSectorBuff为非NULL则读写sector状态。

——从以上两点对FMD_WriteSector分析可以知道FMD_WriteSector(i, NULL, &si, 1)是把flash的状态写入数据带外区。但是还是不能完满解释怎么样把flash的一些block标记为坏块或者只读,保留的呢,我推测是微软自己定义了一些数据。现在来看看。

程序好长,在fmd.cpp里面,关键是NAND_LB_WriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)这个函数,在这里就不贴出来了。

=============================现在看看他是怎么格式化的。MBR到底在哪里写了呢?

OALMSG(TRUE, (TEXT("Low-level format Blocks [0x%x - 0x%x] .../r/n"), IMAGE_START_BLOCK, wNUM_BLOCKS-1));
                for (i = IMAGE_START_BLOCK; i < wNUM_BLOCKS; i++) {
                    FMD_EraseBlock(i);
                }
                OALMSG(TRUE, (TEXT("...erase complete./r/n")));

从上面的代码看,他只是察除而已?看看FMD_EraseBlock这个函数——这个是FMD部分的,复用的不错,这里所谓的高低格式化就是标记保留区以及察除FAT部分。那MBR跑哪里去了呢?看另外一个菜单吧。

 

====================9) Format Boot Media for BinFS菜单实现分析=====================

case '9':
            // format the boot media for BinFS
            // N.B: this does not destroy our OEM reserved sections (TOC, bootloaders, etc)
            if ( !g_bBootMediaExist ) //检查flash是否初始化成功

            {
                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.

            //这个是微软的库函数,我觉得这个是支持binfs的难点和关键点
            if ( !BP_LowLevelFormat( g_dwImageStartBlock,
                                     wNUM_BLOCKS - g_dwImageStartBlock,
                                     0) )
            {
                OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: Low-level boot media format failed./r/n")));
                continue;
            }
            break;

C:/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BOOTPART/bootpart.cpp(1135)BP_LowLevelFormat

  1. /*  BP_LowLevelFormat 
  2.  *
  3.  *  Called when preparing flash for a multiple-BIN download. 
  4.  *  Erases, verifies, and writes logical sector numbers in the range to be written.
  5.  *
  6.  *  ENTRY
  7.  *      dwStartBlock - starting physical block for format
  8.  *      dwNumBlocks - number of physical blocks to format
  9.  *      dwFlags - Flags used in formatting.
  10.  *
  11.  *  EXIT
  12.  *      TRUE returned on success and FALSE on failure.
  13.  */
  14. BOOL BP_LowLevelFormat(DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)
  15. {
  16.     dwNumBlocks = min (dwNumBlocks, g_FlashInfo.dwNumBlocks);
  17.     RETAILMSG(1,(TEXT("Enter LowLevelFormat [0x%x, 0x%x]./r/n"), dwStartBlock, dwStartBlock + dwNumBlocks - 1));
  18.     // Erase all the flash blocks.
  19.     if (!EraseBlocks(dwStartBlock, dwNumBlocks, dwFlags))
  20.         return(FALSE);
  21.     // Determine first good starting block
  22.     while (IS_BLOCK_UNUSABLE (dwStartBlock) && dwStartBlock < g_FlashInfo.dwNumBlocks) {
  23.         dwStartBlock++;
  24.     }
  25.     if (dwStartBlock >= g_FlashInfo.dwNumBlocks) {
  26.         RETAILMSG(1,(TEXT("BP_LowLevelFormat: no good blocks/r/n")));        
  27.         return FALSE;
  28.     }
  29.     // MBR goes in the first sector of the starting block.  This will be logical sector 0.
  30.     g_dwMBRSectorNum = dwStartBlock * g_FlashInfo.wSectorsPerBlock;
  31.     // Create an MBR. 哦原来创建了MBR...................哈哈,找到关键点了
  32.     CreateMBR();
  33.     RETAILMSG (1, (TEXT("Done./r/n/r/n")));
  34.     return(TRUE);
  35. }

——转微软MVP对这个函数的解释

2. BOOL BP_LowLevelFormat(DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)

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

// This should not change unless reserved blocks are added/removed;
// made global to do the calc only once.
    g_dwImageStartBlock = IMAGE_START_BLOCK;

再从前面看可知

#define RESERVED_BOOT_BLOCKS   (NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE + EBOOT_BLOCK_SIZE)

// Images start after OEM Reserved Blocks
#define IMAGE_START_BLOCK    RESERVED_BOOT_BLOCKS
#define IMAGE_START_SECTOR BLOCK_TO_SECTOR MAGE_START_BLOCK

综上所述,MBR不是是放在FAT区域的第一个block里面;而是放在NK占用部分的第一个block里面,为什么会这样呢?那系统是怎么读取MBR的,他怎么知道这个MBR所在的位置?

——本文到此结束,关于MBR以及分区等的事情,准备到下一篇文章讨论。

转载请标明:作者wogoyixikexie@gliet.桂林电子科技大学一系科协。如有错误,希望能够留言指出。