您的位置:首页 > 运维架构 > Linux

为AM335x移植Linux内核主线代码(4)booting-without-of.txt学习笔记上

2018-03-28 08:50 661 查看
转载地址:http://www.eefocus.com/marianna/blog/14-10/306295_02c38.html

以下是摘抄的Linux内核的Documentation的内容,一边学一边做笔记。

所以以下内容可直接忽略,看源代码更方便~

linux-3.16.1/Documentation/devicetree/booting-without-of.txt
==========================================
I) - Introduction
========================
1)Entry point for arch/arm
---------------------------

a) ATAGS interface.
b) Entry with a flattened device-tree block.
Firmware loads 
the physical address of the flattened device
tree block (dtb) 
into r2, r1 is not used, but it is considered
good practice 
to use a valid machine number as described in 
Documentation/arm/Booting.

The kernel will differentiate between ATAGS
and device tree 
booting by reading the memory pointed to by
r2 and looking for 
either the flattened device tree block magic
value (0xd00dfeed) 
or ATAG_CORE value at offset 0x4 from r2 (ox54410001).

        ***********************************************
        练习题:使用od -x命令查看生成的xx.dtb文件,会发现神马呢?

        [maria@localhost dts]$ od -x maria_am335x.dtb
        0000000 0dd0 edfe 0000 fd6c 0000 3800
0000 a467
        0000020 0000 2800 0000 1100 0000 1000
0000 0000
        0000040 0000 5905 0000 6c67 0000 0000
0000 0000
        0000060 0000 0000 0000 0000 0000 0100
0000 0000
        0000100 0000 0300 0000 0400 0000 0000
0000 0100
        0000120 0000 0300 0000 0400 0000 0f00
0000 0100
        0000140 0000 0300 0000 1a00 0000 1b00
6974 6d2c
        0000160 7261 6169 615f 336d 3533 0078
6974 612c
        0000200 336d 7833 0078 0000 0000 0300
0000 0400
        0000220 0000 2600 0000 0100 0000 0300
0000 1700
        
        答:可观察到前4个字节就是0xd00dfeed。
        ***********************************************
        
II) - The DT block format
========================

This chapter defines the actual format of the
flattened 
device-tree passed to the kernel. It is expected
that a 
bootloader like uboot provides a bot more support.

Note: The block has to be in main memory. It
has to be 
accessible in both real mode and virtual mode
with no mapping 
other than main memory. If you are writing a
simple flash 
bootloader, it should copy the block to RAM
before passing 
it to the kernel.

1) Header
---------

The kernel is passed the physical address pointing
to an area 
of memory that is roughly described in include/linux/of_fdt.h 
by the structure boot_param_header:

struct boot_param_header {
        u32 magic;              /* magic work
OF_DT_HEADER */
        u32 totalsize;          /* total size
of DT block */
        u32 off_dt_struct;      /* offset to
structure */
        u32 off_dt_strings;     /* offset to
strings */
        u32 off_mem_rsvmap;     /* offset to
memory reserve 
                                   map */
        u32 version;            /* format version
*/
        u32 last_comp_version;  /* last compatible
version */
        
        /* version 2 fields below */
        u32 boot_cpuid_phys;    /* Which physical
CPU id we're 
                                booting on */
        /* version 3 fields below */
        u32 size_dt_strings;    /* size of the
strings block */

        /* version 17 fields below */
        u32 size_dt_struct;     /* size of the
DT structure block */
};

/* Definitions used by the flattened device
tree */
#define OF_DT_HEADER            0xd00dfeed     
/* 4: version
                                                  
4: total size */
#define OF_DT_BEGIN_NODE        0x1            
/* Start mode: full 
                                                  
name */
#define OF_DT_END_NODE          0x2            
/* End node */
#define OF_DT_PROP              0x3            
/* Property: name off,
                                                  
size, content */
#define OF_DT_END               0x9

All values in this header are in big endian
format, the various fields 
in this header are defined more precisely below.
All "offset" values 
are in bytes from the start of the header; that
is from the physical 
base address of the device tree block.

- magic
This is a magic value that "marks" the beginning
of the 
device-tree block header. It contains the value
0xd00dfeed and 
is defined by the constant OF_DT_HEADER
        
        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,magic在哪里?
        
        答:发现前面四个字节是0dd0 edfe,因为它的存储格式是big endian,
        所以倒过来就是0xd00dfeed,这奏是magic value。
        ***********************************************        
        
