在 SDCard 上引导双系统( wince , ubuntu )的详细过程;

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

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

ubuntu 版本 :ubuntu9.04,kernel 2.6.28;



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

单系统的两种引导方式:

wince 的引导方式为 xldr.nb0+eboot.nb0+nk.bin

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

ubuntu 的引导方式为 babbage_sdinitblocks.bin+redboot.bin+zImage

如图 1-2 所示。

 

 

   图 1-1 : Sdcard Flash memory map for wince ( Flash memory map for wince.jpg)

 

  图 1-2: Sdcard flash memory map for ubuntu( flash memory map for ubuntu.jpg)

 

 

 

 

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

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

1: 利用 cfimager.exe工具写入 xldr.nb0到 0x400地址

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

 

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

 

2:利用 cfimager.exe工具写入 eboot.nb0到 0x20000地址

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

 

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

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

 

 

 

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

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

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

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

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

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

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

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

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

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

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双系统启动

 

曾经尝试的几种方案:

 

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

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

> Dear jerone:
>     Now I'm using a board of IMX.51 from freescale company. 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 来实现, 因为并没有

 

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

4: Babbage_sdinitblocks.bin+redboot.bin+eboot.nb0 和 Babbage_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):通过 redboot把 eboot.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 (创建一个索引在 SD Card 上)

 

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

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

 

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

RedBoot> fis list

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

Name              FLASH addr  Mem addr    Length      Entry point

RedBoot           0x00000000  0x00000000  0x00040000  0x00000000

FIS directory     0x00040000  0x00040000

RedBoot config    0x0005F000  0x0005F000  0x00001000  0x00000000

eboot             0x00060000  0x00040000

RedBoot>

 

之后执行下面命令:

fis load eboot

出现错误如下:

 

RedBoot> fis load eboot

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

Not a loadable image - try using -b ADDRESS option  

RedBoot>

 

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

RedBoot> fis load -b 0x40000

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

No image '<null>' found

RedBoot>

这里出现了错误,仔细分析一下,就可以知道, FIS directory 和 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 physical addresses 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 avoid potential romimage issue

       ;IPL              80080000      00040000     RESERVED

        RAM              800C0000      00040000     RAM

