ARM I.MX51双启动模式实现,Ubuntu 和Wince

来源:互联网 发布:photoshop软件下载 编辑:程序博客网 时间:2024/06/05 11:05

SDCard 上引导双系统(winceubuntu)的详细过程;

硬件平台:Freescale, MX.51-EVKboard;

wince版本:wince6.0 R2, MX.51-EVK BSP from Freescale

ubuntu版本:ubuntu9.04,kernel 2.6.28;


联系方式chenxi1243@qq.com; qq 号码:584906351


第一:单系统的两种引导方式介绍

单系统的两种引导方式:

wince的引导方式为xldr.nb0+eboot.nb0+nk.bin,其中xldr.nb0 作用用于引导eboot.nb0eboot用于wince内核nk.bin的下载与引导;nk.binwince的内核;

如图1-1所示:其中所有都是*.nb0文件,是raw数据,nk.bin被写到sdcardflash上面的时候自动被eboot解成了raw数据。关于*.nb0*.bin的区别网上有很多介绍,这里就不讲了。

ubuntu的引导方式为babbage_sdinitblocks.bin+redboot.bin+zImage,其中babbage_sdinitblocks.binsdcardMBR以及用于引导redboot的代码,redboot用于下载ubuntu的内核以及ubuntu的引导,zImageubuntu的内核。

