在u-boot里面加入Android lk bootloader的一键烧写功能(3)

来源:互联网 发布:pic单片机汇编指令 编辑:程序博客网 时间:2024/05/17 05:55

        烧写完成之后我们需要启动,我们看看lk怎么启动的吧。

      

int boot_linux(int argc, const cmd_args *argv){read_nand((u_char *)0x40007800 , 7, 0x800000);//将boot.img读入到内存的0x40007800地址中char *linux_cmd,*ramdisk_size;char *p;unsigned char *flag = KERNEL_ADDR + header_read(0);//header_read(0)表示kernel大小,header_read(1)表示ramdisk大小unsigned char *base = RAMDISK_ADDR;memset(params, 0, sizeof(struct tag));//设定一些列的参数,与启动内核相关 params->hdr.tag = ATAG_CORE;params->hdr.size = tag_size(tag_core);params->u.core.flags=0;params->u.core.pagesize = 0;params->u.core.rootdev = 0;params = tag_next(params);params->hdr.tag = ATAG_CMDLINE;linux_cmd = "root=/dev/ram0 rw console=ttyS0,115200 mem=216mb init=/init";         /*定位ramdisk的头部,因为我们说过,ramdisk是以1F8B080000开头的*/while(1){if( *(flag-1) == 0 && *flag == 0x1F && *(flag+1) == 0x8B)break;flag++;}printf("\nthe location of flag is :0x%0x",flag);memcpy(base,flag,header_read(1));for (p = linux_cmd; *p == ' '; p++);params->hdr.size = (sizeof(struct tag_header)+strlen(p)+1+4)>>2;strcpy(params->u.cmdline.cmdline,p);params = tag_next(params);setup_initrd_tag(RAMDISK_ADDR,header_read(1));params->hdr.tag = ATAG_NONE;params->hdr.size = 0;printf("Set environment end !\n");void (*entry)(unsigned,unsigned,unsigned*) = KERNEL_ADDR;  entry (0, MACHINE_ID, TAG_ADDR);//linux入口    return 0;}
        Android的启动和一般的linux启动不太相同。因为我们之前说过,Android的kernel是存放于boot.img里面的,这样我们想要引导linux内核,就要从boot.img中将kernel解析出来。可能由于内核编译时指定的需要,我们的内核地址、ramdisk、传参的地址都需要固定,否则无法启动(有待验证)。它们的地址指定如下:


#define START_ADDR 0x40007800
#define TAG_ADDR 0x40000100
#define KERNEL_ADDR 0x40008000
#define RAMDISK_ADDR 0x42000000

#define MACHINE_ID 2556  //我们板子的机器码ID


      因此我们在上电之后就需要将boot.img读入到内存的0x40007800地址中,然后将ramdisk拷贝到0x42000000地址中,并且设置linux启动所需要的参数。这样才能最终启动linux。


了解了lk如何启动linux之后,我们可以如法炮制,直接在u-boot里面加入同样的命令进行启动。还有一点需要说明的是我们没有办法直接利用u-boot的bootm指令来启动我们的Android,因为u-boot启动的linux内核需要uImage格式的内核镜像,uImage在zImage的头部加入了64byte的头部信息,而我们boot.img里面的image并不符合uImage。所以启动linux需要我们直接实现。好在lk已经告诉了我们应该如何启动了。如上一篇文章中一样我们在u-boot/common/下添加一个cmd_lkboot.c文件用来实现我们自己的启动。并将其加入编译。


在整个过程进行完之后发现了另外一个问题,那就是我们的lk在内存里面的运行地址为0x42800000 ,而我们的u-boot运行的地址为0x40400000,如果将boot.img读取到0x40007800之后因为boot.img文件的大小为6MB+,所以会将u-boot整个冲掉,导致无法完成。所以我们需要将u-boot搬移到更远端的地址。需要修改的有:

(1)u-boot/include/configs/SEP0611.h中相关的地址#define CONFIG_SYS_TEXT_BASE   #define CONFIG_UBOOT_BASE

(2)u-boot/arch/unicore/cpu/unicore32/u-boot.lds:        . = 0x42800000;

(3)u-boot/arch/unicore/cpu/unicore32/start.S 中的相关地址

(4)u-boot/arch/unicore/cpu/unicore32/SDIO.c nand.c相关的拷贝地址


修改完成!至此,我们就可以在uboot中使用dnw进行烧写然后用nandmtd命令进行解析,并用lkboot指令启动android系统了!