; Flash cache (used to store eboot.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 physical addresses 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 avoid potential romimage issue

       ;IPL              80140000      00040000     RESERVED

        RAM              80180000      00040000     RAM

 

; Flash cache (used to store eboot.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也相应修改,就是 eboot在 ram中的加载地址。

 

第三个,修改前:

IF IMGNAND !

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

ROMOFFSET=0x17CE0000

    ENDIF

ENDIF

修改后:

IF IMGNAND !

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

ROMOFFSET=0x17C20000

    ENDIF

ENDIF

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

 

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

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

 

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

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

run

 

运行正常;

(2): 然后通过 redboot把 eboot.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 –l 0x40000 –f 0x60000 –r 0x100000 –e 0x100000 –n eboot (创建一个索引在 SD Card 上)

 

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

fis write –f  0x60000 –b 0x100000 –l 0x40000 (把 eboot.nb0写入 SD Card flash中 )

 

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

RedBoot> fis list

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

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

eboot             0x00060000  0x00100000

RedBoot>

(3): 运行下面命令加载 eboot 到 ram, 并运行

fis load eboot

run

(4): eboot 测试成功。

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

 

图片1-3( option.jpg)

 

然后点击 Target->Attach Device

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

 

  [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=1 的 nk.bin 出来,把这个 nk.bin 通过 eboot 的 [D] Download Image Now 菜单下载后,

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

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

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

对于我来说,只需修改函数 BOOL SDHCLoadNK(VOID) 就可以了。修改完之后重新编译 BSP, 生成新的 eboot.nb0, 通过上面的办法,把 eboot.nb0 烧写到 flash 的 0x60000 位置,把 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

 

[L] Launch Existing Flash Resident Image Now

  [E] Select Ether Device : FEC

  [M] MMC and SD Utilities

 

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

 

INFO: Using device name: 'MX5165535'

INFO: Reading NK image to SDHC (please wait)…..



INFO: Copying NK image to RAM address 0xa0200000



 

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

 

load –v –r –b 0x200000   zImage

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

然后烧写到 sdcard 的 flash 上面。

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=tty1 console=ttymxc0,115200 root=/dev/mmcblk0p1 rw video=mxcfb:1024x768-16@60”

2:加载 wince的命令如下:

fis load eboot

run

 

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


在 SDCard 上引导双系统( wince , ubuntu )的详细过程;

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

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

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

ubuntu 的引导方式为 babbage_sdinitblocks.bin+redboot.bin+zImage

如图 1-2 所示。

 

 

 

   图 1-1 : Sdcard Flash memory map for wince ( Flash memory map for wince.jpg)

 

  图 1-2: Sdcard flash memory map for ubuntu( flash memory map for ubuntu.jpg)

 

 

 

 

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

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

1: 利用 cfimager.exe工具写入 xldr.nb0到 0x400地址

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

 

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

 

2:利用 cfimager.exe工具写入 eboot.nb0到 0x20000地址

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

 

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

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

 

 

 

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

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

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

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

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

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

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

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

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

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

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双系统启动

 

曾经尝试的几种方案:

 

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

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

> Dear jerone:
>     Now I'm using a board of IMX.51 from freescale company. 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 来实现, 因为并没有

 

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

4: Babbage_sdinitblocks.bin+redboot.bin+eboot.nb0 和 Babbage_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):通过 redboot把 eboot.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 (创建一个索引在 SD Card 上)

 

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

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

 

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

RedBoot> fis list

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

Name              FLASH addr  Mem addr    Length      Entry point

RedBoot           0x00000000  0x00000000  0x00040000  0x00000000

FIS directory     0x00040000  0x00040000

RedBoot config    0x0005F000  0x0005F000  0x00001000  0x00000000

eboot             0x00060000  0x00040000

RedBoot>

 

之后执行下面命令:

fis load eboot

出现错误如下:

 

RedBoot> fis load eboot

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

Not a loadable image - try using -b ADDRESS option  

RedBoot>

 

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

RedBoot> fis load -b 0x40000

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

No image '<null>' found

RedBoot>

这里出现了错误,仔细分析一下,就可以知道, FIS directory 和 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 physical addresses 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 avoid potential romimage issue

       ;IPL              80080000      00040000     RESERVED

        RAM              800C0000      00040000     RAM

; Flash cache (used to store eboot.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 physical addresses 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 avoid potential romimage issue

       ;IPL              80140000      00040000     RESERVED

        RAM              80180000      00040000     RAM

 

; Flash cache (used to store eboot.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也相应修改,就是 eboot在 ram中的加载地址。

 

第三个,修改前:

IF IMGNAND !

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

ROMOFFSET=0x17CE0000

    ENDIF

ENDIF

修改后:

IF IMGNAND !

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

ROMOFFSET=0x17C20000

    ENDIF

ENDIF

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

 

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

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

 

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

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

run

 

运行正常;

(2): 然后通过 redboot把 eboot.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 –l 0x40000 –f 0x60000 –r 0x100000 –e 0x100000 –n eboot (创建一个索引在 SD Card 上)

 

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

fis write –f  0x60000 –b 0x100000 –l 0x40000 (把 eboot.nb0写入 SD Card flash中 )

 

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

RedBoot> fis list

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

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

eboot             0x00060000  0x00100000

RedBoot>

(3): 运行下面命令加载 eboot 到 ram, 并运行

fis load eboot

run

(4): eboot 测试成功。

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

 

图片1-3( option.jpg)

 

然后点击 Target->Attach Device

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

 

  [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=1 的 nk.bin 出来,把这个 nk.bin 通过 eboot 的 [D] Download Image Now 菜单下载后,

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

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

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

对于我来说,只需修改函数 BOOL SDHCLoadNK(VOID) 就可以了。修改完之后重新编译 BSP, 生成新的 eboot.nb0, 通过上面的办法,把 eboot.nb0 烧写到 flash 的 0x60000 位置,把 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

 

[L] Launch Existing Flash Resident Image Now

  [E] Select Ether Device : FEC

  [M] MMC and SD Utilities

 

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

 

INFO: Using device name: 'MX5165535'

INFO: Reading NK image to SDHC (please wait)…..



INFO: Copying NK image to RAM address 0xa0200000



 

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

 

load –v –r –b 0x200000   zImage

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

然后烧写到 sdcard 的 flash 上面。

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=tty1 console=ttymxc0,115200 root=/dev/mmcblk0p1 rw video=mxcfb:1024x768-16@60”

2:加载 wince的命令如下:

fis load eboot

run

 

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