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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
.. SPDX-License-Identifier: GPL-2.0+
Logical Memory Blocks (LMB)
===========================
U-Boot has support for reserving chunks of memory which is primarily
used for loading images to the DRAM memory, before these are booted,
or written to non-volatile storage medium. This functionality is
provided through the Logical Memory Blocks (LMB) module.
Introduction
------------
The LMB module manages allocation requests for memory region not
occupied by the U-Boot image. Allocation requests that are made
through malloc() and similar functions result in memory getting
allocated from the heap region, which is part of the U-Boot
image. Typically, the heap memory is a few MiB in size. Loading an
image like the linux kernel might require lot more memory than what
the heap can provide. Such allocations are usually handled through the
LMB module.
The U-Boot image typically gets relocated to the top of the usable
DRAM memory region. A typical memory layout looks as follows::
| |
| |
| |
| |
| |
--- +--------------+ <--- U-Boot ram top
| | |
| | Text |
| +--------------+
| | |
| | Data |
| +--------------+
| | |
| | BSS |
U-Boot Image +--------------+
| | |
| | Heap |
| | |
| +--------------+
| | |
| | |
| | Stack |
| | |
| | |
--- +--------------+
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
+--------------+ <--- ram start
The region of memory below the U-Boot image is the one controlled by
the LMB module.
Types of LMB Allocations
------------------------
There are two classes of allocation requests that get made to the LMB
module. One type of allocation requests are requesting memory of a
particular number of bytes. This type of allocation is similar to that
done using the malloc type of function calls. The other type of
allocations, are requests made for a specific memory address. The
second type of allocations are usually made for loading images to a
particular memory address.
LMB design Pre 2025.01
----------------------
The earlier versions of U-Boot (pre 2025.01 release)
had a local memory map based LMB implementation whereby it was
possible to declare the LMB map inside a function or a C file. This
design resulted in temporary, non-global LMB maps, which also allowed
for re-use of memory. This meant that it was possible to use a region
of memory to load some image, and subsequently the same region of
memory could be used for loading a different image. A typical example
of this usage would be loading an image to a memory address, followed
by writing that image to some non-volatile storage medium. Once this
is done, the same address can be used for loading a different image
and then writing it to it's non-volatile storage
destination. Typically, environment variables like `loadaddr`,
`kernel_addr_r`, `ramdisk_addr_r` are used for loading images to
memory regions.
Current LMB implementation
--------------------------
Changes were made in the 2025.01 release to make the LMB memory map
global and persistent. With this, the LMB memory map is the same
across all of U-Boot, and also persists as long as U-Boot is
active. Even with this change, there has been consistency as far as
re-use of memory is concerned to maintain backward compatibility. It
is allowed for re-requesting the same region of memory if the memory
region has a particular attribute (LMB_NONE).
As part of the platform boot, DRAM memory available for use in U-Boot
gets added to the LMB memory map. Any allocation requests made
subsequently will be made from this memory added as part of the board
init.
Allocation API
--------------
Any request for non-heap memory can be made through the LMB allocation
API.
.. code-block:: c
int lmb_alloc_mem(enum lmb_mem_type type, u64 align,
phys_addr_t *addr, phys_size_t size,
u32 flags);
Correspondingly, the allocated memory can be free'd
.. code-block:: c
long lmb_free(phys_addr_t base, phys_size_t size, u32 flags);
For a detailed API description, please refer to the header file.
UEFI allocations with LMB as the backend
----------------------------------------
The UEFI specification describes boot-time API's for allocation of
memory. These API's use the same memory that is being used by the LMB
module. Pre 2025.01 release, there wasn't any synchronisation between
the EFI sub-system and the LMB module about the memory that was
getting allocated by each of these modules. This was the primary
reason for making the LMB memory map global and persistent. With this
change, the EFI memory allocation API's have also been changed to use
the LMB module as the backend for the allocation requests. Any other
sub-system which might wish to use the same memory region for it's use
can then use the LMB as the backend for the memory allocations and
it's associated book-keeping.
API documentation
-----------------
.. kernel-doc:: include/lmb.h
|