04.uboot分析uboot启动内核

网友投稿 814 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

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

04.uboot分析之uboot启动内核

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 的使用技巧
相关文章