summaryrefslogtreecommitdiff
path: root/util/cbfstool/README
blob: 912ffa985f5e9ae1ea1989b92797d7c04b88ca59 (plain)
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
Coreboot CBFS Specification
Jordan Crouse <jordan@cosmicpenguin.net>

= Introduction =

This document describes the coreboot CBFS specification (from here referred 
to as CBFS).  CBFS is a scheme for managing independent chunks of data in
a system ROM.  Though not a true filesystem, the style and concepts are
similar.

= Architecture =

The CBFS architecture looks like the following:

/---------------\ <-- Start of ROM
| /-----------\ | --|
| | Header    | |   |
| |-----------| |   |
| | Name      | |   |-- Component
| |-----------| |   |
| |Data       | |   |
| |..         | |   |
| \-----------/ | --|
|               |
| /-----------\ |
| | Header    | |
| |-----------| |
| | Name      | |
| |-----------| |
| |Data       | |
| |..         | |
| \-----------/ |
|               |
| ...           |
| /-----------\ |
| |           | |
| | Bootblock | |
| | --------- | |
| | Reset     | | <- 0xFFFFFFF0
| \-----------/ | 
\---------------/ 


The CBFS architecture consists of a binary associated with a physical
ROM disk referred hereafter as the ROM. A number of independent of
components, each with a  header prepended on to data are located within
the ROM.  The components are nominally arranged sequentially, though they
are aligned along a pre-defined boundary.

The bootblock occupies the last 20k of the ROM.  Within
the bootblock is a master header containing information about the ROM
including the size, alignment of the components, and the offset of the
start of the first CBFS component within the ROM.

= Master Header =

The master header contains essential information about the ROM that is
used by both the CBFS implementation within coreboot at runtime as well
as host based utilities to create and manage the ROM.  The master header
will be located somewhere within the bootblock (high end of the ROM).  A
pointer to the location of the header will be located at offset
-4 from the end of the ROM.  This translates to address 0xFFFFFFFC on a
normal x86 system.  The pointer will be to physical memory somewhere
between - 0xFFFF0000 and 0xFFFFFFF0.  This makes it easier for coreboot
to locate the header at run time.  Build time utilities will
need to read the pointer and do the appropriate math to locate the header.

The following is the structure of the master header:

struct cbfs_header {
	unsigned int magic;
	unsigned int version; 
	unsigned int romsize;
	unsigned int bootblocksize;
	unsigned int align;
	unsigned int offset;
	unsigned int pad[2];
};

The meaning of each member is as follows:

'magic' is a 32 bit number that identifies the ROM as a CBFS type.  The magic
number is 0x4F524243, which is 'ORBC' in ASCII. 

'version' is a 32 bit number that identifies the version of CBFS. The current
version is 0x31313131 ('1111' in ASCII) which is endian-independent. 

'romsize' is the size of the ROM in bytes.  Coreboot will subtract 'size' from
0xFFFFFFFF to locate the beginning of the ROM in memory.  

'bootblocksize' is the boot block size in bytes. There is no limitation on 
the boot block size as in v3. 

'align' is the number of bytes that each component is aligned to within the
ROM.  This is used to make sure that each component is aligned correctly with
regards to the erase block sizes on the ROM - allowing one to replace a
component at runtime without disturbing the others.

'offset' is the offset of the the first CBFS component (from the start of
the ROM).  This is to allow for arbitrary space to be left at the beginning
of the ROM for things like embedded controller firmware.

'pad' rounds the header to 32 bytes and reserves a little room for later use. 

= Bootblock =
The bootblock is a mandatory component in the ROM.  It is located in the
last bootblocksize bytes of ROM space, and contains, among other things,
the location of the master header and the entry point for the loader
firmware.  The bootblock does not have a component header attached to it.


= Components =

CBFS components are placed in the ROM starting at 'offset' specified in
the master header and ending at the bootblock.  Thus the total size available
for components in the ROM is (ROM size - bootblocksize - 'offset').  Each CBFS
component is to be aligned according to the 'align' value in the header.
Thus, if a component of size 1052 is located at offset 0 with an 'align' value
of 1024, the next component will be located at offset 2048.

Each CBFS component will be indexed with a unique ASCII string name of
unlimited size. 

Each CBFS component starts with a header:

struct cbfs_file {
        char magic[8];
        unsigned int len;
        unsigned int type;
        unsigned int checksum;
        unsigned int offset;
};

'magic' is a magic value used to identify the header.  During runtime,
coreboot will scan the ROM looking for this value.  The default magic is
the string 'LARCHIVE'.

'len' is the length of the data, not including the size of the header and
the size of the name.

'type' is a 32 bit number indicating the type of data that is attached.
The data type is used in a number of ways, as detailed in the section
below.

'checksum' is a 32bit checksum of the entire component, including the
header and name.

'offset' is the start of the component data, based off the start of the header.
The difference between the size of the header and offset is the size of the
component name. 

Immediately following the header will be the name of the component, which will
null terminated and 16 byte aligned.   The following picture shows the 
structure of the header:

/--------\  <- start
| Header |
|--------|  <- sizeof(struct cbfs_file)
| Name   |
|--------|  <- 'offset'
| Data   |
| ...    |
\--------/  <- start + 'offset' + 'len' 

