以下是摘抄的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 |
-----------------------------------------
| (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.