04.uboot分析之uboot启动内核
【摘要】
首先要明确:uboot目标是从flash读出内核(nand read.jffs2 0x30007FC0 kernel;),启动它(bootm 0x30007FC0)。
/*从NAND读出内核:从哪里读,...
首先要明确:uboot目标是从flash读出内核(nand read.jffs2 0x30007FC0 kernel;),启动它(bootm 0x30007FC0)。
/*从NAND读出内核:从哪里读,从kernel分区读
放到哪里去:0x30007FC0(可以随便放)
nand read.jffs2 0x30007FC0 0x00060000 0x00200000*/
nand read.jffs2 0x30007FC0 kernel;
/*flash上存放的内核为uimage,uimage为头部+真正的内核*/
bootm 0x30007FC0
/*image_header 如下*/
typedef struct image_header {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
/*bootm先读出头部,知道加载地址和入口地址。当真正的内核不位于加载地址时,会自动把内核放到加载地址,然后跳转到入口地址执行。*/
/*所以可以随便放内核到某个地址。我们开发板的加载地址0x30008000 */*/
uint32_t ih_load; /* Data Load Address加载地址 */
uint32_t ih_ep; /* Entry Point Address入口地址 */
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
/* Copy header so we can blank CRC field for re-calculation 读出头部*/
memmove (&header, (char *)addr, sizeof(image_header_t));
/**/
/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) data为真正内核,移动到ih_load地址 */
memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
/*另外一种情况,不需要移动内核,内核刚好位于ih_load地址*/
/*为什么是0x30007FC0地址?0x30008000-0x30007FC0=64字节。头部刚好为64字节。 0x30007FC0+64字节刚好为加载地址0x30008000。不需要再次移动*/
if(ntohl(hdr->ih_load) == data) {
printf (" XIP %s ... ", name);
}
/*综上,bootm做的事情:1.移动内核到合适的地方(加载地址);2.启动。(do_bootm_linux)*/
/*内核也位于加载地址了,是不是就可以在入口地址启动内核了?不是!PC机启动时BIOS会检测内存,flash告诉内核*/
/*同样uboot也要告诉内核一些启动参数;之后才会跳到入口地址启动内核*/
theKernel = (void (*)(int, int, uint))addr;
/*hdr->ih_ep头部入口地址*/
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
/*启动内核*/
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
/*启动内核:1.设置参数2.跳转到入口地址去*/
/*如何设置参数*/
/*uboot把内核读进来之后就启动他然后跳转到内核去,uboot就不存在了。uboot和内核之间如何交互数据。*/
/*在某个地址(和内核约定好的,开发板0x30000100)按某种格式(TAG)保存数据,内核启动后再去读出来。*/
setup_start_tag (bd);
setup_memory_tags (bd);
setup_commandline_tag (bd, commandline);
setup_end_tag (bd);
static void setup_start_tag (bd_t *bd)
{
params = (struct tag *) bd->bi_boot_params;
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);
struct tag {
struct tag_header hdr;
union {
struct tag_core core;
struct tag_mem_range mem_range;
struct tag_cmdline cmdline;
struct tag_clock clock;
struct tag_ethernet ethernet;
} u;
};
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
分区概念:
PC机可以给硬盘分区,但是嵌入式linux的flash没有分区表。所以我们只能在代码写死bootloader分区,kernel分区,root分区等。所谓的ubbot的分区,我们关心地址。在100ask24x0.h中已经写死,如下:
/*分区位于nandflash0上,从0到256k为bootloader;接下来的128k为存放环境变量的params;接下来2m为kernel;剩下的为root。起始地址和大小很重要!*/
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader)," \
"128k(params)," \
"2m(kernel)," \
"-(root)"
- 1
- 2
- 3
- 4
- 5
文章来源: blog.csdn.net,作者:嵌入式与Linux那些事,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/qq_16933601/article/details/102845767
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)