== Searching Alogrithm ==

To locate a specific component in the ROM, one starts at the 'offset'
specified in the CBFS master header.  For this example, the offset will
be 0.  

From that offset, the code should search for the magic string on the
component, jumping 'align' bytes each time.  So, assuming that 'align' is
16, the code will search for the string 'LARCHIVE' at offset 0, 16, 32, etc.
If the offset ever exceeds the allowable range for CBFS components, then no
component was found.

Upon recognizing a component, the software then has to search for the
specific name of the component.  This is accomplished by comparing the
desired name with the string on the component located at
offset + sizeof(struct cbfs_file).  If the string matches, then the component
has been located, otherwise the software should add 'offset' + 'len' to
the offset and resume the search for the magic value.

== Data Types ==

The 'type' member of struct cbfs_file is used to identify the content
of the component data, and is used by coreboot and other
run-time entities to make decisions about how to handle the data.

There are three component types that are essential to coreboot, and so
are defined here.

=== Stages ===

Stages are code loaded by coreboot during the boot process.  They are
essential to a successful boot.   Stages are comprised of a single blob
of binary data that is to be loaded into a particular location in memory
and executed.   The uncompressed header contains information about how
large the data is, and where it should be placed, and what additional memory
needs to be cleared.

Stages are assigned a component value of 0x10.  When coreboot sees this
component type, it knows that it should pass the data to a sub-function
that will process the stage.

The following is the format of a stage component:

/--------\
| Header |
|--------|
| Binary |
| ..     |
\--------/

The header is defined as:

struct cbfs_stage {
        unsigned int compression;
        unsigned long long entry;
        unsigned long long load;
        unsigned int len;
        unsigned int memlen;
};

'compression' is an integer defining how the data is compressed.  There
are three compression types defined by this version of the standard:
none (0x0), lzma (0x1), and nrv2b (0x02), though additional types may be
added assuming that coreboot understands how to handle the scheme.

'entry' is a 64 bit value indicating the location where  the program
counter should jump following the loading of the stage.  This should be
an absolute physical memory address.

'load' is a 64 bit value indicating where the subsequent data should be
loaded.  This should be an absolute physical memory address.

'len' is the length of the compressed data in the component.

'memlen' is the amount of memory that will be used by the component when
it is loaded.

The component data will start immediately following the header.

When coreboot loads a stage, it will first zero the memory from 'load' to
'memlen'.  It will then decompress the component data according to the
specified scheme and place it in memory starting at 'load'.  Following that,
it will jump execution to the address specified by 'entry'.
Some components are designed to execute directly from the ROM - coreboot
knows which components must do that and will act accordingly.

=== Payloads ===

Payloads are loaded by coreboot following the boot process.

Stages are assigned a component value of 0x20.  When coreboot sees this
component type, it knows that it should pass the data to a sub-function
that will process the payload.  Furthermore, other run time 
applications such as 'bayou' may easily index all available payloads
on the system by searching for the payload type.


The following is the format of a stage component:

/-----------\
| Header    |
| Segment 1 |
| Segment 2 |
| ...       |
|-----------|
| Binary    |
| ..        |
\-----------/

The header is as follows:

struct cbfs_payload {
        struct cbfs_payload_segment segments;
}

The header contains a number of segments corresponding to the segments
that need to be loaded for the payload.

The following is the structure of each segment header:

struct cbfs_payload_segment {
        unsigned int type;
        unsigned int compression;
        unsigned int offset;
        unsigned long long load_addr;
        unsigned int len;
        unsigned int mem_len;
};

'type' is the type of segment, one of the following:

PAYLOAD_SEGMENT_CODE   0x45444F43   The segment contains executable code
PAYLOAD_SEGMENT_DATA   0x41544144   The segment contains data
PAYLOAD_SEGMENT_BSS    0x20535342   The memory speicfied by the segment 
                                    should be zeroed
PAYLOAD_SEGMENT_PARAMS 0x41524150   The segment contains information for
                                    the payload
PAYLOAD_SEGMENT_ENTRY  0x52544E45   The segment contains the entry point
		       		    for the payload

'compression' is the compression scheme for the segment.  Each segment can
be independently compressed. There are three compression types defined by
this version of the standard: none (0x0), lzma (0x1), and nrv2b (0x02),
though additional types may be added assuming that coreboot understands
how to handle the scheme.

'offset' is the address of the data within the component, starting from
the component header.

'load_addr' is a 64 bit value indicating where the segment should be placed
in memory.

'len' is a 32 bit value indicating the size of the segment within the
component.

'mem_len' is the size of the data when it is placed into memory.

The data will located immediately following the last segment.

=== Option ROMS ===

The third specified component type will be Option ROMs.  Option ROMS will 
have component type '0x30'.  They will have no additional header, the 
uncompressed binary data will be located in the data portion of the 
component.

=== NULL ===

There is a 4th component type ,defined as NULL (0xFFFFFFFF).  This is
the "don't care" component type.  This can be used when the component
type is not necessary (such as when the name of the component is unique.
i.e. option_table).  It is recommended that all components be assigned a
unique type, but NULL can be used when the type does not matter.