如图1-2所示。

 

 

 

  1-1Sdcard Flash memory map forwince (http://p.blog.csdn.net/images/p_blog_csdn_net/chenxi_1243/EntryImages/20091030/Sdcard Flash memory map for wince.jpg)

 

  1-2Sdcardflash memory map for ubuntu(http://p.blog.csdn.net/images/p_blog_csdn_net/chenxi_1243/EntryImages/20091030/Sdcard flash memory map for ubuntu.jpg)

 

 

 

 

两种引导方式sdcard 制作过程:

第一种,Wince6.0的引导,需要准备的文件:xldr.nb0,eboot.nb0,nk.bin(由Freescale BSP编译出);

1: 利用cfimager.exe工具写入xldr.nb00x400地址

"D:/Tools/cfimager  -f xldr.nb0 -d <logical driver letter forSD card> -o 0x400"

 

1024个字节保留为MBR,运行上述命令后,一是把xldr.nb0写到flash0x400处,二是重置MBR区域。MBR中前136个字节(0x00-0x88)是主引导程序,后面是分区信息,以指示xldr.nb0的位置。PC上的原理是这样,但是ARM的板子好像并非如此,我用Winhex读入一个装有wincesdcardMBR信息,发现主引导程序段都是0x00信息。奇怪中,有时间再去研究一下。可能上电运行并不是从0x00处执行,很有可能是0x400,也就是xldr,nb0的位置。

 

2:利用cfimager.exe工具写入eboot.nb00x20000地址

D:/Tools/cfimager  -f eboot.nb0 -d <logical drive letter forSD card> -o 0x20000

 

这个0x20000地址是sdcard上面的地址,主要用于xldr.nb0启动后引导eboot,如果需要修改此地址,那么xldr.bib也需要相应修改,因为我最后实现双启动是用了redboot来启动eboot,并没有使用xldr.nb0,所以不用修改xldr.bib文件中的ebootsdcard上面的起始地址。这里大家要注意一下。

3:完毕后,板子上电,然后就可以看到eboot启动画面了,按space键可以进入菜单选择项,可以根据需求,来选择是通过网线来下载nk.bin还是直接引导sdcard上面的nk.nb0内核文件。如果是第一种,那么如果下载的nk.binram版本,那么就会直接运行wince,如果下载的nk.binsdcard版本,那么eboot就会把nk.bin解压成*.nb0格式然后烧写道sdcardflash内存上去。如果是第二种,应该用cfimager.exe事先把nb.nb0写到sdcard上面。

 

 

 

第二种,ubuntu9.04的引导,需要准备的文件:Babbage_sdinitblocks.binredboot.bin,以及zImage9.04_jaunty_armel_offical_release_rootfs_april_21_09.tar.gz.(Freescale提供,源代码也有,可以修改编译)

1:格式化sdcard,0-20M的空间未分配,用来保存Babbage_sdinitblocks.binredboot.bin

zImage。剩余的空间格式化成ext3文件格式的主分区,用于加载文件系统。

2:使用脚本updater.shBabbage_sdinitblocks.bin写到从地址0x00000x0400的位置,共1024个字节。命令如下:

./updater.sh  –i./babbage/ babbage_sdinitblocks.bin –n /dev/mmcblk0

3:使用脚本updater.shredboot.bin写到从0x04000开始的地方。这个地址在Babbage_sdinitblocks.bin中被固定死了。如若修改,请修改产生Babbage_sdinitblocks.bin的源程序。命令如下:

./updater.sh  –b  ./babbage/redboot.bin –n /dev/mmcblk0

4::使用脚本updater.shzImage写到从0x100000开始的地方。这个地址不是固定的,可以通过redboot命令fis create 来灵活修改。写入命令如下:

./updater.sh  -k./babbage/zImage –n /dev/mmcblk0

5 :把ubunturoot文件系统解压缩到主分区,以使内核运行后自动加载。命令如下:

mount  /dev/mmcblk0p1/media/sdcard

tar –zxvf 9.04_jaunty_armel_offical_release_rootfs_april_21_09.tar.gz–C /media/sdcard

umount /media/sdcard

6:板子上电后,就可以看到redboot的引导过程,以及内核的加载运行过程了,完毕进入ubuntu的登陆画面。

 

 

 

第二:SD Card双系统启动

 

曾经尝试的几种方案:

 

1xldr+redboot+zImage方式,因为xldr+eboot+nk.binwince默认的启动方式,如果xldr也可以启动redboot,那么此方案就算成功。测试结果,xldr不可以启动redboot,虽然把redboot.bin写到与eboot.nb0相同的地方。但是上电后并不可以启动redboot,看了xldr的代码后才知道,应该把xldr中加载eboot的那一段改成可以加载redboot的代码,所以移植Babbage_sdinitblocks.bin的代码中那段到xldr中就应该能解决问题,但遗憾的是Babbage_sdinitblocks.bin的源代码并没有从freescale拿到。所以此方案不了了之。

2mybootloader+eboot+nk.bin mybootloader+redboot+zImage方案。此方案就是做一个类似于grub 或者是lilo的引导程序。最终没有实现,就其原因有二:第一,PC上的grub是写入MBR中的,通过首先执行MBR中的代码实现双系统的加载。而ARM目前的嵌入式上的内核加载方式并非如此,虽然有MBR,但是并不是执行其中的代码来引导系统的。你可以打开单独装有wince系统的sdcardMBR,使用工具winhex,主引导程序段都是0x00, 还有我曾经写emailubuntu的总部技术负责人jerone,回复如下:

> Dear jerone:
>     Now I'm using a board of IMX.51 from freescalecompany. I want to
> boot both ubuntu and wince from the same sdcard.
Not sure what wince is ?

>  currently my board can run ubuntu and wince in separate sdcards. the
> ubuntu is your package for  IMX.51 board. it uses redboot as its
> bootloader. and the wince kernel is built by freescale's bsp. it use
> eboot as its bootloader.
Do you mean redboot?

>  what I want to do is to change the MBR to direct the two bootloaders
> for the two different
OSs.
That isn't possible. Since they don't acutally use MBRs. That is
something done on x86. For the Freescale boards at the beginning of the
SD card is the actual firmware (written raw to disk).

> as I know, the code in the begaining of 0000-0088H addresses of sdcard
> MBR let the board to locate the bootloader for OS.

>  so I want to do some changes here to boot the two
OSs. I have
> disassembled the MBR code for the ubuntu sdcard but can not make sure
> the code is correct.

> so if you can give some advices or give the source code of the MBR for
> ubuntu system, it will be great appriciated. thank you very much.

Sadly for what you want to do isn't exactly possible. They way it works
is the firmware & kernel are written raw to the disk. This is why you
leave about the first 10 - 20 MB unallocated. The firmware then knows
where to look on the disk (this is the address your looking at) and
reads the kernel from that location. This is still in the unallocated
space. The firmware (in this care redboot) will then boot the kernel
once it has it loaded into memory.

So what your trying to do your stuck with 2 seperate SD cards. In the
future though we hope to get a bootloader such as Grub 2 so you can have
a more dynamic type enviroment.

Right now you can't.

            Thanks,
               Jerone

第二个原因:即使可以通过更改MBR来实现, 因为并没有Babbage_sdinitblocks.bin的源代码,所以不清楚如何调用redboot。只能作罢。

 

3Babbage_sdinitblocks.bin+redboot+nk.nb0Babbage_sdinitblocks.bin+redboot+zImage方案。只要测试redboot能够引导起nk.nb0就可以了。测试结果:可以用redboot通过Ethernet下载nk.nb0ram中,但是跳转到入口地址0x200000,没有什么反应,猜想应该是eboot引导nk.nb0时带参数调用或者做了一些初始化工作。所以如果想直接由redboot来引导nk.nb0应该需要对redboot源码进行一下修改。但是此时突然想到,如果用redboot先引导起eboot来,然后由eboot来引导nk.nb0应该会可行。所以想到了第四个方案,也就是最终解决方案。

4Babbage_sdinitblocks.bin+redboot.bin+eboot.nb0Babbage_sdinitblocks.bin+redboot.bin+zImage方案。这也是我的最终解决方案。

(1):redboot 通过Ethernet下载eboot.nb0 到地址0x40000,然后运行,成功,命令如下:

load –v –r –b 0x40000 eboot.nb0

(load –r –b 0x40000 –m xmodem :通过串口下载,比较慢)

run

.这里强调一点,下载到内存的地址必须是eboot.bib中定义的地址。我的是0x40000,下载到别的地方不可以运行。

(2):通过redbooteboot.nb0写到SD Card上面。命令如下:

写入eboot.nb0之前的SD Card 的内存分布:

Name             FLASH addr  Mem addr    Length     Entry point

RedBoot          0x00000000  0x00000000  0x00040000 0x00000000

FIS directory    0x00040000  0x00040000  0x0001F000 0x00000000

RedBoot config   0x0005F000  0x0005F000  0x00001000 0x00000000

 

执行的命令:

fis create –b 0x40000 –l 0x40000–f 0x60000 –r 0x40000 –e 0x40000 –n eboot (创建一个索引在SDCard 上)

 

load –v –r –b 0x40000 eboot.nb0 (通过网络下载eboot.nb0,Host 端用tftp

fis write –f  0x60000 –b0x40000 –l 0x40000 (eboot.nb0写入SD Card flash)

 

命令执行完后SD Card内存分布:

RedBoot> fislist

... Read from0x1fee0000-0x1feff000 at 0x00040000: .

Name              FLASH addr  Mem addr   Length      Entry point

RedBoot           0x00000000  0x00000000 0x00040000  0x00000000

FISdirectory     0x00040000  0x00040000  0x0001F000 0x00000000

RedBootconfig    0x0005F000  0x0005F000 0x00001000  0x00000000

eboot             0x00060000  0x00040000  0x00040000 0x00040000

RedBoot>

 

之后执行下面命令:

fis load eboot

出现错误如下:

 

RedBoot>fis load eboot

...Read from 0x1fee0000-0x1feff000 at 0x00040000: .

Not aloadable image - try using -b ADDRESS option  

RedBoot>

 

When I use –baddress option, the output is as below:

RedBoot>fis load -b 0x40000

...Read from 0x1fee0000-0x1feff000 at 0x00040000: .

Noimage '<null>' found

RedBoot>

这里出现了错误,仔细分析一下,就可以知道,FISdirectory eboot的下载到内存的地址重叠了。应该是这个原因,但是eboot按照eboot.bib中的设定,必须下载到0x40000的位置才可以执行,解决办法就是更改eboot.bib 然后重新编译eboot.

需要修改的有三个地方:

第一,修改前:

MEMORY

; Driver globals area (used to pass config info to kernel,don't change unless

; you update config.bib) NOTE: We're using physicaladdresses here.

;       Name             Start         Size          Type

;       -------          --------      --------      ----

        ARGS             80000000      00001000     RESERVED

        XLDR             80001000      00001000     RESERVED

        STACK            80002000      0003A000    RESERVED

       PAGE_TABLE       8003C000      00004000     RESERVED

        $(TARGETNAME)    80040000      00040000     RAMIMAGE

;IPL is obsolete, remove it to avoidpotential romimage issue

       ;IPL              80080000      00040000     RESERVED

        RAM              800C0000      00040000     RAM

; Flash cache (used to storeeboot.bin or nk.bin before flashing)

        FCACHE           80100000      07F00000      RESERVED

 

修改后:

MEMORY

; Driver globals area (used to pass config info to kernel,don't change unless

; you update config.bib) NOTE: We're using physicaladdresses here.

;       Name             Start         Size          Type

;       -------          --------      --------      ----

        ARGS             80000000      00001000    RESERVED

        XLDR             80001000      00001000     RESERVED

        STACK            80002000      0003A000     RESERVED

       PAGE_TABLE       8003C000      00004000     RESERVED

        $(TARGETNAME)    80100000      00040000    RAMIMAGE

;IPL is obsolete, remove it to avoidpotential romimage issue

       ;IPL              80140000      00040000     RESERVED

        RAM              80180000      00040000     RAM

 

; Flash cache (used to storeeboot.bin or nk.bin before flashing)

        FCACHE           801C0000      07F00000      RESERVED

 

eboot 的内存入口地址,改为0x100000,前面的8000000其实是ram的物理起始地址。在eboot之后的地址统一向后偏移0xC0000

第二个,修改前:

    ROMSIZE =00040000

    ROMSTART=80040000

    ROMWIDTH=32

修改后:

    ROMSIZE =00040000

    ROMSTART=80100000

    ROMWIDTH=32

ROMSTART也相应修改,就是ebootram中的加载地址。

 

第三个,修改前:

IF IMGNAND !

    ; 0x97D20000 =(0x80040000 + ROMOFFSET) & 0xFFFFFFFF ==> ROMOFFSET = 0x17CE0000

    ROMOFFSET=0x17CE0000

    ENDIF

ENDIF

修改后:

IF IMGNAND !

    ; 0x97D20000 =(0x80100000 + ROMOFFSET) & 0xFFFFFFFF ==> ROMOFFSET = 0x17CE0000

    ROMOFFSET=0x17C20000

    ENDIF

ENDIF

其实这个偏移地址是说明ebootram中的实际地址到sdcard上面起始地址的偏移。也就是eboot在内存中的起始地址为:0x80100000, sdcard上面的存储地址是0x97D20000,把eboot.nb0从内存移动到sdcardflash memory必须知道这个偏移量,或者反过来从sdcard上面把eboot.nb0加载至内存也许要知道。但我们并没有用到,我们后面是直接用redboot先下载至内存然后把 eboot.nb0写到sdcardflash memory上面的;从sdcard上拷贝至内存也是通过redboot命令load ram中的。所以其实我们并不需要这个偏移量,但是如果你是用的xldr.nb0+eboot.nb0+nk.bin的方案,那么这个变量是必需的。

 

这样修改完成之后,重新编译BSP,会生成新的eboot.nb0,

(1): 通过redboot下载到ram0x100000位置,然后run.命令如下:

 

load –v –r –b 0x100000 eboot.nb0

(load –r –b 0x100000 –m xmodem :通过串口下载,比较慢)

run

 

运行正常;

(2): 然后通过redbooteboot.nb0写到SD Card上面。命令如下:

写入eboot.nb0之前的SD Card 的内存分布:

Name             FLASH addr  Mem addr    Length     Entry point

RedBoot           0x00000000  0x00000000 0x00040000  0x00000000

FIS directory    0x00040000  0x00040000  0x0001F000 0x00000000

RedBoot config   0x0005F000  0x0005F000  0x00001000 0x00000000

 

执行的命令:

fis create –b 0x100000 –l0x40000 –f 0x60000 –r 0x100000 –e 0x100000 –n eboot (创建一个索引在SDCard 上)

 

load –v –r –b 0x100000 eboot.nb0 (通过网络下载eboot.nb0,Host 端用tftp

fis write –f  0x60000 –b0x100000 –l 0x40000 (eboot.nb0写入SD Card flash)

 

命令执行完后SD Card内存分布:

RedBoot> fislist

... Read from0x1fee0000-0x1feff000 at 0x00040000: .

Name              FLASH addr  Mem addr   Length      Entry point

RedBoot           0x00000000  0x00000000 0x00040000  0x00000000

FISdirectory     0x00040000  0x00040000 0x0001F000  0x00000000

RedBootconfig    0x0005F000  0x0005F000 0x00001000  0x00000000

eboot             0x00060000  0x00100000  0x00040000 0x00100000

RedBoot>

(3):运行下面命令加载ebootram,并运行

fis load eboot

run

(4):eboot测试成功。

(5):通过eboot来下载内核nk.bin,host 端是vs2005+Platform buider; 配置好connectivity option

 

图片1-3(http://p.blog.csdn.net/images/p_blog_csdn_net/chenxi_1243/EntryImages/20091030/connectivity option.jpg)

 

然后点击Target->AttachDevice

eboot中选择[D] Download Image Now

-----------------------------------------------------------------------------

 [0] IP Address : 192.168.0.163

 [1] Set IP Mask : 255.255.255.0

 [2] Boot Delay : 3

 [3] DHCP : Enabled

 [4] Reset to Factory Default Configuration

 [5] Select Boot Device : NK from SD/MMC

 [6] Set MAC Address : 0-4-9F-0-E9-7

 [7] Format OS NAND Region

 [8] Format All NAND Regions

 [9] Bootloader Shell

 [I] KITL Work Mode : Interrupt

 [K] KITL Enable Mode : Disable

 [P] KITL Passive Mode : Disable

 [S] Save Settings

 [D] Download Image Now

 [L] Launch Existing Flash Resident Image Now

 [E] Select Ether Device : FEC

 [M] MMC and SD Utilities

 

然后nk.bin就会被下载并解压到ram中,下载完成后,然后执行命令:

run

wince 系统就会运行起来了。

(6):nk.bin通过eboot解压后把nk.nb0烧写到sdcard上去。这个过程是这样,WinCE BSP可以编译一个具有参数IMGMMC=1nk.bin出来,把这个nk.bin通过eboot[D] Download Image Now 菜单下载后,它会首先把nk.bin下载解压到ram中,然后烧写到sdcard上面去。结果写到sdcard上的过程出现了错误,因为现在的eboot.nb0sdcard flash上面的位置0x60000,恰好是通过eboot自己烧写nk.nb0sdcard的地址。这样导致烧写失败。解决办法由两个,一个是修改eboot的烧写代码,把nk.nb0的烧写地址改为起始0x60000+长度0x40000=0xA0000的位置,然后改写eboot的加载代码,把加载nk.nb0的地址设为0xA0000;另外一个办法就是把nk.nb0通过其他工具先烧写到sdcard0xA0000位置,然后再改写eboot的加载代码,把加载nk.nb0的地址设为0xA0000;我采用的是第二种办法,本来想通过redboot下载nk.nb0ram,然后通过fis create fis write 把内存中的nk.nb0写到sdcard上面,但是使用fis write的时候出现了错误,提示不能烧写成功,可能是文件太大的原因。所以最后只能通过cimager.exe 来提前烧写nk.nb0sdcard0xA0000位置。其中eboot的烧写nk.nb0到代码以及eboot加载nk.nb0的代码在文件C:/WINCE600/PLATFORM/COMMON/SRC/SOC/COMMON_FSL_V2/BOOT/FMD/SDMMC/sdboot.c

函数BOOL SDHCWriteNK(DWORDdwStartAddr, DWORD dwLength)用于把nk.nb0写到sdcard上面。

这里只要修改SDImageCfg.dwNkOffset= 655360;(0xA0000)即可;也就修改了eboot烧写nk.nb0的起始地址。

函数BOOL SDHCLoadNK(VOID)用于把nk.nb0sdcard读出到ram中,也是只需修改SDImageCfg.dwNkOffset= 655360;(0xA0000)即可; 也就修改了ebootsdcard加载nk.nb0的起始地址。

对于我来说,只需修改函数BOOLSDHCLoadNK(VOID)就可以了。修改完之后重新编译BSP,生成新的eboot.nb0,通过上面的办法,把eboot.nb0烧写到flash0x60000位置,把nk.nb0通过cimager.exe烧写到0xA0000的位置。然后运行eboot.

选择L

 

[0] IP Address :192.168.0.163

 [1] Set IP Mask : 255.255.255.0

 [2] Boot Delay : 3

 [3] DHCP : Enabled

 [4] Reset to Factory Default Configuration

 [5] Select Boot Device : NK from SD/MMC

 [6] Set MAC Address : 0-4-9F-0-E9-7

 [7] Format OS NAND Region

 [8] Format All NAND Regions

 [9] Bootloader Shell

 [I] KITL Work Mode : Interrupt

 [K] KITL Enable Mode : Disable

 [P] KITL Passive Mode : Disable

 [S] Save Settings

 [D] Download Image Now

 [L] Launch ExistingFlash Resident Image Now

 [E] Select Ether Device : FEC

 [M] MMC and SD Utilities

 

后出现下面的输出,之后wince就运行起来了。

 

INFO: Usingdevice name: 'MX5165535'

INFO: Reading NKimage to SDHC (please wait)…..

INFO: Copying NK image to RAM address 0xa0200000

 

(7): redboot 引导wince成功了,可以说差不多大功告成了。下面是如何把ubuntuzImage也烧写到sdcardflash上面。然后引导起来。通过redboot的网络下载命令把zImage先下载到内存。

 

load –v –r –b 0x200000  zImage

(load –r –b 0x200000 –m xmodem :通过串口下载,比较慢)

然后烧写到sdcardflash上面。

Fis create  -b 0x100000 –l 0x200000  –f  0x02FE0000 -e 0xFFFFFFFF –n kernel

Fis write  -f  0x02FE0000-b 0x100000  -l  0x1d6d40

 

这里强调一点linux的入口地址是0xFFFFFFFF; 不要写成内存起始地址。

这样linux 内核就被写入起始地址为0x02FE0000的地方。但是还需有文件系统,才可以运行linux.

(8): 创建linux启动所需的文件系统。首先格式化sdcard, 保留前60M的空间,这些空间内写入了redboot,eboot,nk.nb0,zimage 等所需文件,不可以破坏。利用fdisk 命令分出一个主分区。起始block号码按预留的60M的空间算出。然后把这个主分区用mkfs.ext3格式化成ext3文件系统分区。最后用tar 命令把9.04_jaunty_armel_offical_release_rootfs_april_21_09.tar.gz 解压到这个主分区上。

主要命令如下:

fdisk /dev/mmcblk0

然后利用fdisk 命令d(删除分区),n(添加分区)等命令产生 一个主分区 /dev/mmcblk0p1

mkfs.ext3 /dev/mmcblk0p1(格式化分区为ext3文件系统格式)

mount  /dev/mmcblk0p1 /media/sdcard

tar –zxvf 9.04_jaunty_armel_offical_release_rootfs_april_21_09.tar.gz–C /media/sdcard

umount /media/sdcard

 

(10): 双启动模式,redboot支持脚本语言,设置ubuntu为默认加载的操作系统,可以自动加载。而Wince需要命令加载

1:加载脚本,如下

fis load kernel

e –c  “noinitrd console=tty1console=ttymxc0,115200 root=/dev/mmcblk0p1 rw video=mxcfb:1024x768-16@60”

2:加载wince的命令如下:

fis load eboot

run

 

目前是这样加载两个操作系统,当然不是很方便,所以现在正在研究redboot的源代码,可以把两个系统的加载脚本都写到fconfig里面去。然后通过信号中断来判断到底需要加载那个操作系统。或者可以做个类似于grub的选择界面出来。也是很不错的。不过,加载双系统总算成功了。恭喜自己哈。

原创粉丝点击