- totalsize
This is the total size of the DT block including
the header. The
"DT" block should enclose all data structures
defined in this 
chapter (who are pointed to by offsets in this
header). That is,
the device-tree structure, strings, and the
memory reserve map.
        
        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,totalsize在哪里?
         
        答:紧跟着magic value的就是totalsize,是0000 fd6c,因为它的存储格式是big 
        endian,所以实际的值为0x00006cfd。
        
        顺便学习一个小知识,Linux下用bc命令转换数制,在命令提示符下输入bc,如果要将
        十六进制转换成十进制,就输入:
        obase=10
        ibase=16
        obase和ibase的顺序不可以反,然后再输入要转换的(大写)值就可以:
        输入: 6CFD
        输出: 27901
        
        使用ls -l查看文件,也发现它的文件大小刚好是27901字节:
        -rw-rw-r--. 1 maria maria 27901 Oct
21 15:57 maria_am335x.dtb
        ***********************************************        

- off_dt_struct
This is an offset from the beginning of the
header to the start 
of the "structure" part the device tree.        

        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,off_dt_struct在哪里?
         
        答:紧跟着totalsize的就是off_dt_struct,00003800,因为它的存储格式是
        big endian,所以实际的值为0x00000038。在查看od命令下的地址时,要注意它默认
        是以八进制打印出来的,所以在这里要使用更复杂的od命令:
        
        [maria@localhost dts]$ od -A x -t xz
-v maria_am335x.dtb
        000000 edfe0dd0 fd6c0000 38000000 a4670000 
>......l....8..g.<
        000010 28000000 11000000 10000000 00000000 
