Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 1 | # Copyright (c) 2016 Google, Inc |
| 2 | # |
| 3 | # SPDX-License-Identifier: GPL-2.0+ |
| 4 | # |
| 5 | |
| 6 | Introduction |
| 7 | ------------ |
| 8 | |
| 9 | Firmware often consists of several components which must be packaged together. |
| 10 | For example, we may have SPL, U-Boot, a device tree and an environment area |
| 11 | grouped together and placed in MMC flash. When the system starts, it must be |
| 12 | able to find these pieces. |
| 13 | |
| 14 | So far U-Boot has not provided a way to handle creating such images in a |
| 15 | general way. Each SoC does what it needs to build an image, often packing or |
| 16 | concatenating images in the U-Boot build system. |
| 17 | |
| 18 | Binman aims to provide a mechanism for building images, from simple |
| 19 | SPL + U-Boot combinations, to more complex arrangements with many parts. |
| 20 | |
| 21 | |
| 22 | What it does |
| 23 | ------------ |
| 24 | |
| 25 | Binman reads your board's device tree and finds a node which describes the |
| 26 | required image layout. It uses this to work out what to place where. The |
| 27 | output file normally contains the device tree, so it is in principle possible |
| 28 | to read an image and extract its constituent parts. |
| 29 | |
| 30 | |
| 31 | Features |
| 32 | -------- |
| 33 | |
| 34 | So far binman is pretty simple. It supports binary blobs, such as 'u-boot', |
| 35 | 'spl' and 'fdt'. It supports empty entries (such as setting to 0xff). It can |
| 36 | place entries at a fixed location in the image, or fit them together with |
| 37 | suitable padding and alignment. It provides a way to process binaries before |
| 38 | they are included, by adding a Python plug-in. The device tree is available |
| 39 | to U-Boot at run-time so that the images can be interpreted. |
| 40 | |
| 41 | Binman does not yet update the device tree with the final location of |
| 42 | everything when it is done. A simple C structure could be generated for |
| 43 | constrained environments like SPL (using dtoc) but this is also not |
| 44 | implemented. |
| 45 | |
| 46 | Binman can also support incorporating filesystems in the image if required. |
| 47 | For example x86 platforms may use CBFS in some cases. |
| 48 | |
| 49 | Binman is intended for use with U-Boot but is designed to be general enough |
| 50 | to be useful in other image-packaging situations. |
| 51 | |
| 52 | |
| 53 | Motivation |
| 54 | ---------- |
| 55 | |
| 56 | Packaging of firmware is quite a different task from building the various |
| 57 | parts. In many cases the various binaries which go into the image come from |
| 58 | separate build systems. For example, ARM Trusted Firmware is used on ARMv8 |
| 59 | devices but is not built in the U-Boot tree. If a Linux kernel is included |
| 60 | in the firmware image, it is built elsewhere. |
| 61 | |
| 62 | It is of course possible to add more and more build rules to the U-Boot |
| 63 | build system to cover these cases. It can shell out to other Makefiles and |
| 64 | build scripts. But it seems better to create a clear divide between building |
| 65 | software and packaging it. |
| 66 | |
| 67 | At present this is handled by manual instructions, different for each board, |
| 68 | on how to create images that will boot. By turning these instructions into a |
| 69 | standard format, we can support making valid images for any board without |
| 70 | manual effort, lots of READMEs, etc. |
| 71 | |
| 72 | Benefits: |
| 73 | - Each binary can have its own build system and tool chain without creating |
| 74 | any dependencies between them |
| 75 | - Avoids the need for a single-shot build: individual parts can be updated |
| 76 | and brought in as needed |
| 77 | - Provides for a standard image description available in the build and at |
| 78 | run-time |
| 79 | - SoC-specific image-signing tools can be accomodated |
| 80 | - Avoids cluttering the U-Boot build system with image-building code |
| 81 | - The image description is automatically available at run-time in U-Boot, |
| 82 | SPL. It can be made available to other software also |
| 83 | - The image description is easily readable (it's a text file in device-tree |
| 84 | format) and permits flexible packing of binaries |
| 85 | |
| 86 | |
| 87 | Terminology |
| 88 | ----------- |
| 89 | |
| 90 | Binman uses the following terms: |
| 91 | |
| 92 | - image - an output file containing a firmware image |
| 93 | - binary - an input binary that goes into the image |
| 94 | |
| 95 | |
| 96 | Relationship to FIT |
| 97 | ------------------- |
| 98 | |
| 99 | FIT is U-Boot's official image format. It supports multiple binaries with |
| 100 | load / execution addresses, compression. It also supports verification |
| 101 | through hashing and RSA signatures. |
| 102 | |
| 103 | FIT was originally designed to support booting a Linux kernel (with an |
| 104 | optional ramdisk) and device tree chosen from various options in the FIT. |
| 105 | Now that U-Boot supports configuration via device tree, it is possible to |
| 106 | load U-Boot from a FIT, with the device tree chosen by SPL. |
| 107 | |
| 108 | Binman considers FIT to be one of the binaries it can place in the image. |
| 109 | |
| 110 | Where possible it is best to put as much as possible in the FIT, with binman |
| 111 | used to deal with cases not covered by FIT. Examples include initial |
| 112 | execution (since FIT itself does not have an executable header) and dealing |
| 113 | with device boundaries, such as the read-only/read-write separation in SPI |
| 114 | flash. |
| 115 | |
| 116 | For U-Boot, binman should not be used to create ad-hoc images in place of |
| 117 | FIT. |
| 118 | |
| 119 | |
| 120 | Relationship to mkimage |
| 121 | ----------------------- |
| 122 | |
| 123 | The mkimage tool provides a means to create a FIT. Traditionally it has |
| 124 | needed an image description file: a device tree, like binman, but in a |
| 125 | different format. More recently it has started to support a '-f auto' mode |
| 126 | which can generate that automatically. |
| 127 | |
| 128 | More relevant to binman, mkimage also permits creation of many SoC-specific |
| 129 | image types. These can be listed by running 'mkimage -T list'. Examples |
| 130 | include 'rksd', the Rockchip SD/MMC boot format. The mkimage tool is often |
| 131 | called from the U-Boot build system for this reason. |
| 132 | |
| 133 | Binman considers the output files created by mkimage to be binary blobs |
| 134 | which it can place in an image. Binman does not replace the mkimage tool or |
| 135 | this purpose. It would be possible in some situtions to create a new entry |
| 136 | type for the images in mkimage, but this would not add functionality. It |
| 137 | seems better to use the mkiamge tool to generate binaries and avoid blurring |
| 138 | the boundaries between building input files (mkimage) and packaging then |
| 139 | into a final image (binman). |
| 140 | |
| 141 | |
| 142 | Example use of binman in U-Boot |
| 143 | ------------------------------- |
| 144 | |
| 145 | Binman aims to replace some of the ad-hoc image creation in the U-Boot |
| 146 | build system. |
| 147 | |
| 148 | Consider sunxi. It has the following steps: |
| 149 | |
| 150 | 1. It uses a custom mksunxiboot tool to build an SPL image called |
| 151 | sunxi-spl.bin. This should probably move into mkimage. |
| 152 | |
| 153 | 2. It uses mkimage to package U-Boot into a legacy image file (so that it can |
| 154 | hold the load and execution address) called u-boot.img. |
| 155 | |
| 156 | 3. It builds a final output image called u-boot-sunxi-with-spl.bin which |
| 157 | consists of sunxi-spl.bin, some padding and u-boot.img. |
| 158 | |
| 159 | Binman is intended to replace the last step. The U-Boot build system builds |
| 160 | u-boot.bin and sunxi-spl.bin. Binman can then take over creation of |
| 161 | sunxi-spl.bin (by calling mksunxiboot, or hopefully one day mkimage). In any |
| 162 | case, it would then create the image from the component parts. |
| 163 | |
| 164 | This simplifies the U-Boot Makefile somewhat, since various pieces of logic |
| 165 | can be replaced by a call to binman. |
| 166 | |
| 167 | |
| 168 | Example use of binman for x86 |
| 169 | ----------------------------- |
| 170 | |
| 171 | In most cases x86 images have a lot of binary blobs, 'black-box' code |
| 172 | provided by Intel which must be run for the platform to work. Typically |
| 173 | these blobs are not relocatable and must be placed at fixed areas in the |
| 174 | firmare image. |
| 175 | |
| 176 | Currently this is handled by ifdtool, which places microcode, FSP, MRC, VGA |
| 177 | BIOS, reference code and Intel ME binaries into a u-boot.rom file. |
| 178 | |
| 179 | Binman is intended to replace all of this, with ifdtool left to handle only |
| 180 | the configuration of the Intel-format descriptor. |
| 181 | |
| 182 | |
| 183 | Running binman |
| 184 | -------------- |
| 185 | |
| 186 | Type: |
| 187 | |
| 188 | binman -b <board_name> |
| 189 | |
| 190 | to build an image for a board. The board name is the same name used when |
| 191 | configuring U-Boot (e.g. for sandbox_defconfig the board name is 'sandbox'). |
| 192 | Binman assumes that the input files for the build are in ../b/<board_name>. |
| 193 | |
| 194 | Or you can specify this explicitly: |
| 195 | |
| 196 | binman -I <build_path> |
| 197 | |
| 198 | where <build_path> is the build directory containing the output of the U-Boot |
| 199 | build. |
| 200 | |
| 201 | (Future work will make this more configurable) |
| 202 | |
| 203 | In either case, binman picks up the device tree file (u-boot.dtb) and looks |
| 204 | for its instructions in the 'binman' node. |
| 205 | |
| 206 | Binman has a few other options which you can see by running 'binman -h'. |
| 207 | |
| 208 | |
Simon Glass | 4b94ac9 | 2017-11-12 21:52:06 -0700 | [diff] [blame] | 209 | Enabling binman for a board |
| 210 | --------------------------- |
| 211 | |
| 212 | At present binman is invoked from a rule in the main Makefile. Typically you |
| 213 | will have a rule like: |
| 214 | |
| 215 | ifneq ($(CONFIG_ARCH_<something>),) |
| 216 | u-boot-<your_suffix>.bin: <input_file_1> <input_file_2> checkbinman FORCE |
| 217 | $(call if_changed,binman) |
| 218 | endif |
| 219 | |
| 220 | This assumes that u-boot-<your_suffix>.bin is a target, and is the final file |
| 221 | that you need to produce. You can make it a target by adding it to ALL-y |
| 222 | either in the main Makefile or in a config.mk file in your arch subdirectory. |
| 223 | |
| 224 | Once binman is executed it will pick up its instructions from a device-tree |
| 225 | file, typically <soc>-u-boot.dtsi, where <soc> is your CONFIG_SYS_SOC value. |
| 226 | You can use other, more specific CONFIG options - see 'Automatic .dtsi |
| 227 | inclusion' below. |
| 228 | |
| 229 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 230 | Image description format |
| 231 | ------------------------ |
| 232 | |
| 233 | The binman node is called 'binman'. An example image description is shown |
| 234 | below: |
| 235 | |
| 236 | binman { |
| 237 | filename = "u-boot-sunxi-with-spl.bin"; |
| 238 | pad-byte = <0xff>; |
| 239 | blob { |
| 240 | filename = "spl/sunxi-spl.bin"; |
| 241 | }; |
| 242 | u-boot { |
| 243 | pos = <CONFIG_SPL_PAD_TO>; |
| 244 | }; |
| 245 | }; |
| 246 | |
| 247 | |
| 248 | This requests binman to create an image file called u-boot-sunxi-with-spl.bin |
| 249 | consisting of a specially formatted SPL (spl/sunxi-spl.bin, built by the |
| 250 | normal U-Boot Makefile), some 0xff padding, and a U-Boot legacy image. The |
| 251 | padding comes from the fact that the second binary is placed at |
| 252 | CONFIG_SPL_PAD_TO. If that line were omitted then the U-Boot binary would |
| 253 | immediately follow the SPL binary. |
| 254 | |
| 255 | The binman node describes an image. The sub-nodes describe entries in the |
| 256 | image. Each entry represents a region within the overall image. The name of |
| 257 | the entry (blob, u-boot) tells binman what to put there. For 'blob' we must |
| 258 | provide a filename. For 'u-boot', binman knows that this means 'u-boot.bin'. |
| 259 | |
| 260 | Entries are normally placed into the image sequentially, one after the other. |
| 261 | The image size is the total size of all entries. As you can see, you can |
| 262 | specify the start position of an entry using the 'pos' property. |
| 263 | |
| 264 | Note that due to a device tree requirement, all entries must have a unique |
| 265 | name. If you want to put the same binary in the image multiple times, you can |
| 266 | use any unique name, with the 'type' property providing the type. |
| 267 | |
| 268 | The attributes supported for entries are described below. |
| 269 | |
| 270 | pos: |
| 271 | This sets the position of an entry within the image. The first byte |
| 272 | of the image is normally at position 0. If 'pos' is not provided, |
| 273 | binman sets it to the end of the previous region, or the start of |
| 274 | the image's entry area (normally 0) if there is no previous region. |
| 275 | |
| 276 | align: |
| 277 | This sets the alignment of the entry. The entry position is adjusted |
| 278 | so that the entry starts on an aligned boundary within the image. For |
| 279 | example 'align = <16>' means that the entry will start on a 16-byte |
| 280 | boundary. Alignment shold be a power of 2. If 'align' is not |
| 281 | provided, no alignment is performed. |
| 282 | |
| 283 | size: |
| 284 | This sets the size of the entry. The contents will be padded out to |
| 285 | this size. If this is not provided, it will be set to the size of the |
| 286 | contents. |
| 287 | |
| 288 | pad-before: |
| 289 | Padding before the contents of the entry. Normally this is 0, meaning |
| 290 | that the contents start at the beginning of the entry. This can be |
| 291 | offset the entry contents a little. Defaults to 0. |
| 292 | |
| 293 | pad-after: |
| 294 | Padding after the contents of the entry. Normally this is 0, meaning |
| 295 | that the entry ends at the last byte of content (unless adjusted by |
| 296 | other properties). This allows room to be created in the image for |
| 297 | this entry to expand later. Defaults to 0. |
| 298 | |
| 299 | align-size: |
| 300 | This sets the alignment of the entry size. For example, to ensure |
| 301 | that the size of an entry is a multiple of 64 bytes, set this to 64. |
| 302 | If 'align-size' is not provided, no alignment is performed. |
| 303 | |
| 304 | align-end: |
| 305 | This sets the alignment of the end of an entry. Some entries require |
| 306 | that they end on an alignment boundary, regardless of where they |
| 307 | start. If 'align-end' is not provided, no alignment is performed. |
| 308 | |
| 309 | Note: This is not yet implemented in binman. |
| 310 | |
| 311 | filename: |
| 312 | For 'blob' types this provides the filename containing the binary to |
| 313 | put into the entry. If binman knows about the entry type (like |
| 314 | u-boot-bin), then there is no need to specify this. |
| 315 | |
| 316 | type: |
| 317 | Sets the type of an entry. This defaults to the entry name, but it is |
| 318 | possible to use any name, and then add (for example) 'type = "u-boot"' |
| 319 | to specify the type. |
| 320 | |
| 321 | |
| 322 | The attributes supported for images are described below. Several are similar |
| 323 | to those for entries. |
| 324 | |
| 325 | size: |
| 326 | Sets the image size in bytes, for example 'size = <0x100000>' for a |
| 327 | 1MB image. |
| 328 | |
| 329 | align-size: |
| 330 | This sets the alignment of the image size. For example, to ensure |
| 331 | that the image ends on a 512-byte boundary, use 'align-size = <512>'. |
| 332 | If 'align-size' is not provided, no alignment is performed. |
| 333 | |
| 334 | pad-before: |
| 335 | This sets the padding before the image entries. The first entry will |
| 336 | be positionad after the padding. This defaults to 0. |
| 337 | |
| 338 | pad-after: |
| 339 | This sets the padding after the image entries. The padding will be |
| 340 | placed after the last entry. This defaults to 0. |
| 341 | |
| 342 | pad-byte: |
| 343 | This specifies the pad byte to use when padding in the image. It |
| 344 | defaults to 0. To use 0xff, you would add 'pad-byte = <0xff>'. |
| 345 | |
| 346 | filename: |
| 347 | This specifies the image filename. It defaults to 'image.bin'. |
| 348 | |
| 349 | sort-by-pos: |
| 350 | This causes binman to reorder the entries as needed to make sure they |
| 351 | are in increasing positional order. This can be used when your entry |
| 352 | order may not match the positional order. A common situation is where |
| 353 | the 'pos' properties are set by CONFIG options, so their ordering is |
| 354 | not known a priori. |
| 355 | |
| 356 | This is a boolean property so needs no value. To enable it, add a |
| 357 | line 'sort-by-pos;' to your description. |
| 358 | |
| 359 | multiple-images: |
| 360 | Normally only a single image is generated. To create more than one |
| 361 | image, put this property in the binman node. For example, this will |
| 362 | create image1.bin containing u-boot.bin, and image2.bin containing |
| 363 | both spl/u-boot-spl.bin and u-boot.bin: |
| 364 | |
| 365 | binman { |
| 366 | multiple-images; |
| 367 | image1 { |
| 368 | u-boot { |
| 369 | }; |
| 370 | }; |
| 371 | |
| 372 | image2 { |
| 373 | spl { |
| 374 | }; |
| 375 | u-boot { |
| 376 | }; |
| 377 | }; |
| 378 | }; |
| 379 | |
| 380 | end-at-4gb: |
| 381 | For x86 machines the ROM positions start just before 4GB and extend |
| 382 | up so that the image finished at the 4GB boundary. This boolean |
| 383 | option can be enabled to support this. The image size must be |
| 384 | provided so that binman knows when the image should start. For an |
| 385 | 8MB ROM, the position of the first entry would be 0xfff80000 with |
| 386 | this option, instead of 0 without this option. |
| 387 | |
| 388 | |
| 389 | Examples of the above options can be found in the tests. See the |
| 390 | tools/binman/test directory. |
| 391 | |
| 392 | |
Simon Glass | 7223245 | 2016-11-25 20:15:53 -0700 | [diff] [blame] | 393 | Special properties |
| 394 | ------------------ |
| 395 | |
| 396 | Some entries support special properties, documented here: |
| 397 | |
| 398 | u-boot-with-ucode-ptr: |
| 399 | optional-ucode: boolean property to make microcode optional. If the |
| 400 | u-boot.bin image does not include microcode, no error will |
| 401 | be generated. |
| 402 | |
| 403 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 404 | Order of image creation |
| 405 | ----------------------- |
| 406 | |
| 407 | Image creation proceeds in the following order, for each entry in the image. |
| 408 | |
| 409 | 1. GetEntryContents() - the contents of each entry are obtained, normally by |
| 410 | reading from a file. This calls the Entry.ObtainContents() to read the |
| 411 | contents. The default version of Entry.ObtainContents() calls |
| 412 | Entry.GetDefaultFilename() and then reads that file. So a common mechanism |
| 413 | to select a file to read is to override that function in the subclass. The |
| 414 | functions must return True when they have read the contents. Binman will |
| 415 | retry calling the functions a few times if False is returned, allowing |
| 416 | dependencies between the contents of different entries. |
| 417 | |
| 418 | 2. GetEntryPositions() - calls Entry.GetPositions() for each entry. This can |
| 419 | return a dict containing entries that need updating. The key should be the |
| 420 | entry name and the value is a tuple (pos, size). This allows an entry to |
| 421 | provide the position and size for other entries. The default implementation |
| 422 | of GetEntryPositions() returns {}. |
| 423 | |
| 424 | 3. PackEntries() - calls Entry.Pack() which figures out the position and |
| 425 | size of an entry. The 'current' image position is passed in, and the function |
| 426 | returns the position immediately after the entry being packed. The default |
| 427 | implementation of Pack() is usually sufficient. |
| 428 | |
| 429 | 4. CheckSize() - checks that the contents of all the entries fits within |
| 430 | the image size. If the image does not have a defined size, the size is set |
| 431 | large enough to hold all the entries. |
| 432 | |
| 433 | 5. CheckEntries() - checks that the entries do not overlap, nor extend |
| 434 | outside the image. |
| 435 | |
| 436 | 6. ProcessEntryContents() - this calls Entry.ProcessContents() on each entry. |
| 437 | The default implementatoin does nothing. This can be overriden to adjust the |
| 438 | contents of an entry in some way. For example, it would be possible to create |
| 439 | an entry containing a hash of the contents of some other entries. At this |
| 440 | stage the position and size of entries should not be adjusted. |
| 441 | |
Simon Glass | be83bc7 | 2017-11-13 18:55:05 -0700 | [diff] [blame] | 442 | 6. WriteEntryInfo() |
| 443 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 444 | 7. BuildImage() - builds the image and writes it to a file. This is the final |
| 445 | step. |
| 446 | |
| 447 | |
Simon Glass | 52debad | 2016-11-25 20:15:59 -0700 | [diff] [blame] | 448 | Automatic .dtsi inclusion |
| 449 | ------------------------- |
| 450 | |
| 451 | It is sometimes inconvenient to add a 'binman' node to the .dts file for each |
| 452 | board. This can be done by using #include to bring in a common file. Another |
| 453 | approach supported by the U-Boot build system is to automatically include |
| 454 | a common header. You can then put the binman node (and anything else that is |
| 455 | specific to U-Boot, such as u-boot,dm-pre-reloc properies) in that header |
| 456 | file. |
| 457 | |
| 458 | Binman will search for the following files in arch/<arch>/dts: |
| 459 | |
| 460 | <dts>-u-boot.dtsi where <dts> is the base name of the .dts file |
| 461 | <CONFIG_SYS_SOC>-u-boot.dtsi |
| 462 | <CONFIG_SYS_CPU>-u-boot.dtsi |
| 463 | <CONFIG_SYS_VENDOR>-u-boot.dtsi |
| 464 | u-boot.dtsi |
| 465 | |
| 466 | U-Boot will only use the first one that it finds. If you need to include a |
| 467 | more general file you can do that from the more specific file using #include. |
| 468 | If you are having trouble figuring out what is going on, you can uncomment |
| 469 | the 'warning' line in scripts/Makefile.lib to see what it has found: |
| 470 | |
| 471 | # Uncomment for debugging |
Simon Glass | 2eee32b | 2017-11-12 21:52:05 -0700 | [diff] [blame] | 472 | # This shows all the files that were considered and the one that we chose. |
| 473 | # u_boot_dtsi_options_debug = $(u_boot_dtsi_options_raw) |
Simon Glass | 52debad | 2016-11-25 20:15:59 -0700 | [diff] [blame] | 474 | |
Simon Glass | be83bc7 | 2017-11-13 18:55:05 -0700 | [diff] [blame] | 475 | |
| 476 | Access to binman entry positions at run time |
| 477 | -------------------------------------------- |
| 478 | |
| 479 | Binman assembles images and determines where each entry is placed in the image. |
| 480 | This information may be useful to U-Boot at run time. For example, in SPL it |
| 481 | is useful to be able to find the location of U-Boot so that it can be executed |
| 482 | when SPL is finished. |
| 483 | |
| 484 | Binman allows you to declare symbols in the SPL image which are filled in |
| 485 | with their correct values during the build. For example: |
| 486 | |
| 487 | binman_sym_declare(ulong, u_boot_any, pos); |
| 488 | |
| 489 | declares a ulong value which will be assigned to the position of any U-Boot |
| 490 | image (u-boot.bin, u-boot.img, u-boot-nodtb.bin) that is present in the image. |
| 491 | You can access this value with something like: |
| 492 | |
| 493 | ulong u_boot_pos = binman_sym(ulong, u_boot_any, pos); |
| 494 | |
| 495 | Thus u_boot_pos will be set to the position of U-Boot in memory, assuming that |
| 496 | the whole image has been loaded, or is available in flash. You can then jump to |
| 497 | that address to start U-Boot. |
| 498 | |
| 499 | At present this feature is only supported in SPL. In principle it is possible |
| 500 | to fill in such symbols in U-Boot proper, as well. |
| 501 | |
Simon Glass | 52debad | 2016-11-25 20:15:59 -0700 | [diff] [blame] | 502 | |
| 503 | Code coverage |
| 504 | ------------- |
| 505 | |
| 506 | Binman is a critical tool and is designed to be very testable. Entry |
| 507 | implementations target 100% test coverage. Run 'binman -T' to check this. |
| 508 | |
| 509 | To enable Python test coverage on Debian-type distributions (e.g. Ubuntu): |
| 510 | |
| 511 | $ sudo apt-get install python-pip python-pytest |
| 512 | $ sudo pip install coverage |
| 513 | |
| 514 | |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 515 | Advanced Features / Technical docs |
| 516 | ---------------------------------- |
| 517 | |
| 518 | The behaviour of entries is defined by the Entry class. All other entries are |
| 519 | a subclass of this. An important subclass is Entry_blob which takes binary |
| 520 | data from a file and places it in the entry. In fact most entry types are |
| 521 | subclasses of Entry_blob. |
| 522 | |
| 523 | Each entry type is a separate file in the tools/binman/etype directory. Each |
| 524 | file contains a class called Entry_<type> where <type> is the entry type. |
| 525 | New entry types can be supported by adding new files in that directory. |
| 526 | These will automatically be detected by binman when needed. |
| 527 | |
| 528 | Entry properties are documented in entry.py. The entry subclasses are free |
| 529 | to change the values of properties to support special behaviour. For example, |
| 530 | when Entry_blob loads a file, it sets content_size to the size of the file. |
| 531 | Entry classes can adjust other entries. For example, an entry that knows |
| 532 | where other entries should be positioned can set up those entries' positions |
| 533 | so they don't need to be set in the binman decription. It can also adjust |
| 534 | entry contents. |
| 535 | |
| 536 | Most of the time such essoteric behaviour is not needed, but it can be |
| 537 | essential for complex images. |
| 538 | |
| 539 | |
| 540 | History / Credits |
| 541 | ----------------- |
| 542 | |
| 543 | Binman takes a lot of inspiration from a Chrome OS tool called |
| 544 | 'cros_bundle_firmware', which I wrote some years ago. That tool was based on |
| 545 | a reasonably simple and sound design but has expanded greatly over the |
| 546 | years. In particular its handling of x86 images is convoluted. |
| 547 | |
| 548 | Quite a few lessons have been learned which are hopefully be applied here. |
| 549 | |
| 550 | |
| 551 | Design notes |
| 552 | ------------ |
| 553 | |
| 554 | On the face of it, a tool to create firmware images should be fairly simple: |
| 555 | just find all the input binaries and place them at the right place in the |
| 556 | image. The difficulty comes from the wide variety of input types (simple |
| 557 | flat binaries containing code, packaged data with various headers), packing |
| 558 | requirments (alignment, spacing, device boundaries) and other required |
| 559 | features such as hierarchical images. |
| 560 | |
| 561 | The design challenge is to make it easy to create simple images, while |
| 562 | allowing the more complex cases to be supported. For example, for most |
| 563 | images we don't much care exactly where each binary ends up, so we should |
| 564 | not have to specify that unnecessarily. |
| 565 | |
| 566 | New entry types should aim to provide simple usage where possible. If new |
| 567 | core features are needed, they can be added in the Entry base class. |
| 568 | |
| 569 | |
| 570 | To do |
| 571 | ----- |
| 572 | |
| 573 | Some ideas: |
| 574 | - Fill out the device tree to include the final position and size of each |
Simon Glass | be83bc7 | 2017-11-13 18:55:05 -0700 | [diff] [blame] | 575 | entry (since the input file may not always specify these). See also |
| 576 | 'Access to binman entry positions at run time' above |
Simon Glass | 2574ef6 | 2016-11-25 20:15:51 -0700 | [diff] [blame] | 577 | - Use of-platdata to make the information available to code that is unable |
| 578 | to use device tree (such as a very small SPL image) |
| 579 | - Write an image map to a text file |
| 580 | - Allow easy building of images by specifying just the board name |
| 581 | - Produce a full Python binding for libfdt (for upstream) |
| 582 | - Add an option to decode an image into the constituent binaries |
| 583 | - Suppoort hierarchical images (packing of binaries into another binary |
| 584 | which is then placed in the image) |
| 585 | - Support building an image for a board (-b) more completely, with a |
| 586 | configurable build directory |
| 587 | - Consider making binman work with buildman, although if it is used in the |
| 588 | Makefile, this will be automatic |
| 589 | - Implement align-end |
| 590 | |
| 591 | -- |
| 592 | Simon Glass <sjg@chromium.org> |
| 593 | 7/7/2016 |