04.uboot分析uboot启动内核

网友投稿 765 2022-05-29

首先要明确: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

04.uboot分析之uboot启动内核

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

ARM

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:基于鲲鹏应用使能套件进行MySQL性能调优|【我的华为云体验之旅】
下一篇:通过实际的例子,介绍 SAP ABAP 里的 Repository Information System 的使用技巧
相关文章