>...(............<
        000020 59050000 6c670000 00000000 00000000 
>...Y..gl........<
        000030 00000000 00000000 01000000 00000000 
>................<
        000040 03000000 04000000 00000000 01000000 
>................<
        000050 03000000 04000000 0f000000 01000000 
>................<
        000060 03000000 1a000000 1b000000 6d2c6974 
>............ti,m<
        000070 61697261 336d615f 00783533 612c6974 
>aria_am335x.ti,a<
        000080 7833336d 00000078 03000000 04000000 
>m33xx...........<

        从0x00000038开始,才是device tree的structure存储的地方。
        ***********************************************    
        
- off_dt_strings
This is an offset from the beginning of the
header to the start of
the "strings" part of the device-tree.

        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,off_dt_strings在哪里?    
        
        答:紧跟着off_dt_struct的就是off_dt_strings,a4670000,因为它的存储
        格式是big endian,所以实际的值为0x000067a4。查看此地址的值:
        
        0067a0 09000000 64646123 73736572 6c65632d 
>....#address-cel<
        0067b0 2300736c 657a6973 6c65632d 6300736c 
>ls.#size-cells.c<
        ***********************************************

- off_mem_rsvmap
This is an offset from the beginning of the
header to the start of the 
reserved memory map. This map is a list of pairs
of 64-bit integers. 
Each pair is a physical address and a size.
The list is terminated by 
an entry of size 0. This map provides the kernel
with a list of physical 
memory areas that are "reserved" and thus not
to be used for memory 
allocations, especially during early initialization.
The kernel needs
to allocate memory during boot for things like
un-flattening the 
device-tree, allocating an MMU hash table, etc...
Those allocations must
be done in such a way to avoid overriding critical
things like, on Open
Firmware capable machines, the RTAS instance,
or on some pSeries, the TCE
tables used for the iommu. Typically, the reserve
map should contain _at 
least_ this DT block itself (header, total_size).
If you are passing an 
initrd to the kernel, you should reserve it
as well. You do not need to 
reserve the kernel image itself. The map should
be 64-bit aligned.

        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,off_mem_rsvmap在哪里?    
        
        答:紧跟着off_dt_strings的就是off_mem_rsvmap,28000000,因为它的存储
        格式是big endian,所以实际的值为0x00000028。理论上AM335x的地址空间有很多
        map都是不能写的,包括关键的CPU寄存器和各种各样的外设寄存器等等。
        
        (64-bit map的具体含义是???)
        ***********************************************

- version
This is the version of this structure. Version
1 stops here. Version 2 
adds an additional field boot_cpuid_phys. Version
3 adds the size of the
strings block, allowing the kernel to reallocate
is easily at boot and 
free up unused flattened structure after expansion.
Version 16 introduces
a new more "compact" format fr the tree itself
that is however not 
backward compatible. Version 17 adds an additional
field, size_dt_struct, 
allowing it to be reallocated or moved more
easily (this is particularly 
useful for bootloaders which need to make adjustments
to a device tree 
based on probed information). You should always
generate a structure of 
highest version defined at the time of your
implementation. Currently 
that is version 17, unless you explicitly aim
at being backward 
compatible.

        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,version在哪里?    
        
        答:紧跟着off_mem_rsvmap的就是version,11000000,因为它的存储
        格式是big endian,所以实际的值为0x00000011,也就是最新版的17。
        ***********************************************

- last_comp_version
Last compatible version. This indicates down
to what version of the DT
block you are backward compatible. For example,
version 2 is backward
compatible with version 1 (that is, a kernel
build for version 1 will 
be able to boot with a version 2 format). You
should put a 1 in this 
field if you generate a device tree of version
1 to 3, or 16 if you 
generate a tree of version 16 or 17 using the
new unit name format.

        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,last_comp_version在哪里?    
        
        答:紧跟着version的就是last_comp_version,10000000,因为它的存储
        格式是big endian,所以实际的值为0x00000010,也就是16。
        ***********************************************

- boot_cpuid_phys
This field only exist on version 2 headers.
It indicate which physical 
CPU ID is calling the kernel entry point. This
is used, among others, by 
kexec. If you are on an SMP system, this value
should match the content
of the "reg" property of the CPU node in the
device-tree corresponding 
to the CPU calling the kernel entry point (see
further chapters for more 
information on the required device-tree contents)

        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,boot_cpuid_phys在哪里?    
        
        答:我编译的dtb版本为17,所以这个值是未定义的,为0x00000000。
        ***********************************************

- size_dt_strings
This field only exists on version 3 and later
headers. It gives the size
of the "strings" section of the device tree
(which starts at the offset
given by off_dt_strings).

        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,size_dt_strings在哪里?    
        
        答:size是0x00000559。
        起始地址是off_dt_strings,0x000067a4。
        所以末尾地址是0x00006cfd。
        整个dtb文件的末尾地址也是0x00006cfd。
        ***********************************************

- size_dt_struct
This field only exists on version 17 and later
headers. It gives the size 
of the "structure" section of the device tree
(which starts at the offset 
given by off_dt_struct).

        ***********************************************
        练习题:观察maria_am335x.dtb的十六进制值,size_dt_struct在哪里?    
        
        答:size是0x0000676c。
        起始地址是off_dt_strings,0x00000038。
        所以末尾地址是0x000067a4。
        刚好是off_dt_strings的地址。
        ***********************************************
        
So the typical layout of a DT block (though
the various parts don't need 
to be in that order) looks like this (addressed
go from top to bottom):

                -----------------------------------------
        base -> |       struct boot_param_header       
|
                ------------
c798
-----------------------------
                |       (alignment gap)) (*)           
|
                -----------------------------------------
                |       memory reserve map             
|
                -----------------------------------------
                |       (alignment gap)                
|
                -----------------------------------------
                |                                      
|
                |       device-tree structure          
|
                |                                      
|
                -----------------------------------------
                |       (alignment gap)                
|
                -----------------------------------------
                |                                      
|
                |       device-tree strings            
|
                |                                      
|
         ---->  -----------------------------------------
         |
         |
         --- (base + totalsize)
         
         (*)The alignment gaps are not necessarily
present; their 
         presence and size are dependent on
the various alignment
         requirements of the individual data
blocks.
         
2) Device tree generalities
---------------------------

This device-tree itself is separated in two
different blocks, a structure 
block and a strings block. Both need to be aligned
to a 4 byte boundary.

First, let's quickly describe the device-tree
concept before detailing 
the strong format. This chapter does _not_ describe
the detail of the 
required types of nodes & properties for the
kernel, this is done later 
in chapter III.

The device-tree layout is strongly inherited
from the definition of the 
Open Firmware IEEE 1275 device-tree. It's basically
a tree of nodes, each 
node having two or more named properties. A
property can have a value or 
not.

It is a tree, so each node has one and only
one parent except for the 
root node who has no parent.

A node has 2 names. The actual node name is
generally contained in a 
property of type "name" in the node property
list whose value is a zero 
terminated string and is mandatory for version
1 to 3 of the format 
definition (as it is in Open Firmware). Version
16 makes it optional as 
it can generate it from the unit name defined
below.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: