diff options
author | Simon Glass | 2021-10-14 12:47:54 -0600 |
---|---|---|
committer | Tom Rini | 2021-11-11 19:01:56 -0500 |
commit | 19a91f2464a89402a925fd4a2d8b7e28c804c7cc (patch) | |
tree | 35d48b06f479acac201447cb32fea47a78c87eb5 /common | |
parent | 1e72ad6b387c599f477f83cda67ab525c089a9b0 (diff) |
Create a new boot/ directory
Quite a lot of the code in common/relates to booting and images. Before
adding more it seems like a good time to move the code into its own
directory.
Most files with 'boot' or 'image' in them are moved, except:
- autoboot.c which relates to U-Boot automatically running a script
- bootstage.c which relates to U-Boot timing
Drop the removal of boot* files from the output directory, since this
interfers with the symlinks created by tools and there does not appear
to be any such file from my brief testing.
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Artem Lapkin <email2tema@gmail.com>
Tested-by: Artem Lapkin <email2tema@gmail.com>
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 2 | ||||
-rw-r--r-- | common/Kconfig.boot | 1036 | ||||
-rw-r--r-- | common/Makefile | 22 | ||||
-rw-r--r-- | common/android_ab.c | 305 | ||||
-rw-r--r-- | common/boot_fit.c | 80 | ||||
-rw-r--r-- | common/bootm.c | 1038 | ||||
-rw-r--r-- | common/bootm_os.c | 653 | ||||
-rw-r--r-- | common/bootretry.c | 60 | ||||
-rw-r--r-- | common/common_fit.c | 86 | ||||
-rw-r--r-- | common/fdt_region.c | 671 | ||||
-rw-r--r-- | common/image-android-dt.c | 157 | ||||
-rw-r--r-- | common/image-android.c | 539 | ||||
-rw-r--r-- | common/image-board.c | 956 | ||||
-rw-r--r-- | common/image-cipher.c | 176 | ||||
-rw-r--r-- | common/image-fdt.c | 666 | ||||
-rw-r--r-- | common/image-fit-sig.c | 486 | ||||
-rw-r--r-- | common/image-fit.c | 2448 | ||||
-rw-r--r-- | common/image-host.c | 27 | ||||
-rw-r--r-- | common/image-sig.c | 136 | ||||
-rw-r--r-- | common/image.c | 738 |
20 files changed, 0 insertions, 10282 deletions
diff --git a/common/Kconfig b/common/Kconfig index d6f77ab7b9c..fdcf4536d0f 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1,5 +1,3 @@ -source "common/Kconfig.boot" - menu "Console" config MENU diff --git a/common/Kconfig.boot b/common/Kconfig.boot deleted file mode 100644 index a8d4be23a97..00000000000 --- a/common/Kconfig.boot +++ /dev/null @@ -1,1036 +0,0 @@ -menu "Boot options" - -menu "Boot images" - -config ANDROID_BOOT_IMAGE - bool "Enable support for Android Boot Images" - default y if FASTBOOT - help - This enables support for booting images which use the Android - image format header. - -config FIT - bool "Support Flattened Image Tree" - select HASH - select MD5 - select SHA1 - imply SHA256 - help - This option allows you to boot the new uImage structure, - Flattened Image Tree. FIT is formally a FDT, which can include - images of various types (kernel, FDT blob, ramdisk, etc.) - in a single blob. To boot this new uImage structure, - pass the address of the blob to the "bootm" command. - FIT is very flexible, supporting compression, multiple images, - multiple configurations, verification through hashing and also - verified boot (secure boot using RSA). - -if FIT - -config FIT_EXTERNAL_OFFSET - hex "FIT external data offset" - default 0x0 - help - This specifies a data offset in fit image. - The offset is from data payload offset to the beginning of - fit image header. When specifies a offset, specific data - could be put in the hole between data payload and fit image - header, such as CSF data on i.MX platform. - -config FIT_FULL_CHECK - bool "Do a full check of the FIT before using it" - default y - help - Enable this do a full check of the FIT to make sure it is valid. This - helps to protect against carefully crafted FITs which take advantage - of bugs or omissions in the code. This includes a bad structure, - multiple root nodes and the like. - -config FIT_SIGNATURE - bool "Enable signature verification of FIT uImages" - depends on DM - select HASH - imply RSA - imply RSA_VERIFY - select IMAGE_SIGN_INFO - select FIT_FULL_CHECK - help - This option enables signature verification of FIT uImages, - using a hash signed and verified using RSA. If - CONFIG_SHA_PROG_HW_ACCEL is defined, i.e support for progressive - hashing is available using hardware, then the RSA library will use - it. See doc/uImage.FIT/signature.txt for more details. - - WARNING: When relying on signed FIT images with a required signature - check the legacy image format is disabled by default, so that - unsigned images cannot be loaded. If a board needs the legacy image - format support in this case, enable it using - CONFIG_LEGACY_IMAGE_FORMAT. - -config FIT_SIGNATURE_MAX_SIZE - hex "Max size of signed FIT structures" - depends on FIT_SIGNATURE - default 0x10000000 - help - This option sets a max size in bytes for verified FIT uImages. - A sane value of 256MB protects corrupted DTB structures from overlapping - device memory. Assure this size does not extend past expected storage - space. - -config FIT_RSASSA_PSS - bool "Support rsassa-pss signature scheme of FIT image contents" - depends on FIT_SIGNATURE - help - Enable this to support the pss padding algorithm as described - in the rfc8017 (https://tools.ietf.org/html/rfc8017). - -config FIT_CIPHER - bool "Enable ciphering data in a FIT uImages" - depends on DM - select AES - help - Enable the feature of data ciphering/unciphering in the tool mkimage - and in the u-boot support of the FIT image. - -config FIT_VERBOSE - bool "Show verbose messages when FIT images fail" - help - Generally a system will have valid FIT images so debug messages - are a waste of code space. If you are debugging your images then - you can enable this option to get more verbose information about - failures. - -config FIT_BEST_MATCH - bool "Select the best match for the kernel device tree" - help - When no configuration is explicitly selected, default to the - one whose fdt's compatibility field best matches that of - U-Boot itself. A match is considered "best" if it matches the - most specific compatibility entry of U-Boot's fdt's root node. - The order of entries in the configuration's fdt is ignored. - -config FIT_IMAGE_POST_PROCESS - bool "Enable post-processing of FIT artifacts after loading by U-Boot" - depends on TI_SECURE_DEVICE || SOCFPGA_SECURE_VAB_AUTH - help - Allows doing any sort of manipulation to blobs after they got extracted - from FIT images like stripping off headers or modifying the size of the - blob, verification, authentication, decryption etc. in a platform or - board specific way. In order to use this feature a platform or board- - specific implementation of board_fit_image_post_process() must be - provided. Also, anything done during this post-processing step would - need to be comprehended in how the images were prepared before being - injected into the FIT creation (i.e. the blobs would have been pre- - processed before being added to the FIT image). - -config FIT_PRINT - bool "Support FIT printing" - default y - help - Support printing the content of the fitImage in a verbose manner. - -if SPL - -config SPL_FIT - bool "Support Flattened Image Tree within SPL" - depends on SPL - select SPL_HASH - select SPL_OF_LIBFDT - -config SPL_FIT_PRINT - bool "Support FIT printing within SPL" - depends on SPL_FIT - help - Support printing the content of the fitImage in a verbose manner in SPL. - -config SPL_FIT_FULL_CHECK - bool "Do a full check of the FIT before using it" - help - Enable this do a full check of the FIT to make sure it is valid. This - helps to protect against carefully crafted FITs which take advantage - of bugs or omissions in the code. This includes a bad structure, - multiple root nodes and the like. - - -config SPL_FIT_SIGNATURE - bool "Enable signature verification of FIT firmware within SPL" - depends on SPL_DM - depends on SPL_LOAD_FIT || SPL_LOAD_FIT_FULL - select FIT_SIGNATURE - select SPL_FIT - select SPL_CRYPTO - select SPL_HASH - imply SPL_RSA - imply SPL_RSA_VERIFY - select SPL_IMAGE_SIGN_INFO - select SPL_FIT_FULL_CHECK - -config SPL_FIT_SIGNATURE_MAX_SIZE - hex "Max size of signed FIT structures in SPL" - depends on SPL_FIT_SIGNATURE - default 0x10000000 - help - This option sets a max size in bytes for verified FIT uImages. - A sane value of 256MB protects corrupted DTB structures from overlapping - device memory. Assure this size does not extend past expected storage - space. - -config SPL_FIT_RSASSA_PSS - bool "Support rsassa-pss signature scheme of FIT image contents in SPL" - depends on SPL_FIT_SIGNATURE - help - Enable this to support the pss padding algorithm as described - in the rfc8017 (https://tools.ietf.org/html/rfc8017) in SPL. - -config SPL_LOAD_FIT - bool "Enable SPL loading U-Boot as a FIT (basic fitImage features)" - select SPL_FIT - help - Normally with the SPL framework a legacy image is generated as part - of the build. This contains U-Boot along with information as to - where it should be loaded. This option instead enables generation - of a FIT (Flat Image Tree) which provides more flexibility. In - particular it can handle selecting from multiple device tree - and passing the correct one to U-Boot. - - This path has the following limitations: - - 1. "loadables" images, other than FDTs, which do not have a "load" - property will not be loaded. This limitation also applies to FPGA - images with the correct "compatible" string. - 2. For FPGA images, only the "compatible" = "u-boot,fpga-legacy" - loading method is supported. - 3. FDTs are only loaded for images with an "os" property of "u-boot". - "linux" images are also supported with Falcon boot mode. - -config SPL_LOAD_FIT_ADDRESS - hex "load address of fit image" - depends on SPL_LOAD_FIT - default 0x0 - help - Specify the load address of the fit image that will be loaded - by SPL. - -config SPL_LOAD_FIT_APPLY_OVERLAY - bool "Enable SPL applying DT overlays from FIT" - depends on SPL_LOAD_FIT - select OF_LIBFDT_OVERLAY - help - The device tree is loaded from the FIT image. Allow the SPL is to - also load device-tree overlays from the FIT image an apply them - over the device tree. - -config SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ - depends on SPL_LOAD_FIT_APPLY_OVERLAY - default 0x10000 - hex "size of temporary buffer used to load the overlays" - help - The size of the area where the overlays will be loaded and - uncompress. Must be at least as large as biggest overlay - (uncompressed) - -config SPL_LOAD_FIT_FULL - bool "Enable SPL loading U-Boot as a FIT (full fitImage features)" - select SPL_FIT - help - Normally with the SPL framework a legacy image is generated as part - of the build. This contains U-Boot along with information as to - where it should be loaded. This option instead enables generation - of a FIT (Flat Image Tree) which provides more flexibility. In - particular it can handle selecting from multiple device tree - and passing the correct one to U-Boot. - -config SPL_FIT_IMAGE_POST_PROCESS - bool "Enable post-processing of FIT artifacts after loading by the SPL" - depends on SPL_LOAD_FIT - help - Allows doing any sort of manipulation to blobs after they got extracted - from the U-Boot FIT image like stripping off headers or modifying the - size of the blob, verification, authentication, decryption etc. in a - platform or board specific way. In order to use this feature a platform - or board-specific implementation of board_fit_image_post_process() must - be provided. Also, anything done during this post-processing step would - need to be comprehended in how the images were prepared before being - injected into the FIT creation (i.e. the blobs would have been pre- - processed before being added to the FIT image). - -config SPL_FIT_SOURCE - string ".its source file for U-Boot FIT image" - depends on SPL_FIT - help - Specifies a (platform specific) FIT source file to generate the - U-Boot FIT image. This could specify further image to load and/or - execute. - -config USE_SPL_FIT_GENERATOR - bool "Use a script to generate the .its script" - default y if SPL_FIT && (!ARCH_SUNXI && !RISCV) - -config SPL_FIT_GENERATOR - string ".its file generator script for U-Boot FIT image" - depends on USE_SPL_FIT_GENERATOR - default "arch/arm/mach-rockchip/make_fit_atf.py" if SPL_LOAD_FIT && ARCH_ROCKCHIP - default "arch/arm/mach-zynqmp/mkimage_fit_atf.sh" if SPL_LOAD_FIT && ARCH_ZYNQMP - help - Specifies a (platform specific) script file to generate the FIT - source file used to build the U-Boot FIT image file. This gets - passed a list of supported device tree file stub names to - include in the generated image. - -endif # SPL - -endif # FIT - -config LEGACY_IMAGE_FORMAT - bool "Enable support for the legacy image format" - default y if !FIT_SIGNATURE - help - This option enables the legacy image format. It is enabled by - default for backward compatibility, unless FIT_SIGNATURE is - set where it is disabled so that unsigned images cannot be - loaded. If a board needs the legacy image format support in this - case, enable it here. - -config SUPPORT_RAW_INITRD - bool "Enable raw initrd images" - help - Note, defining the SUPPORT_RAW_INITRD allows user to supply - kernel with raw initrd images. The syntax is slightly different, the - address of the initrd must be augmented by it's size, in the following - format: "<initrd address>:<initrd size>". - -config OF_BOARD_SETUP - bool "Set up board-specific details in device tree before boot" - depends on OF_LIBFDT - help - This causes U-Boot to call ft_board_setup() before booting into - the Operating System. This function can set up various - board-specific information in the device tree for use by the OS. - The device tree is then passed to the OS. - -config OF_SYSTEM_SETUP - bool "Set up system-specific details in device tree before boot" - depends on OF_LIBFDT - help - This causes U-Boot to call ft_system_setup() before booting into - the Operating System. This function can set up various - system-specific information in the device tree for use by the OS. - The device tree is then passed to the OS. - -config OF_STDOUT_VIA_ALIAS - bool "Update the device-tree stdout alias from U-Boot" - depends on OF_LIBFDT - help - This uses U-Boot's serial alias from the aliases node to update - the device tree passed to the OS. The "linux,stdout-path" property - in the chosen node is set to point to the correct serial node. - This option currently references CONFIG_CONS_INDEX, which is - incorrect when used with device tree as this option does not - exist / should not be used. - -config SYS_EXTRA_OPTIONS - string "Extra Options (DEPRECATED)" - help - The old configuration infrastructure (= mkconfig + boards.cfg) - provided the extra options field. If you have something like - "HAS_BAR,BAZ=64", the optional options - #define CONFIG_HAS - #define CONFIG_BAZ 64 - will be defined in include/config.h. - This option was prepared for the smooth migration from the old - configuration to Kconfig. Since this option will be removed sometime, - new boards should not use this option. - -config HAVE_SYS_TEXT_BASE - bool - depends on !NIOS2 && !XTENSA - depends on !EFI_APP - default y - -config SYS_TEXT_BASE - depends on HAVE_SYS_TEXT_BASE - default 0x0 if POSITION_INDEPENDENT - default 0x80800000 if ARCH_OMAP2PLUS || ARCH_K3 - default 0x4a000000 if ARCH_SUNXI && !MACH_SUN9I && !MACH_SUN8I_V3S - default 0x2a000000 if ARCH_SUNXI && MACH_SUN9I - default 0x42e00000 if ARCH_SUNXI && MACH_SUN8I_V3S - hex "Text Base" - help - The address in memory that U-Boot will be running from, initially. - -config SYS_CLK_FREQ - depends on ARC || ARCH_SUNXI || MPC83xx - int "CPU clock frequency" - help - TODO: Move CONFIG_SYS_CLK_FREQ for all the architecture - -config ARCH_FIXUP_FDT_MEMORY - bool "Enable arch_fixup_memory_banks() call" - default y - help - Enable FDT memory map syncup before OS boot. This feature can be - used for booting OS with different memory setup where the part of - the memory location should be used for different purpose. - -config CHROMEOS - bool "Support booting Chrome OS" - help - Chrome OS requires U-Boot to set up a table indicating the boot mode - (e.g. Developer mode) and a few other things. Enable this if you are - booting on a Chromebook to avoid getting an error about an invalid - firmware ID. - -config CHROMEOS_VBOOT - bool "Support Chrome OS verified boot" - help - This is intended to enable the full Chrome OS verified boot support - in U-Boot. It is not actually implemented in the U-Boot source code - at present, so this option is always set to 'n'. It allows - distinguishing between booting Chrome OS in a basic way (developer - mode) and a full boot. - -config RAMBOOT_PBL - bool "Freescale PBL(pre-boot loader) image format support" - help - Some SoCs use PBL to load RCW and/or pre-initialization instructions. - For more details refer to doc/README.pblimage - -config SYS_FSL_PBL_PBI - string "PBI(pre-boot instructions) commands for the PBL image" - depends on RAMBOOT_PBL - help - PBI commands can be used to configure SoC before it starts the execution. - Please refer doc/README.pblimage for more details. - -config SYS_FSL_PBL_RCW - string "Aadditional RCW (Power on reset configuration) for the PBL image" - depends on RAMBOOT_PBL - help - Enables addition of RCW (Power on reset configuration) in built image. - Please refer doc/README.pblimage for more details. - -endmenu # Boot images - -menu "Boot timing" - -config BOOTSTAGE - bool "Boot timing and reporting" - help - Enable recording of boot time while booting. To use it, insert - calls to bootstage_mark() with a suitable BOOTSTAGE_ID from - bootstage.h. Only a single entry is recorded for each ID. You can - give the entry a name with bootstage_mark_name(). You can also - record elapsed time in a particular stage using bootstage_start() - before starting and bootstage_accum() when finished. Bootstage will - add up all the accumulated time and report it. - - Normally, IDs are defined in bootstage.h but a small number of - additional 'user' IDs can be used by passing BOOTSTAGE_ID_ALLOC - as the ID. - - Calls to show_boot_progress() will also result in log entries but - these will not have names. - -config SPL_BOOTSTAGE - bool "Boot timing and reported in SPL" - depends on BOOTSTAGE - help - Enable recording of boot time in SPL. To make this visible to U-Boot - proper, enable BOOTSTAGE_STASH as well. This will stash the timing - information when SPL finishes and load it when U-Boot proper starts - up. - -config TPL_BOOTSTAGE - bool "Boot timing and reported in TPL" - depends on BOOTSTAGE - help - Enable recording of boot time in SPL. To make this visible to U-Boot - proper, enable BOOTSTAGE_STASH as well. This will stash the timing - information when TPL finishes and load it when U-Boot proper starts - up. - -config BOOTSTAGE_REPORT - bool "Display a detailed boot timing report before booting the OS" - depends on BOOTSTAGE - help - Enable output of a boot time report just before the OS is booted. - This shows how long it took U-Boot to go through each stage of the - boot process. The report looks something like this: - - Timer summary in microseconds: - Mark Elapsed Stage - 0 0 reset - 3,575,678 3,575,678 board_init_f start - 3,575,695 17 arch_cpu_init A9 - 3,575,777 82 arch_cpu_init done - 3,659,598 83,821 board_init_r start - 3,910,375 250,777 main_loop - 29,916,167 26,005,792 bootm_start - 30,361,327 445,160 start_kernel - -config BOOTSTAGE_RECORD_COUNT - int "Number of boot stage records to store" - depends on BOOTSTAGE - default 30 - help - This is the size of the bootstage record list and is the maximum - number of bootstage records that can be recorded. - -config SPL_BOOTSTAGE_RECORD_COUNT - int "Number of boot stage records to store for SPL" - depends on SPL_BOOTSTAGE - default 5 - help - This is the size of the bootstage record list and is the maximum - number of bootstage records that can be recorded. - -config TPL_BOOTSTAGE_RECORD_COUNT - int "Number of boot stage records to store for TPL" - depends on TPL_BOOTSTAGE - default 5 - help - This is the size of the bootstage record list and is the maximum - number of bootstage records that can be recorded. - -config BOOTSTAGE_FDT - bool "Store boot timing information in the OS device tree" - depends on BOOTSTAGE - help - Stash the bootstage information in the FDT. A root 'bootstage' - node is created with each bootstage id as a child. Each child - has a 'name' property and either 'mark' containing the - mark time in microseconds, or 'accum' containing the - accumulated time for that bootstage id in microseconds. - For example: - - bootstage { - 154 { - name = "board_init_f"; - mark = <3575678>; - }; - 170 { - name = "lcd"; - accum = <33482>; - }; - }; - - Code in the Linux kernel can find this in /proc/devicetree. - -config BOOTSTAGE_STASH - bool "Stash the boot timing information in memory before booting OS" - depends on BOOTSTAGE - help - Some OSes do not support device tree. Bootstage can instead write - the boot timing information in a binary format at a given address. - This happens through a call to bootstage_stash(), typically in - the CPU's cleanup_before_linux() function. You can use the - 'bootstage stash' and 'bootstage unstash' commands to do this on - the command line. - -config BOOTSTAGE_STASH_ADDR - hex "Address to stash boot timing information" - default 0 - help - Provide an address which will not be overwritten by the OS when it - starts, so that it can read this information when ready. - -config BOOTSTAGE_STASH_SIZE - hex "Size of boot timing stash region" - default 0x1000 - help - This should be large enough to hold the bootstage stash. A value of - 4096 (4KiB) is normally plenty. - -config SHOW_BOOT_PROGRESS - bool "Show boot progress in a board-specific manner" - help - Defining this option allows to add some board-specific code (calling - a user-provided function show_boot_progress(int) that enables you to - show the system's boot progress on some display (for example, some - LEDs) on your board. At the moment, the following checkpoints are - implemented: - - Legacy uImage format: - - Arg Where When - 1 common/cmd_bootm.c before attempting to boot an image - -1 common/cmd_bootm.c Image header has bad magic number - 2 common/cmd_bootm.c Image header has correct magic number - -2 common/cmd_bootm.c Image header has bad checksum - 3 common/cmd_bootm.c Image header has correct checksum - -3 common/cmd_bootm.c Image data has bad checksum - 4 common/cmd_bootm.c Image data has correct checksum - -4 common/cmd_bootm.c Image is for unsupported architecture - 5 common/cmd_bootm.c Architecture check OK - -5 common/cmd_bootm.c Wrong Image Type (not kernel, multi) - 6 common/cmd_bootm.c Image Type check OK - -6 common/cmd_bootm.c gunzip uncompression error - -7 common/cmd_bootm.c Unimplemented compression type - 7 common/cmd_bootm.c Uncompression OK - 8 common/cmd_bootm.c No uncompress/copy overwrite error - -9 common/cmd_bootm.c Unsupported OS (not Linux, BSD, VxWorks, QNX) - - 9 common/image.c Start initial ramdisk verification - -10 common/image.c Ramdisk header has bad magic number - -11 common/image.c Ramdisk header has bad checksum - 10 common/image.c Ramdisk header is OK - -12 common/image.c Ramdisk data has bad checksum - 11 common/image.c Ramdisk data has correct checksum - 12 common/image.c Ramdisk verification complete, start loading - -13 common/image.c Wrong Image Type (not PPC Linux ramdisk) - 13 common/image.c Start multifile image verification - 14 common/image.c No initial ramdisk, no multifile, continue. - - 15 arch/<arch>/lib/bootm.c All preparation done, transferring control to OS - - -30 arch/powerpc/lib/board.c Fatal error, hang the system - -31 post/post.c POST test failed, detected by post_output_backlog() - -32 post/post.c POST test failed, detected by post_run_single() - - 34 common/cmd_doc.c before loading a Image from a DOC device - -35 common/cmd_doc.c Bad usage of "doc" command - 35 common/cmd_doc.c correct usage of "doc" command - -36 common/cmd_doc.c No boot device - 36 common/cmd_doc.c correct boot device - -37 common/cmd_doc.c Unknown Chip ID on boot device - 37 common/cmd_doc.c correct chip ID found, device available - -38 common/cmd_doc.c Read Error on boot device - 38 common/cmd_doc.c reading Image header from DOC device OK - -39 common/cmd_doc.c Image header has bad magic number - 39 common/cmd_doc.c Image header has correct magic number - -40 common/cmd_doc.c Error reading Image from DOC device - 40 common/cmd_doc.c Image header has correct magic number - 41 common/cmd_ide.c before loading a Image from a IDE device - -42 common/cmd_ide.c Bad usage of "ide" command - 42 common/cmd_ide.c correct usage of "ide" command - -43 common/cmd_ide.c No boot device - 43 common/cmd_ide.c boot device found - -44 common/cmd_ide.c Device not available - 44 common/cmd_ide.c Device available - -45 common/cmd_ide.c wrong partition selected - 45 common/cmd_ide.c partition selected - -46 common/cmd_ide.c Unknown partition table - 46 common/cmd_ide.c valid partition table found - -47 common/cmd_ide.c Invalid partition type - 47 common/cmd_ide.c correct partition type - -48 common/cmd_ide.c Error reading Image Header on boot device - 48 common/cmd_ide.c reading Image Header from IDE device OK - -49 common/cmd_ide.c Image header has bad magic number - 49 common/cmd_ide.c Image header has correct magic number - -50 common/cmd_ide.c Image header has bad checksum - 50 common/cmd_ide.c Image header has correct checksum - -51 common/cmd_ide.c Error reading Image from IDE device - 51 common/cmd_ide.c reading Image from IDE device OK - 52 common/cmd_nand.c before loading a Image from a NAND device - -53 common/cmd_nand.c Bad usage of "nand" command - 53 common/cmd_nand.c correct usage of "nand" command - -54 common/cmd_nand.c No boot device - 54 common/cmd_nand.c boot device found - -55 common/cmd_nand.c Unknown Chip ID on boot device - 55 common/cmd_nand.c correct chip ID found, device available - -56 common/cmd_nand.c Error reading Image Header on boot device - 56 common/cmd_nand.c reading Image Header from NAND device OK - -57 common/cmd_nand.c Image header has bad magic number - 57 common/cmd_nand.c Image header has correct magic number - -58 common/cmd_nand.c Error reading Image from NAND device - 58 common/cmd_nand.c reading Image from NAND device OK - - -60 common/env_common.c Environment has a bad CRC, using default - - 64 net/eth.c starting with Ethernet configuration. - -64 net/eth.c no Ethernet found. - 65 net/eth.c Ethernet found. - - -80 common/cmd_net.c usage wrong - 80 common/cmd_net.c before calling net_loop() - -81 common/cmd_net.c some error in net_loop() occurred - 81 common/cmd_net.c net_loop() back without error - -82 common/cmd_net.c size == 0 (File with size 0 loaded) - 82 common/cmd_net.c trying automatic boot - 83 common/cmd_net.c running "source" command - -83 common/cmd_net.c some error in automatic boot or "source" command - 84 common/cmd_net.c end without errors - - FIT uImage format: - - Arg Where When - 100 common/cmd_bootm.c Kernel FIT Image has correct format - -100 common/cmd_bootm.c Kernel FIT Image has incorrect format - 101 common/cmd_bootm.c No Kernel subimage unit name, using configuration - -101 common/cmd_bootm.c Can't get configuration for kernel subimage - 102 common/cmd_bootm.c Kernel unit name specified - -103 common/cmd_bootm.c Can't get kernel subimage node offset - 103 common/cmd_bootm.c Found configuration node - 104 common/cmd_bootm.c Got kernel subimage node offset - -104 common/cmd_bootm.c Kernel subimage hash verification failed - 105 common/cmd_bootm.c Kernel subimage hash verification OK - -105 common/cmd_bootm.c Kernel subimage is for unsupported architecture - 106 common/cmd_bootm.c Architecture check OK - -106 common/cmd_bootm.c Kernel subimage has wrong type - 107 common/cmd_bootm.c Kernel subimage type OK - -107 common/cmd_bootm.c Can't get kernel subimage data/size - 108 common/cmd_bootm.c Got kernel subimage data/size - -108 common/cmd_bootm.c Wrong image type (not legacy, FIT) - -109 common/cmd_bootm.c Can't get kernel subimage type - -110 common/cmd_bootm.c Can't get kernel subimage comp - -111 common/cmd_bootm.c Can't get kernel subimage os - -112 common/cmd_bootm.c Can't get kernel subimage load address - -113 common/cmd_bootm.c Image uncompress/copy overwrite error - - 120 common/image.c Start initial ramdisk verification - -120 common/image.c Ramdisk FIT image has incorrect format - 121 common/image.c Ramdisk FIT image has correct format - 122 common/image.c No ramdisk subimage unit name, using configuration - -122 common/image.c Can't get configuration for ramdisk subimage - 123 common/image.c Ramdisk unit name specified - -124 common/image.c Can't get ramdisk subimage node offset - 125 common/image.c Got ramdisk subimage node offset - -125 common/image.c Ramdisk subimage hash verification failed - 126 common/image.c Ramdisk subimage hash verification OK - -126 common/image.c Ramdisk subimage for unsupported architecture - 127 common/image.c Architecture check OK - -127 common/image.c Can't get ramdisk subimage data/size - 128 common/image.c Got ramdisk subimage data/size - 129 common/image.c Can't get ramdisk load address - -129 common/image.c Got ramdisk load address - - -130 common/cmd_doc.c Incorrect FIT image format - 131 common/cmd_doc.c FIT image format OK - - -140 common/cmd_ide.c Incorrect FIT image format - 141 common/cmd_ide.c FIT image format OK - - -150 common/cmd_nand.c Incorrect FIT image format - 151 common/cmd_nand.c FIT image format OK - -config SPL_SHOW_BOOT_PROGRESS - bool "Show boot progress in a board-specific manner" - depends on SPL - help - Defining this option allows to add some board-specific code (calling - a user-provided function show_boot_progress(int) that enables you to - show the system's boot progress on some display (for example, some - LEDs) on your board. For details see SHOW_BOOT_PROGRESS. - -endmenu - -menu "Boot media" - -config NOR_BOOT - bool "Support for booting from NOR flash" - depends on NOR - help - Enabling this will make a U-Boot binary that is capable of being - booted via NOR. In this case we will enable certain pinmux early - as the ROM only partially sets up pinmux. We also default to using - NOR for environment. - -config NAND_BOOT - bool "Support for booting from NAND flash" - imply MTD_RAW_NAND - help - Enabling this will make a U-Boot binary that is capable of being - booted via NAND flash. This is not a must, some SoCs need this, - some not. - -config ONENAND_BOOT - bool "Support for booting from ONENAND" - imply MTD_RAW_NAND - help - Enabling this will make a U-Boot binary that is capable of being - booted via ONENAND. This is not a must, some SoCs need this, - some not. - -config QSPI_BOOT - bool "Support for booting from QSPI flash" - help - Enabling this will make a U-Boot binary that is capable of being - booted via QSPI flash. This is not a must, some SoCs need this, - some not. - -config SATA_BOOT - bool "Support for booting from SATA" - help - Enabling this will make a U-Boot binary that is capable of being - booted via SATA. This is not a must, some SoCs need this, - some not. - -config SD_BOOT - bool "Support for booting from SD/EMMC" - help - Enabling this will make a U-Boot binary that is capable of being - booted via SD/EMMC. This is not a must, some SoCs need this, - some not. - -config SPI_BOOT - bool "Support for booting from SPI flash" - help - Enabling this will make a U-Boot binary that is capable of being - booted via SPI flash. This is not a must, some SoCs need this, - some not. - -endmenu - -menu "Autoboot options" - -config AUTOBOOT - bool "Autoboot" - default y - help - This enables the autoboot. See doc/README.autoboot for detail. - -config BOOTDELAY - int "delay in seconds before automatically booting" - default 2 - depends on AUTOBOOT - help - Delay before automatically running bootcmd; - set to 0 to autoboot with no delay, but you can stop it by key input. - set to -1 to disable autoboot. - set to -2 to autoboot with no delay and not check for abort - - If this value is >= 0 then it is also used for the default delay - before starting the default entry in bootmenu. If it is < 0 then - a default value of 10s is used. - - See doc/README.autoboot for details. - -config AUTOBOOT_KEYED - bool "Stop autobooting via specific input key / string" - help - This option enables stopping (aborting) of the automatic - boot feature only by issuing a specific input key or - string. If not enabled, any input key will abort the - U-Boot automatic booting process and bring the device - to the U-Boot prompt for user input. - -config AUTOBOOT_FLUSH_STDIN - bool "Enable flushing stdin before starting to read the password" - depends on AUTOBOOT_KEYED && !SANDBOX - help - When this option is enabled stdin buffer will be flushed before - starting to read the password. - This can't be enabled for the sandbox as flushing stdin would - break the autoboot unit tests. - -config AUTOBOOT_PROMPT - string "Autoboot stop prompt" - depends on AUTOBOOT_KEYED - default "Autoboot in %d seconds\\n" - help - This string is displayed before the boot delay selected by - CONFIG_BOOTDELAY starts. If it is not defined there is no - output indicating that autoboot is in progress. - - Note that this define is used as the (only) argument to a - printf() call, so it may contain '%' format specifications, - provided that it also includes, sepearated by commas exactly - like in a printf statement, the required arguments. It is - the responsibility of the user to select only such arguments - that are valid in the given context. - -config AUTOBOOT_ENCRYPTION - bool "Enable encryption in autoboot stopping" - depends on AUTOBOOT_KEYED - help - This option allows a string to be entered into U-Boot to stop the - autoboot. - The behavior depends whether CONFIG_CRYPT_PW from lib is enabled - or not. - In case CONFIG_CRYPT_PW is enabled, the string will be forwarded - to the crypt-based functionality and be compared against the - string in the environment variable 'bootstopkeycrypt'. - In case CONFIG_CRYPT_PW is disabled the string itself is hashed - and compared against the hash in the environment variable - 'bootstopkeysha256'. - If it matches in either case then boot stops and - a command-line prompt is presented. - This provides a way to ship a secure production device which can also - be accessed at the U-Boot command line. - -config AUTOBOOT_SHA256_FALLBACK - bool "Allow fallback from crypt-hashed password to sha256" - depends on AUTOBOOT_ENCRYPTION && CRYPT_PW - help - This option adds support to fall back from crypt-hashed - passwords to checking a SHA256 hashed password in case the - 'bootstopusesha256' environment variable is set to 'true'. - -config AUTOBOOT_DELAY_STR - string "Delay autobooting via specific input key / string" - depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION - help - This option delays the automatic boot feature by issuing - a specific input key or string. If CONFIG_AUTOBOOT_DELAY_STR - or the environment variable "bootdelaykey" is specified - and this string is received from console input before - autoboot starts booting, U-Boot gives a command prompt. The - U-Boot prompt will time out if CONFIG_BOOT_RETRY_TIME is - used, otherwise it never times out. - -config AUTOBOOT_STOP_STR - string "Stop autobooting via specific input key / string" - depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION - help - This option enables stopping (aborting) of the automatic - boot feature only by issuing a specific input key or - string. If CONFIG_AUTOBOOT_STOP_STR or the environment - variable "bootstopkey" is specified and this string is - received from console input before autoboot starts booting, - U-Boot gives a command prompt. The U-Boot prompt never - times out, even if CONFIG_BOOT_RETRY_TIME is used. - -config AUTOBOOT_KEYED_CTRLC - bool "Enable Ctrl-C autoboot interruption" - depends on AUTOBOOT_KEYED && !AUTOBOOT_ENCRYPTION - help - This option allows for the boot sequence to be interrupted - by ctrl-c, in addition to the "bootdelaykey" and "bootstopkey". - Setting this variable provides an escape sequence from the - limited "password" strings. - -config AUTOBOOT_NEVER_TIMEOUT - bool "Make the password entry never time-out" - depends on AUTOBOOT_KEYED && AUTOBOOT_ENCRYPTION && CRYPT_PW - help - This option removes the timeout from the password entry - when the user first presses the <Enter> key before entering - any other character. - -config AUTOBOOT_STOP_STR_ENABLE - bool "Enable fixed string to stop autobooting" - depends on AUTOBOOT_KEYED && AUTOBOOT_ENCRYPTION - help - This option enables the feature to add a fixed stop - string that is defined at compile time. - In every case it will be tried to load the stop - string from the environment. - In case this is enabled and there is no stop string - in the environment, this will be used as default value. - -config AUTOBOOT_STOP_STR_CRYPT - string "Stop autobooting via crypt-hashed password" - depends on AUTOBOOT_STOP_STR_ENABLE && CRYPT_PW - help - This option adds the feature to only stop the autobooting, - and therefore boot into the U-Boot prompt, when the input - string / password matches a values that is hashed via - one of the supported crypt-style password hashing options - and saved in the environment variable "bootstopkeycrypt". - -config AUTOBOOT_STOP_STR_SHA256 - string "Stop autobooting via SHA256 hashed password" - depends on AUTOBOOT_STOP_STR_ENABLE - help - This option adds the feature to only stop the autobooting, - and therefore boot into the U-Boot prompt, when the input - string / password matches a values that is encypted via - a SHA256 hash and saved in the environment variable - "bootstopkeysha256". If the value in that variable - includes a ":", the portion prior to the ":" will be treated - as a salt value. - -config AUTOBOOT_USE_MENUKEY - bool "Allow a specify key to run a menu from the environment" - depends on !AUTOBOOT_KEYED - help - If a specific key is pressed to stop autoboot, then the commands in - the environment variable 'menucmd' are executed before boot starts. - -config AUTOBOOT_MENUKEY - int "ASCII value of boot key to show a menu" - default 0 - depends on AUTOBOOT_USE_MENUKEY - help - If this key is pressed to stop autoboot, then the commands in the - environment variable 'menucmd' will be executed before boot starts. - For example, 33 means "!" in ASCII, so pressing ! at boot would take - this action. - -config AUTOBOOT_MENU_SHOW - bool "Show a menu on boot" - depends on CMD_BOOTMENU - help - This enables the boot menu, controlled by environment variables - defined by the board. The menu starts after running the 'preboot' - environmnent variable (if enabled) and before handling the boot delay. - See README.bootmenu for more details. - -endmenu - -config USE_BOOTARGS - bool "Enable boot arguments" - help - Provide boot arguments to bootm command. Boot arguments are specified - in CONFIG_BOOTARGS option. Enable this option to be able to specify - CONFIG_BOOTARGS string. If this option is disabled, CONFIG_BOOTARGS - will be undefined and won't take any space in U-Boot image. - -config BOOTARGS - string "Boot arguments" - depends on USE_BOOTARGS && !USE_DEFAULT_ENV_FILE - help - This can be used to pass arguments to the bootm command. The value of - CONFIG_BOOTARGS goes into the environment value "bootargs". Note that - this value will also override the "chosen" node in FDT blob. - -config BOOTARGS_SUBST - bool "Support substituting strings in boot arguments" - help - This allows substituting string values in the boot arguments. These - are applied after the commandline has been built. - - One use for this is to insert the root-disk UUID into the command - line where bootargs contains "root=${uuid}" - - setenv bootargs "console= root=${uuid}" - # Set the 'uuid' environment variable - part uuid mmc 2:2 uuid - - # Command-line substitution will put the real uuid into the - # kernel command line - bootm - -config USE_BOOTCOMMAND - bool "Enable a default value for bootcmd" - help - Provide a default value for the bootcmd entry in the environment. If - autoboot is enabled this is what will be run automatically. Enable - this option to be able to specify CONFIG_BOOTCOMMAND as a string. If - this option is disabled, CONFIG_BOOTCOMMAND will be undefined and - won't take any space in U-Boot image. - -config BOOTCOMMAND - string "bootcmd value" - depends on USE_BOOTCOMMAND && !USE_DEFAULT_ENV_FILE - default "run distro_bootcmd" if DISTRO_DEFAULTS - help - This is the string of commands that will be used as bootcmd and if - AUTOBOOT is set, automatically run. - -config USE_PREBOOT - bool "Enable preboot" - help - When this option is enabled, the existence of the environment - variable "preboot" will be checked immediately before starting the - CONFIG_BOOTDELAY countdown and/or running the auto-boot command resp. - entering interactive mode. - - This feature is especially useful when "preboot" is automatically - generated or modified. For example, the boot code can modify the - "preboot" when a user holds down a certain combination of keys. - -config PREBOOT - string "preboot default value" - depends on USE_PREBOOT && !USE_DEFAULT_ENV_FILE - default "usb start" if USB_KEYBOARD - default "" - help - This is the default of "preboot" environment variable. - -config DEFAULT_FDT_FILE - string "Default fdt file" - help - This option is used to set the default fdt file to boot OS. - -endmenu # Booting diff --git a/common/Makefile b/common/Makefile index e7839027b6c..afaf8e5048a 100644 --- a/common/Makefile +++ b/common/Makefile @@ -11,21 +11,12 @@ obj-y += exports.o obj-$(CONFIG_HUSH_PARSER) += cli_hush.o obj-$(CONFIG_AUTOBOOT) += autoboot.o -# This option is not just y/n - it can have a numeric value -ifdef CONFIG_BOOT_RETRY_TIME -obj-y += bootretry.o -endif - # # boards obj-y += board_f.o obj-y += board_r.o obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o obj-$(CONFIG_DISPLAY_BOARDINFO_LATE) += board_info.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o -obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o -obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o - obj-$(CONFIG_CMD_BEDBUG) += bedbug.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o obj-$(CONFIG_MII) += miiphyutil.o @@ -65,7 +56,6 @@ ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_DFU obj-$(CONFIG_DFU_OVER_USB) += dfu.o endif -obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o obj-$(CONFIG_SPL_NET) += miiphyutil.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdt_support.o @@ -101,23 +91,11 @@ obj-y += malloc_simple.o endif endif -obj-y += image.o image-board.o obj-$(CONFIG_$(SPL_TPL_)HASH) += hash.o -obj-$(CONFIG_ANDROID_AB) += android_ab.o -obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o -obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o -obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o -obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o -obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o -obj-$(CONFIG_$(SPL_TPL_)IMAGE_SIGN_INFO) += image-sig.o -obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-fit-sig.o -obj-$(CONFIG_$(SPL_TPL_)FIT_CIPHER) += image-cipher.o obj-$(CONFIG_IO_TRACE) += iotrace.o obj-y += memsize.o obj-y += stdio.o -obj-$(CONFIG_CMD_ADTIMG) += image-android-dt.o - ifdef CONFIG_CMD_EEPROM_LAYOUT obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o endif diff --git a/common/android_ab.c b/common/android_ab.c deleted file mode 100644 index 4943f26d53a..00000000000 --- a/common/android_ab.c +++ /dev/null @@ -1,305 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause -/* - * Copyright (C) 2017 The Android Open Source Project - */ -#include <common.h> -#include <android_ab.h> -#include <android_bootloader_message.h> -#include <blk.h> -#include <log.h> -#include <malloc.h> -#include <part.h> -#include <memalign.h> -#include <linux/err.h> -#include <u-boot/crc.h> -#include <u-boot/crc.h> - -/** - * Compute the CRC-32 of the bootloader control struct. - * - * Only the bytes up to the crc32_le field are considered for the CRC-32 - * calculation. - * - * @param[in] abc bootloader control block - * - * @return crc32 sum - */ -static uint32_t ab_control_compute_crc(struct bootloader_control *abc) -{ - return crc32(0, (void *)abc, offsetof(typeof(*abc), crc32_le)); -} - -/** - * Initialize bootloader_control to the default value. - * - * It allows us to boot all slots in order from the first one. This value - * should be used when the bootloader message is corrupted, but not when - * a valid message indicates that all slots are unbootable. - * - * @param[in] abc bootloader control block - * - * @return 0 on success and a negative on error - */ -static int ab_control_default(struct bootloader_control *abc) -{ - int i; - const struct slot_metadata metadata = { - .priority = 15, - .tries_remaining = 7, - .successful_boot = 0, - .verity_corrupted = 0, - .reserved = 0 - }; - - if (!abc) - return -EFAULT; - - memcpy(abc->slot_suffix, "a\0\0\0", 4); - abc->magic = BOOT_CTRL_MAGIC; - abc->version = BOOT_CTRL_VERSION; - abc->nb_slot = NUM_SLOTS; - memset(abc->reserved0, 0, sizeof(abc->reserved0)); - for (i = 0; i < abc->nb_slot; ++i) - abc->slot_info[i] = metadata; - - memset(abc->reserved1, 0, sizeof(abc->reserved1)); - abc->crc32_le = ab_control_compute_crc(abc); - - return 0; -} - -/** - * Load the boot_control struct from disk into newly allocated memory. - * - * This function allocates and returns an integer number of disk blocks, - * based on the block size of the passed device to help performing a - * read-modify-write operation on the boot_control struct. - * The boot_control struct offset (2 KiB) must be a multiple of the device - * block size, for simplicity. - * - * @param[in] dev_desc Device where to read the boot_control struct from - * @param[in] part_info Partition in 'dev_desc' where to read from, normally - * the "misc" partition should be used - * @param[out] pointer to pointer to bootloader_control data - * @return 0 on success and a negative on error - */ -static int ab_control_create_from_disk(struct blk_desc *dev_desc, - const struct disk_partition *part_info, - struct bootloader_control **abc) -{ - ulong abc_offset, abc_blocks, ret; - - abc_offset = offsetof(struct bootloader_message_ab, slot_suffix); - if (abc_offset % part_info->blksz) { - log_err("ANDROID: Boot control block not block aligned.\n"); - return -EINVAL; - } - abc_offset /= part_info->blksz; - - abc_blocks = DIV_ROUND_UP(sizeof(struct bootloader_control), - part_info->blksz); - if (abc_offset + abc_blocks > part_info->size) { - log_err("ANDROID: boot control partition too small. Need at"); - log_err(" least %lu blocks but have %lu blocks.\n", - abc_offset + abc_blocks, part_info->size); - return -EINVAL; - } - *abc = malloc_cache_aligned(abc_blocks * part_info->blksz); - if (!*abc) - return -ENOMEM; - - ret = blk_dread(dev_desc, part_info->start + abc_offset, abc_blocks, - *abc); - if (IS_ERR_VALUE(ret)) { - log_err("ANDROID: Could not read from boot ctrl partition\n"); - free(*abc); - return -EIO; - } - - log_debug("ANDROID: Loaded ABC, %lu blocks\n", abc_blocks); - - return 0; -} - -/** - * Store the loaded boot_control block. - * - * Store back to the same location it was read from with - * ab_control_create_from_misc(). - * - * @param[in] dev_desc Device where we should write the boot_control struct - * @param[in] part_info Partition on the 'dev_desc' where to write - * @param[in] abc Pointer to the boot control struct and the extra bytes after - * it up to the nearest block boundary - * @return 0 on success and a negative on error - */ -static int ab_control_store(struct blk_desc *dev_desc, - const struct disk_partition *part_info, - struct bootloader_control *abc) -{ - ulong abc_offset, abc_blocks, ret; - - abc_offset = offsetof(struct bootloader_message_ab, slot_suffix) / - part_info->blksz; - abc_blocks = DIV_ROUND_UP(sizeof(struct bootloader_control), - part_info->blksz); - ret = blk_dwrite(dev_desc, part_info->start + abc_offset, abc_blocks, - abc); - if (IS_ERR_VALUE(ret)) { - log_err("ANDROID: Could not write back the misc partition\n"); - return -EIO; - } - - return 0; -} - -/** - * Compare two slots. - * - * The function determines slot which is should we boot from among the two. - * - * @param[in] a The first bootable slot metadata - * @param[in] b The second bootable slot metadata - * @return Negative if the slot "a" is better, positive of the slot "b" is - * better or 0 if they are equally good. - */ -static int ab_compare_slots(const struct slot_metadata *a, - const struct slot_metadata *b) -{ - /* Higher priority is better */ - if (a->priority != b->priority) - return b->priority - a->priority; - - /* Higher successful_boot value is better, in case of same priority */ - if (a->successful_boot != b->successful_boot) - return b->successful_boot - a->successful_boot; - - /* Higher tries_remaining is better to ensure round-robin */ - if (a->tries_remaining != b->tries_remaining) - return b->tries_remaining - a->tries_remaining; - - return 0; -} - -int ab_select_slot(struct blk_desc *dev_desc, struct disk_partition *part_info) -{ - struct bootloader_control *abc = NULL; - u32 crc32_le; - int slot, i, ret; - bool store_needed = false; - char slot_suffix[4]; - - ret = ab_control_create_from_disk(dev_desc, part_info, &abc); - if (ret < 0) { - /* - * This condition represents an actual problem with the code or - * the board setup, like an invalid partition information. - * Signal a repair mode and do not try to boot from either slot. - */ - return ret; - } - - crc32_le = ab_control_compute_crc(abc); - if (abc->crc32_le != crc32_le) { - log_err("ANDROID: Invalid CRC-32 (expected %.8x, found %.8x),", - crc32_le, abc->crc32_le); - log_err("re-initializing A/B metadata.\n"); - - ret = ab_control_default(abc); - if (ret < 0) { - free(abc); - return -ENODATA; - } - store_needed = true; - } - - if (abc->magic != BOOT_CTRL_MAGIC) { - log_err("ANDROID: Unknown A/B metadata: %.8x\n", abc->magic); - free(abc); - return -ENODATA; - } - - if (abc->version > BOOT_CTRL_VERSION) { - log_err("ANDROID: Unsupported A/B metadata version: %.8x\n", - abc->version); - free(abc); - return -ENODATA; - } - - /* - * At this point a valid boot control metadata is stored in abc, - * followed by other reserved data in the same block. We select a with - * the higher priority slot that - * - is not marked as corrupted and - * - either has tries_remaining > 0 or successful_boot is true. - * If the selected slot has a false successful_boot, we also decrement - * the tries_remaining until it eventually becomes unbootable because - * tries_remaining reaches 0. This mechanism produces a bootloader - * induced rollback, typically right after a failed update. - */ - - /* Safety check: limit the number of slots. */ - if (abc->nb_slot > ARRAY_SIZE(abc->slot_info)) { - abc->nb_slot = ARRAY_SIZE(abc->slot_info); - store_needed = true; - } - - slot = -1; - for (i = 0; i < abc->nb_slot; ++i) { - if (abc->slot_info[i].verity_corrupted || - !abc->slot_info[i].tries_remaining) { - log_debug("ANDROID: unbootable slot %d tries: %d, ", - i, abc->slot_info[i].tries_remaining); - log_debug("corrupt: %d\n", - abc->slot_info[i].verity_corrupted); - continue; - } - log_debug("ANDROID: bootable slot %d pri: %d, tries: %d, ", - i, abc->slot_info[i].priority, - abc->slot_info[i].tries_remaining); - log_debug("corrupt: %d, successful: %d\n", - abc->slot_info[i].verity_corrupted, - abc->slot_info[i].successful_boot); - - if (slot < 0 || - ab_compare_slots(&abc->slot_info[i], - &abc->slot_info[slot]) < 0) { - slot = i; - } - } - - if (slot >= 0 && !abc->slot_info[slot].successful_boot) { - log_err("ANDROID: Attempting slot %c, tries remaining %d\n", - BOOT_SLOT_NAME(slot), - abc->slot_info[slot].tries_remaining); - abc->slot_info[slot].tries_remaining--; - store_needed = true; - } - - if (slot >= 0) { - /* - * Legacy user-space requires this field to be set in the BCB. - * Newer releases load this slot suffix from the command line - * or the device tree. - */ - memset(slot_suffix, 0, sizeof(slot_suffix)); - slot_suffix[0] = BOOT_SLOT_NAME(slot); - if (memcmp(abc->slot_suffix, slot_suffix, - sizeof(slot_suffix))) { - memcpy(abc->slot_suffix, slot_suffix, - sizeof(slot_suffix)); - store_needed = true; - } - } - - if (store_needed) { - abc->crc32_le = ab_control_compute_crc(abc); - ab_control_store(dev_desc, part_info, abc); - } - free(abc); - - if (slot < 0) - return -EINVAL; - - return slot; -} diff --git a/common/boot_fit.c b/common/boot_fit.c deleted file mode 100644 index dfc2a3117d1..00000000000 --- a/common/boot_fit.c +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2017 - * Texas Instruments, <www.ti.com> - * - * Franklin S Cooper Jr. <fcooper@ti.com> - */ - -#include <boot_fit.h> -#include <common.h> -#include <errno.h> -#include <image.h> -#include <log.h> -#include <linux/libfdt.h> - -static int fdt_offset(const void *fit) -{ - int images, node, fdt_len, fdt_node, fdt_offset; - const char *fdt_name; - - node = fit_find_config_node(fit); - if (node < 0) - return node; - - images = fdt_path_offset(fit, FIT_IMAGES_PATH); - if (images < 0) { - debug("%s: Cannot find /images node: %d\n", __func__, images); - return -EINVAL; - } - - fdt_name = fdt_getprop(fit, node, FIT_FDT_PROP, &fdt_len); - if (!fdt_name) { - debug("%s: Cannot find fdt name property: %d\n", - __func__, fdt_len); - return -EINVAL; - } - - fdt_node = fdt_subnode_offset(fit, images, fdt_name); - if (fdt_node < 0) { - debug("%s: Cannot find fdt node '%s': %d\n", - __func__, fdt_name, fdt_node); - return -EINVAL; - } - - fdt_offset = fdt_getprop_u32(fit, fdt_node, "data-offset"); - - if (fdt_offset == FDT_ERROR) - return -ENOENT; - - fdt_len = fdt_getprop_u32(fit, fdt_node, "data-size"); - - if (fdt_len < 0) - return fdt_len; - - return fdt_offset; -} - -void *locate_dtb_in_fit(const void *fit) -{ - struct image_header *header; - int size; - int ret; - - size = fdt_totalsize(fit); - size = (size + 3) & ~3; - - header = (struct image_header *)fit; - - if (image_get_magic(header) != FDT_MAGIC) { - debug("No FIT image appended to U-boot\n"); - return NULL; - } - - ret = fdt_offset(fit); - - if (ret < 0) - return NULL; - else - return (void *)fit+size+ret; -} diff --git a/common/bootm.c b/common/bootm.c deleted file mode 100644 index 4482f84b40a..00000000000 --- a/common/bootm.c +++ /dev/null @@ -1,1038 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2000-2009 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#ifndef USE_HOSTCC -#include <common.h> -#include <bootstage.h> -#include <cli.h> -#include <cpu_func.h> -#include <env.h> -#include <errno.h> -#include <fdt_support.h> -#include <irq_func.h> -#include <lmb.h> -#include <log.h> -#include <malloc.h> -#include <mapmem.h> -#include <net.h> -#include <asm/cache.h> -#include <asm/global_data.h> -#include <asm/io.h> -#include <linux/sizes.h> -#if defined(CONFIG_CMD_USB) -#include <usb.h> -#endif -#else -#include "mkimage.h" -#endif - -#include <command.h> -#include <bootm.h> -#include <image.h> - -#ifndef CONFIG_SYS_BOOTM_LEN -/* use 8MByte as default max gunzip size */ -#define CONFIG_SYS_BOOTM_LEN 0x800000 -#endif - -#define MAX_CMDLINE_SIZE SZ_4K - -#define IH_INITRD_ARCH IH_ARCH_DEFAULT - -#ifndef USE_HOSTCC - -DECLARE_GLOBAL_DATA_PTR; - -bootm_headers_t images; /* pointers to os/initrd/fdt images */ - -static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], bootm_headers_t *images, - ulong *os_data, ulong *os_len); - -__weak void board_quiesce_devices(void) -{ -} - -#ifdef CONFIG_LMB -static void boot_start_lmb(bootm_headers_t *images) -{ - ulong mem_start; - phys_size_t mem_size; - - mem_start = env_get_bootm_low(); - mem_size = env_get_bootm_size(); - - lmb_init_and_reserve_range(&images->lmb, (phys_addr_t)mem_start, - mem_size, NULL); -} -#else -#define lmb_reserve(lmb, base, size) -static inline void boot_start_lmb(bootm_headers_t *images) { } -#endif - -static int bootm_start(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - memset((void *)&images, 0, sizeof(images)); - images.verify = env_get_yesno("verify"); - - boot_start_lmb(&images); - - bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start"); - images.state = BOOTM_STATE_START; - - return 0; -} - -static int bootm_find_os(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - const void *os_hdr; - bool ep_found = false; - int ret; - - /* get kernel image header, start address and length */ - os_hdr = boot_get_kernel(cmdtp, flag, argc, argv, - &images, &images.os.image_start, &images.os.image_len); - if (images.os.image_len == 0) { - puts("ERROR: can't get kernel image!\n"); - return 1; - } - - /* get image parameters */ - switch (genimg_get_format(os_hdr)) { -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - case IMAGE_FORMAT_LEGACY: - images.os.type = image_get_type(os_hdr); - images.os.comp = image_get_comp(os_hdr); - images.os.os = image_get_os(os_hdr); - - images.os.end = image_get_image_end(os_hdr); - images.os.load = image_get_load(os_hdr); - images.os.arch = image_get_arch(os_hdr); - break; -#endif -#if CONFIG_IS_ENABLED(FIT) - case IMAGE_FORMAT_FIT: - if (fit_image_get_type(images.fit_hdr_os, - images.fit_noffset_os, - &images.os.type)) { - puts("Can't get image type!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_TYPE); - return 1; - } - - if (fit_image_get_comp(images.fit_hdr_os, - images.fit_noffset_os, - &images.os.comp)) { - puts("Can't get image compression!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_COMPRESSION); - return 1; - } - - if (fit_image_get_os(images.fit_hdr_os, images.fit_noffset_os, - &images.os.os)) { - puts("Can't get image OS!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_OS); - return 1; - } - - if (fit_image_get_arch(images.fit_hdr_os, - images.fit_noffset_os, - &images.os.arch)) { - puts("Can't get image ARCH!\n"); - return 1; - } - - images.os.end = fit_get_end(images.fit_hdr_os); - - if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os, - &images.os.load)) { - puts("Can't get image load address!\n"); - bootstage_error(BOOTSTAGE_ID_FIT_LOADADDR); - return 1; - } - break; -#endif -#ifdef CONFIG_ANDROID_BOOT_IMAGE - case IMAGE_FORMAT_ANDROID: - images.os.type = IH_TYPE_KERNEL; - images.os.comp = android_image_get_kcomp(os_hdr); - images.os.os = IH_OS_LINUX; - - images.os.end = android_image_get_end(os_hdr); - images.os.load = android_image_get_kload(os_hdr); - images.ep = images.os.load; - ep_found = true; - break; -#endif - default: - puts("ERROR: unknown image format type!\n"); - return 1; - } - - /* If we have a valid setup.bin, we will use that for entry (x86) */ - if (images.os.arch == IH_ARCH_I386 || - images.os.arch == IH_ARCH_X86_64) { - ulong len; - - ret = boot_get_setup(&images, IH_ARCH_I386, &images.ep, &len); - if (ret < 0 && ret != -ENOENT) { - puts("Could not find a valid setup.bin for x86\n"); - return 1; - } - /* Kernel entry point is the setup.bin */ - } else if (images.legacy_hdr_valid) { - images.ep = image_get_ep(&images.legacy_hdr_os_copy); -#if CONFIG_IS_ENABLED(FIT) - } else if (images.fit_uname_os) { - int ret; - - ret = fit_image_get_entry(images.fit_hdr_os, - images.fit_noffset_os, &images.ep); - if (ret) { - puts("Can't get entry point property!\n"); - return 1; - } -#endif - } else if (!ep_found) { - puts("Could not find kernel entry point!\n"); - return 1; - } - - if (images.os.type == IH_TYPE_KERNEL_NOLOAD) { - if (CONFIG_IS_ENABLED(CMD_BOOTI) && - images.os.arch == IH_ARCH_ARM64) { - ulong image_addr; - ulong image_size; - - ret = booti_setup(images.os.image_start, &image_addr, - &image_size, true); - if (ret != 0) - return 1; - - images.os.type = IH_TYPE_KERNEL; - images.os.load = image_addr; - images.ep = image_addr; - } else { - images.os.load = images.os.image_start; - images.ep += images.os.image_start; - } - } - - images.os.start = map_to_sysmem(os_hdr); - - return 0; -} - -/** - * bootm_find_images - wrapper to find and locate various images - * @flag: Ignored Argument - * @argc: command argument count - * @argv: command argument list - * @start: OS image start address - * @size: OS image size - * - * boot_find_images() will attempt to load an available ramdisk, - * flattened device tree, as well as specifically marked - * "loadable" images (loadables are FIT only) - * - * Note: bootm_find_images will skip an image if it is not found - * - * @return: - * 0, if all existing images were loaded correctly - * 1, if an image is found but corrupted, or invalid - */ -int bootm_find_images(int flag, int argc, char *const argv[], ulong start, - ulong size) -{ - int ret; - - /* find ramdisk */ - ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH, - &images.rd_start, &images.rd_end); - if (ret) { - puts("Ramdisk image is corrupt or invalid\n"); - return 1; - } - - /* check if ramdisk overlaps OS image */ - if (images.rd_start && (((ulong)images.rd_start >= start && - (ulong)images.rd_start < start + size) || - ((ulong)images.rd_end > start && - (ulong)images.rd_end <= start + size) || - ((ulong)images.rd_start < start && - (ulong)images.rd_end >= start + size))) { - printf("ERROR: RD image overlaps OS image (OS=0x%lx..0x%lx)\n", - start, start + size); - return 1; - } - -#if CONFIG_IS_ENABLED(OF_LIBFDT) - /* find flattened device tree */ - ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images, - &images.ft_addr, &images.ft_len); - if (ret) { - puts("Could not find a valid device tree\n"); - return 1; - } - - /* check if FDT overlaps OS image */ - if (images.ft_addr && - (((ulong)images.ft_addr >= start && - (ulong)images.ft_addr <= start + size) || - ((ulong)images.ft_addr + images.ft_len >= start && - (ulong)images.ft_addr + images.ft_len <= start + size))) { - printf("ERROR: FDT image overlaps OS image (OS=0x%lx..0x%lx)\n", - start, start + size); - return 1; - } - - if (CONFIG_IS_ENABLED(CMD_FDT)) - set_working_fdt_addr(map_to_sysmem(images.ft_addr)); -#endif - -#if CONFIG_IS_ENABLED(FIT) - if (IS_ENABLED(CONFIG_FPGA)) { - /* find bitstreams */ - ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT, - NULL, NULL); - if (ret) { - printf("FPGA image is corrupted or invalid\n"); - return 1; - } - } - - /* find all of the loadables */ - ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT, - NULL, NULL); - if (ret) { - printf("Loadable(s) is corrupt or invalid\n"); - return 1; - } -#endif - - return 0; -} - -static int bootm_find_other(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - if (((images.os.type == IH_TYPE_KERNEL) || - (images.os.type == IH_TYPE_KERNEL_NOLOAD) || - (images.os.type == IH_TYPE_MULTI)) && - (images.os.os == IH_OS_LINUX || - images.os.os == IH_OS_VXWORKS)) - return bootm_find_images(flag, argc, argv, 0, 0); - - return 0; -} -#endif /* USE_HOSTC */ - -#if !defined(USE_HOSTCC) || defined(CONFIG_FIT_SIGNATURE) -/** - * handle_decomp_error() - display a decompression error - * - * This function tries to produce a useful message. In the case where the - * uncompressed size is the same as the available space, we can assume that - * the image is too large for the buffer. - * - * @comp_type: Compression type being used (IH_COMP_...) - * @uncomp_size: Number of bytes uncompressed - * @ret: errno error code received from compression library - * @return Appropriate BOOTM_ERR_ error code - */ -static int handle_decomp_error(int comp_type, size_t uncomp_size, int ret) -{ - const char *name = genimg_get_comp_name(comp_type); - - /* ENOSYS means unimplemented compression type, don't reset. */ - if (ret == -ENOSYS) - return BOOTM_ERR_UNIMPLEMENTED; - - if (uncomp_size >= CONFIG_SYS_BOOTM_LEN) - printf("Image too large: increase CONFIG_SYS_BOOTM_LEN\n"); - else - printf("%s: uncompress error %d\n", name, ret); - - /* - * The decompression routines are now safe, so will not write beyond - * their bounds. Probably it is not necessary to reset, but maintain - * the current behaviour for now. - */ - printf("Must RESET board to recover\n"); -#ifndef USE_HOSTCC - bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); -#endif - - return BOOTM_ERR_RESET; -} -#endif - -#ifndef USE_HOSTCC -static int bootm_load_os(bootm_headers_t *images, int boot_progress) -{ - image_info_t os = images->os; - ulong load = os.load; - ulong load_end; - ulong blob_start = os.start; - ulong blob_end = os.end; - ulong image_start = os.image_start; - ulong image_len = os.image_len; - ulong flush_start = ALIGN_DOWN(load, ARCH_DMA_MINALIGN); - bool no_overlap; - void *load_buf, *image_buf; - int err; - - load_buf = map_sysmem(load, 0); - image_buf = map_sysmem(os.image_start, image_len); - err = image_decomp(os.comp, load, os.image_start, os.type, - load_buf, image_buf, image_len, - CONFIG_SYS_BOOTM_LEN, &load_end); - if (err) { - err = handle_decomp_error(os.comp, load_end - load, err); - bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); - return err; - } - /* We need the decompressed image size in the next steps */ - images->os.image_len = load_end - load; - - flush_cache(flush_start, ALIGN(load_end, ARCH_DMA_MINALIGN) - flush_start); - - debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, load_end); - bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED); - - no_overlap = (os.comp == IH_COMP_NONE && load == image_start); - - if (!no_overlap && load < blob_end && load_end > blob_start) { - debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n", - blob_start, blob_end); - debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load, - load_end); - - /* Check what type of image this is. */ - if (images->legacy_hdr_valid) { - if (image_get_type(&images->legacy_hdr_os_copy) - == IH_TYPE_MULTI) - puts("WARNING: legacy format multi component image overwritten\n"); - return BOOTM_ERR_OVERLAP; - } else { - puts("ERROR: new format image overwritten - must RESET the board to recover\n"); - bootstage_error(BOOTSTAGE_ID_OVERWRITTEN); - return BOOTM_ERR_RESET; - } - } - - lmb_reserve(&images->lmb, images->os.load, (load_end - - images->os.load)); - return 0; -} - -/** - * bootm_disable_interrupts() - Disable interrupts in preparation for load/boot - * - * @return interrupt flag (0 if interrupts were disabled, non-zero if they were - * enabled) - */ -ulong bootm_disable_interrupts(void) -{ - ulong iflag; - - /* - * We have reached the point of no return: we are going to - * overwrite all exception vector code, so we cannot easily - * recover from any failures any more... - */ - iflag = disable_interrupts(); -#ifdef CONFIG_NETCONSOLE - /* Stop the ethernet stack if NetConsole could have left it up */ - eth_halt(); -# ifndef CONFIG_DM_ETH - eth_unregister(eth_get_dev()); -# endif -#endif - -#if defined(CONFIG_CMD_USB) - /* - * turn off USB to prevent the host controller from writing to the - * SDRAM while Linux is booting. This could happen (at least for OHCI - * controller), because the HCCA (Host Controller Communication Area) - * lies within the SDRAM and the host controller writes continously to - * this area (as busmaster!). The HccaFrameNumber is for example - * updated every 1 ms within the HCCA structure in SDRAM! For more - * details see the OpenHCI specification. - */ - usb_stop(); -#endif - return iflag; -} - -#define CONSOLE_ARG "console=" -#define CONSOLE_ARG_SIZE sizeof(CONSOLE_ARG) - -/** - * fixup_silent_linux() - Handle silencing the linux boot if required - * - * This uses the silent_linux envvar to control whether to add/set a "console=" - * parameter to the command line - * - * @buf: Buffer containing the string to process - * @maxlen: Maximum length of buffer - * @return 0 if OK, -ENOSPC if @maxlen is too small - */ -static int fixup_silent_linux(char *buf, int maxlen) -{ - int want_silent; - char *cmdline; - int size; - - /* - * Move the input string to the end of buffer. The output string will be - * built up at the start. - */ - size = strlen(buf) + 1; - if (size * 2 > maxlen) - return -ENOSPC; - cmdline = buf + maxlen - size; - memmove(cmdline, buf, size); - /* - * Only fix cmdline when requested. The environment variable can be: - * - * no - we never fixup - * yes - we always fixup - * unset - we rely on the console silent flag - */ - want_silent = env_get_yesno("silent_linux"); - if (want_silent == 0) - return 0; - else if (want_silent == -1 && !(gd->flags & GD_FLG_SILENT)) - return 0; - - debug("before silent fix-up: %s\n", cmdline); - if (*cmdline) { - char *start = strstr(cmdline, CONSOLE_ARG); - - /* Check space for maximum possible new command line */ - if (size + CONSOLE_ARG_SIZE > maxlen) - return -ENOSPC; - - if (start) { - char *end = strchr(start, ' '); - int start_bytes; - - start_bytes = start - cmdline + CONSOLE_ARG_SIZE - 1; - strncpy(buf, cmdline, start_bytes); - if (end) - strcpy(buf + start_bytes, end); - else - buf[start_bytes] = '\0'; - } else { - sprintf(buf, "%s %s", cmdline, CONSOLE_ARG); - } - if (buf + strlen(buf) >= cmdline) - return -ENOSPC; - } else { - if (maxlen < sizeof(CONSOLE_ARG)) - return -ENOSPC; - strcpy(buf, CONSOLE_ARG); - } - debug("after silent fix-up: %s\n", buf); - - return 0; -} - -/** - * process_subst() - Handle substitution of ${...} fields in the environment - * - * Handle variable substitution in the provided buffer - * - * @buf: Buffer containing the string to process - * @maxlen: Maximum length of buffer - * @return 0 if OK, -ENOSPC if @maxlen is too small - */ -static int process_subst(char *buf, int maxlen) -{ - char *cmdline; - int size; - int ret; - - /* Move to end of buffer */ - size = strlen(buf) + 1; - cmdline = buf + maxlen - size; - if (buf + size > cmdline) - return -ENOSPC; - memmove(cmdline, buf, size); - - ret = cli_simple_process_macros(cmdline, buf, cmdline - buf); - - return ret; -} - -int bootm_process_cmdline(char *buf, int maxlen, int flags) -{ - int ret; - - /* Check config first to enable compiler to eliminate code */ - if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && - !IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) && - (flags & BOOTM_CL_SILENT)) { - ret = fixup_silent_linux(buf, maxlen); - if (ret) - return log_msg_ret("silent", ret); - } - if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && IS_ENABLED(CONFIG_CMDLINE) && - (flags & BOOTM_CL_SUBST)) { - ret = process_subst(buf, maxlen); - if (ret) - return log_msg_ret("subst", ret); - } - - return 0; -} - -int bootm_process_cmdline_env(int flags) -{ - const int maxlen = MAX_CMDLINE_SIZE; - bool do_silent; - const char *env; - char *buf; - int ret; - - /* First check if any action is needed */ - do_silent = IS_ENABLED(CONFIG_SILENT_CONSOLE) && - !IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) && (flags & BOOTM_CL_SILENT); - if (!do_silent && !IS_ENABLED(CONFIG_BOOTARGS_SUBST)) - return 0; - - env = env_get("bootargs"); - if (env && strlen(env) >= maxlen) - return -E2BIG; - buf = malloc(maxlen); - if (!buf) - return -ENOMEM; - if (env) - strcpy(buf, env); - else - *buf = '\0'; - ret = bootm_process_cmdline(buf, maxlen, flags); - if (!ret) { - ret = env_set("bootargs", buf); - - /* - * If buf is "" and bootargs does not exist, this will produce - * an error trying to delete bootargs. Ignore it - */ - if (ret == -ENOENT) - ret = 0; - } - free(buf); - if (ret) - return log_msg_ret("env", ret); - - return 0; -} - -/** - * Execute selected states of the bootm command. - * - * Note the arguments to this state must be the first argument, Any 'bootm' - * or sub-command arguments must have already been taken. - * - * Note that if states contains more than one flag it MUST contain - * BOOTM_STATE_START, since this handles and consumes the command line args. - * - * Also note that aside from boot_os_fn functions and bootm_load_os no other - * functions we store the return value of in 'ret' may use a negative return - * value, without special handling. - * - * @param cmdtp Pointer to bootm command table entry - * @param flag Command flags (CMD_FLAG_...) - * @param argc Number of subcommand arguments (0 = no arguments) - * @param argv Arguments - * @param states Mask containing states to run (BOOTM_STATE_...) - * @param images Image header information - * @param boot_progress 1 to show boot progress, 0 to not do this - * @return 0 if ok, something else on error. Some errors will cause this - * function to perform a reboot! If states contains BOOTM_STATE_OS_GO - * then the intent is to boot an OS, so this function will not return - * unless the image type is standalone. - */ -int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], int states, bootm_headers_t *images, - int boot_progress) -{ - boot_os_fn *boot_fn; - ulong iflag = 0; - int ret = 0, need_boot_fn; - - images->state |= states; - - /* - * Work through the states and see how far we get. We stop on - * any error. - */ - if (states & BOOTM_STATE_START) - ret = bootm_start(cmdtp, flag, argc, argv); - - if (!ret && (states & BOOTM_STATE_FINDOS)) - ret = bootm_find_os(cmdtp, flag, argc, argv); - - if (!ret && (states & BOOTM_STATE_FINDOTHER)) - ret = bootm_find_other(cmdtp, flag, argc, argv); - - /* Load the OS */ - if (!ret && (states & BOOTM_STATE_LOADOS)) { - iflag = bootm_disable_interrupts(); - ret = bootm_load_os(images, 0); - if (ret && ret != BOOTM_ERR_OVERLAP) - goto err; - else if (ret == BOOTM_ERR_OVERLAP) - ret = 0; - } - - /* Relocate the ramdisk */ -#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH - if (!ret && (states & BOOTM_STATE_RAMDISK)) { - ulong rd_len = images->rd_end - images->rd_start; - - ret = boot_ramdisk_high(&images->lmb, images->rd_start, - rd_len, &images->initrd_start, &images->initrd_end); - if (!ret) { - env_set_hex("initrd_start", images->initrd_start); - env_set_hex("initrd_end", images->initrd_end); - } - } -#endif -#if CONFIG_IS_ENABLED(OF_LIBFDT) && defined(CONFIG_LMB) - if (!ret && (states & BOOTM_STATE_FDT)) { - boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr); - ret = boot_relocate_fdt(&images->lmb, &images->ft_addr, - &images->ft_len); - } -#endif - - /* From now on, we need the OS boot function */ - if (ret) - return ret; - boot_fn = bootm_os_get_boot_func(images->os.os); - need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE | - BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP | - BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO); - if (boot_fn == NULL && need_boot_fn) { - if (iflag) - enable_interrupts(); - printf("ERROR: booting os '%s' (%d) is not supported\n", - genimg_get_os_name(images->os.os), images->os.os); - bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS); - return 1; - } - - - /* Call various other states that are not generally used */ - if (!ret && (states & BOOTM_STATE_OS_CMDLINE)) - ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images); - if (!ret && (states & BOOTM_STATE_OS_BD_T)) - ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images); - if (!ret && (states & BOOTM_STATE_OS_PREP)) { - ret = bootm_process_cmdline_env(images->os.os == IH_OS_LINUX); - if (ret) { - printf("Cmdline setup failed (err=%d)\n", ret); - ret = CMD_RET_FAILURE; - goto err; - } - ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images); - } - -#ifdef CONFIG_TRACE - /* Pretend to run the OS, then run a user command */ - if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) { - char *cmd_list = env_get("fakegocmd"); - - ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO, - images, boot_fn); - if (!ret && cmd_list) - ret = run_command_list(cmd_list, -1, flag); - } -#endif - - /* Check for unsupported subcommand. */ - if (ret) { - puts("subcommand not supported\n"); - return ret; - } - - /* Now run the OS! We hope this doesn't return */ - if (!ret && (states & BOOTM_STATE_OS_GO)) - ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO, - images, boot_fn); - - /* Deal with any fallout */ -err: - if (iflag) - enable_interrupts(); - - if (ret == BOOTM_ERR_UNIMPLEMENTED) - bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL); - else if (ret == BOOTM_ERR_RESET) - do_reset(cmdtp, flag, argc, argv); - - return ret; -} - -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) -/** - * image_get_kernel - verify legacy format kernel image - * @img_addr: in RAM address of the legacy format image to be verified - * @verify: data CRC verification flag - * - * image_get_kernel() verifies legacy image integrity and returns pointer to - * legacy image header if image verification was completed successfully. - * - * returns: - * pointer to a legacy image header if valid image was found - * otherwise return NULL - */ -static image_header_t *image_get_kernel(ulong img_addr, int verify) -{ - image_header_t *hdr = (image_header_t *)img_addr; - - if (!image_check_magic(hdr)) { - puts("Bad Magic Number\n"); - bootstage_error(BOOTSTAGE_ID_CHECK_MAGIC); - return NULL; - } - bootstage_mark(BOOTSTAGE_ID_CHECK_HEADER); - - if (!image_check_hcrc(hdr)) { - puts("Bad Header Checksum\n"); - bootstage_error(BOOTSTAGE_ID_CHECK_HEADER); - return NULL; - } - - bootstage_mark(BOOTSTAGE_ID_CHECK_CHECKSUM); - image_print_contents(hdr); - - if (verify) { - puts(" Verifying Checksum ... "); - if (!image_check_dcrc(hdr)) { - printf("Bad Data CRC\n"); - bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM); - return NULL; - } - puts("OK\n"); - } - bootstage_mark(BOOTSTAGE_ID_CHECK_ARCH); - - if (!image_check_target_arch(hdr)) { - printf("Unsupported Architecture 0x%x\n", image_get_arch(hdr)); - bootstage_error(BOOTSTAGE_ID_CHECK_ARCH); - return NULL; - } - return hdr; -} -#endif - -/** - * boot_get_kernel - find kernel image - * @os_data: pointer to a ulong variable, will hold os data start address - * @os_len: pointer to a ulong variable, will hold os data length - * - * boot_get_kernel() tries to find a kernel image, verifies its integrity - * and locates kernel data. - * - * returns: - * pointer to image header if valid image was found, plus kernel start - * address and length, otherwise NULL - */ -static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], bootm_headers_t *images, - ulong *os_data, ulong *os_len) -{ -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - image_header_t *hdr; -#endif - ulong img_addr; - const void *buf; - const char *fit_uname_config = NULL; - const char *fit_uname_kernel = NULL; -#if CONFIG_IS_ENABLED(FIT) - int os_noffset; -#endif - - img_addr = genimg_get_kernel_addr_fit(argc < 1 ? NULL : argv[0], - &fit_uname_config, - &fit_uname_kernel); - - bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC); - - /* check image type, for FIT images get FIT kernel node */ - *os_data = *os_len = 0; - buf = map_sysmem(img_addr, 0); - switch (genimg_get_format(buf)) { -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - case IMAGE_FORMAT_LEGACY: - printf("## Booting kernel from Legacy Image at %08lx ...\n", - img_addr); - hdr = image_get_kernel(img_addr, images->verify); - if (!hdr) - return NULL; - bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE); - - /* get os_data and os_len */ - switch (image_get_type(hdr)) { - case IH_TYPE_KERNEL: - case IH_TYPE_KERNEL_NOLOAD: - *os_data = image_get_data(hdr); - *os_len = image_get_data_size(hdr); - break; - case IH_TYPE_MULTI: - image_multi_getimg(hdr, 0, os_data, os_len); - break; - case IH_TYPE_STANDALONE: - *os_data = image_get_data(hdr); - *os_len = image_get_data_size(hdr); - break; - default: - printf("Wrong Image Type for %s command\n", - cmdtp->name); - bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE); - return NULL; - } - - /* - * copy image header to allow for image overwrites during - * kernel decompression. - */ - memmove(&images->legacy_hdr_os_copy, hdr, - sizeof(image_header_t)); - - /* save pointer to image header */ - images->legacy_hdr_os = hdr; - - images->legacy_hdr_valid = 1; - bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE); - break; -#endif -#if CONFIG_IS_ENABLED(FIT) - case IMAGE_FORMAT_FIT: - os_noffset = fit_image_load(images, img_addr, - &fit_uname_kernel, &fit_uname_config, - IH_ARCH_DEFAULT, IH_TYPE_KERNEL, - BOOTSTAGE_ID_FIT_KERNEL_START, - FIT_LOAD_IGNORED, os_data, os_len); - if (os_noffset < 0) - return NULL; - - images->fit_hdr_os = map_sysmem(img_addr, 0); - images->fit_uname_os = fit_uname_kernel; - images->fit_uname_cfg = fit_uname_config; - images->fit_noffset_os = os_noffset; - break; -#endif -#ifdef CONFIG_ANDROID_BOOT_IMAGE - case IMAGE_FORMAT_ANDROID: - printf("## Booting Android Image at 0x%08lx ...\n", img_addr); - if (android_image_get_kernel(buf, images->verify, - os_data, os_len)) - return NULL; - break; -#endif - default: - printf("Wrong Image Format for %s command\n", cmdtp->name); - bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO); - return NULL; - } - - debug(" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n", - *os_data, *os_len, *os_len); - - return buf; -} - -/** - * switch_to_non_secure_mode() - switch to non-secure mode - * - * This routine is overridden by architectures requiring this feature. - */ -void __weak switch_to_non_secure_mode(void) -{ -} - -#else /* USE_HOSTCC */ - -#if defined(CONFIG_FIT_SIGNATURE) -static int bootm_host_load_image(const void *fit, int req_image_type, - int cfg_noffset) -{ - const char *fit_uname_config = NULL; - ulong data, len; - bootm_headers_t images; - int noffset; - ulong load_end; - uint8_t image_type; - uint8_t imape_comp; - void *load_buf; - int ret; - - fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL); - memset(&images, '\0', sizeof(images)); - images.verify = 1; - noffset = fit_image_load(&images, (ulong)fit, - NULL, &fit_uname_config, - IH_ARCH_DEFAULT, req_image_type, -1, - FIT_LOAD_IGNORED, &data, &len); - if (noffset < 0) - return noffset; - if (fit_image_get_type(fit, noffset, &image_type)) { - puts("Can't get image type!\n"); - return -EINVAL; - } - - if (fit_image_get_comp(fit, noffset, &imape_comp)) { - puts("Can't get image compression!\n"); - return -EINVAL; - } - - /* Allow the image to expand by a factor of 4, should be safe */ - load_buf = malloc((1 << 20) + len * 4); - ret = image_decomp(imape_comp, 0, data, image_type, load_buf, - (void *)data, len, CONFIG_SYS_BOOTM_LEN, - &load_end); - free(load_buf); - - if (ret) { - ret = handle_decomp_error(imape_comp, load_end - 0, ret); - if (ret != BOOTM_ERR_UNIMPLEMENTED) - return ret; - } - - return 0; -} - -int bootm_host_load_images(const void *fit, int cfg_noffset) -{ - static uint8_t image_types[] = { - IH_TYPE_KERNEL, - IH_TYPE_FLATDT, - IH_TYPE_RAMDISK, - }; - int err = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(image_types); i++) { - int ret; - - ret = bootm_host_load_image(fit, image_types[i], cfg_noffset); - if (!err && ret && ret != -ENOENT) - err = ret; - } - - /* Return the first error we found */ - return err; -} -#endif - -#endif /* ndef USE_HOSTCC */ diff --git a/common/bootm_os.c b/common/bootm_os.c deleted file mode 100644 index 39623f9126b..00000000000 --- a/common/bootm_os.c +++ /dev/null @@ -1,653 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2000-2009 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#include <common.h> -#include <bootm.h> -#include <bootstage.h> -#include <cpu_func.h> -#include <efi_loader.h> -#include <env.h> -#include <fdt_support.h> -#include <image.h> -#include <lmb.h> -#include <log.h> -#include <asm/global_data.h> -#include <linux/libfdt.h> -#include <malloc.h> -#include <mapmem.h> -#include <vxworks.h> -#include <tee/optee.h> - -DECLARE_GLOBAL_DATA_PTR; - -static int do_bootm_standalone(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - char *s; - int (*appl)(int, char *const[]); - - /* Don't start if "autostart" is set to "no" */ - s = env_get("autostart"); - if ((s != NULL) && !strcmp(s, "no")) { - env_set_hex("filesize", images->os.image_len); - return 0; - } - appl = (int (*)(int, char * const []))images->ep; - appl(argc, argv); - return 0; -} - -/*******************************************************************/ -/* OS booting routines */ -/*******************************************************************/ - -#if defined(CONFIG_BOOTM_NETBSD) || defined(CONFIG_BOOTM_PLAN9) -static void copy_args(char *dest, int argc, char *const argv[], char delim) -{ - int i; - - for (i = 0; i < argc; i++) { - if (i > 0) - *dest++ = delim; - strcpy(dest, argv[i]); - dest += strlen(argv[i]); - } -} -#endif - -static void __maybe_unused fit_unsupported_reset(const char *msg) -{ - if (CONFIG_IS_ENABLED(FIT_VERBOSE)) { - printf("! FIT images not supported for '%s' - must reset board to recover!\n", - msg); - } -} - -#ifdef CONFIG_BOOTM_NETBSD -static int do_bootm_netbsd(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - void (*loader)(struct bd_info *, image_header_t *, char *, char *); - image_header_t *os_hdr, *hdr; - ulong kernel_data, kernel_len; - char *cmdline; - - if (flag != BOOTM_STATE_OS_GO) - return 0; - -#if defined(CONFIG_FIT) - if (!images->legacy_hdr_valid) { - fit_unsupported_reset("NetBSD"); - return 1; - } -#endif - hdr = images->legacy_hdr_os; - - /* - * Booting a (NetBSD) kernel image - * - * This process is pretty similar to a standalone application: - * The (first part of an multi-) image must be a stage-2 loader, - * which in turn is responsible for loading & invoking the actual - * kernel. The only differences are the parameters being passed: - * besides the board info strucure, the loader expects a command - * line, the name of the console device, and (optionally) the - * address of the original image header. - */ - os_hdr = NULL; - if (image_check_type(&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { - image_multi_getimg(hdr, 1, &kernel_data, &kernel_len); - if (kernel_len) - os_hdr = hdr; - } - - if (argc > 0) { - ulong len; - int i; - - for (i = 0, len = 0; i < argc; i += 1) - len += strlen(argv[i]) + 1; - cmdline = malloc(len); - copy_args(cmdline, argc, argv, ' '); - } else { - cmdline = env_get("bootargs"); - if (cmdline == NULL) - cmdline = ""; - } - - loader = (void (*)(struct bd_info *, image_header_t *, char *, char *))images->ep; - - printf("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n", - (ulong)loader); - - bootstage_mark(BOOTSTAGE_ID_RUN_OS); - - /* - * NetBSD Stage-2 Loader Parameters: - * arg[0]: pointer to board info data - * arg[1]: image load address - * arg[2]: char pointer to the console device to use - * arg[3]: char pointer to the boot arguments - */ - (*loader)(gd->bd, os_hdr, "", cmdline); - - return 1; -} -#endif /* CONFIG_BOOTM_NETBSD*/ - -#ifdef CONFIG_LYNXKDI -static int do_bootm_lynxkdi(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - image_header_t *hdr = &images->legacy_hdr_os_copy; - - if (flag != BOOTM_STATE_OS_GO) - return 0; - -#if defined(CONFIG_FIT) - if (!images->legacy_hdr_valid) { - fit_unsupported_reset("Lynx"); - return 1; - } -#endif - - lynxkdi_boot((image_header_t *)hdr); - - return 1; -} -#endif /* CONFIG_LYNXKDI */ - -#ifdef CONFIG_BOOTM_RTEMS -static int do_bootm_rtems(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - void (*entry_point)(struct bd_info *); - - if (flag != BOOTM_STATE_OS_GO) - return 0; - -#if defined(CONFIG_FIT) - if (!images->legacy_hdr_valid) { - fit_unsupported_reset("RTEMS"); - return 1; - } -#endif - - entry_point = (void (*)(struct bd_info *))images->ep; - - printf("## Transferring control to RTEMS (at address %08lx) ...\n", - (ulong)entry_point); - - bootstage_mark(BOOTSTAGE_ID_RUN_OS); - - /* - * RTEMS Parameters: - * r3: ptr to board info data - */ - (*entry_point)(gd->bd); - - return 1; -} -#endif /* CONFIG_BOOTM_RTEMS */ - -#if defined(CONFIG_BOOTM_OSE) -static int do_bootm_ose(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - void (*entry_point)(void); - - if (flag != BOOTM_STATE_OS_GO) - return 0; - -#if defined(CONFIG_FIT) - if (!images->legacy_hdr_valid) { - fit_unsupported_reset("OSE"); - return 1; - } -#endif - - entry_point = (void (*)(void))images->ep; - - printf("## Transferring control to OSE (at address %08lx) ...\n", - (ulong)entry_point); - - bootstage_mark(BOOTSTAGE_ID_RUN_OS); - - /* - * OSE Parameters: - * None - */ - (*entry_point)(); - - return 1; -} -#endif /* CONFIG_BOOTM_OSE */ - -#if defined(CONFIG_BOOTM_PLAN9) -static int do_bootm_plan9(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - void (*entry_point)(void); - char *s; - - if (flag != BOOTM_STATE_OS_GO) - return 0; - -#if defined(CONFIG_FIT) - if (!images->legacy_hdr_valid) { - fit_unsupported_reset("Plan 9"); - return 1; - } -#endif - - /* See README.plan9 */ - s = env_get("confaddr"); - if (s != NULL) { - char *confaddr = (char *)hextoul(s, NULL); - - if (argc > 0) { - copy_args(confaddr, argc, argv, '\n'); - } else { - s = env_get("bootargs"); - if (s != NULL) - strcpy(confaddr, s); - } - } - - entry_point = (void (*)(void))images->ep; - - printf("## Transferring control to Plan 9 (at address %08lx) ...\n", - (ulong)entry_point); - - bootstage_mark(BOOTSTAGE_ID_RUN_OS); - - /* - * Plan 9 Parameters: - * None - */ - (*entry_point)(); - - return 1; -} -#endif /* CONFIG_BOOTM_PLAN9 */ - -#if defined(CONFIG_BOOTM_VXWORKS) && \ - (defined(CONFIG_PPC) || defined(CONFIG_ARM)) - -static void do_bootvx_fdt(bootm_headers_t *images) -{ -#if defined(CONFIG_OF_LIBFDT) - int ret; - char *bootline; - ulong of_size = images->ft_len; - char **of_flat_tree = &images->ft_addr; - struct lmb *lmb = &images->lmb; - - if (*of_flat_tree) { - boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree); - - ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); - if (ret) - return; - - /* Update ethernet nodes */ - fdt_fixup_ethernet(*of_flat_tree); - - ret = fdt_add_subnode(*of_flat_tree, 0, "chosen"); - if ((ret >= 0 || ret == -FDT_ERR_EXISTS)) { - bootline = env_get("bootargs"); - if (bootline) { - ret = fdt_find_and_setprop(*of_flat_tree, - "/chosen", "bootargs", - bootline, - strlen(bootline) + 1, 1); - if (ret < 0) { - printf("## ERROR: %s : %s\n", __func__, - fdt_strerror(ret)); - return; - } - } - } else { - printf("## ERROR: %s : %s\n", __func__, - fdt_strerror(ret)); - return; - } - } -#endif - - boot_prep_vxworks(images); - - bootstage_mark(BOOTSTAGE_ID_RUN_OS); - -#if defined(CONFIG_OF_LIBFDT) - printf("## Starting vxWorks at 0x%08lx, device tree at 0x%08lx ...\n", - (ulong)images->ep, (ulong)*of_flat_tree); -#else - printf("## Starting vxWorks at 0x%08lx\n", (ulong)images->ep); -#endif - - boot_jump_vxworks(images); - - puts("## vxWorks terminated\n"); -} - -static int do_bootm_vxworks_legacy(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - if (flag != BOOTM_STATE_OS_GO) - return 0; - -#if defined(CONFIG_FIT) - if (!images->legacy_hdr_valid) { - fit_unsupported_reset("VxWorks"); - return 1; - } -#endif - - do_bootvx_fdt(images); - - return 1; -} - -int do_bootm_vxworks(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - char *bootargs; - int pos; - unsigned long vxflags; - bool std_dtb = false; - - /* get bootargs env */ - bootargs = env_get("bootargs"); - - if (bootargs != NULL) { - for (pos = 0; pos < strlen(bootargs); pos++) { - /* find f=0xnumber flag */ - if ((bootargs[pos] == '=') && (pos >= 1) && - (bootargs[pos - 1] == 'f')) { - vxflags = hextoul(&bootargs[pos + 1], NULL); - if (vxflags & VXWORKS_SYSFLG_STD_DTB) - std_dtb = true; - } - } - } - - if (std_dtb) { - if (flag & BOOTM_STATE_OS_PREP) - printf(" Using standard DTB\n"); - return do_bootm_linux(flag, argc, argv, images); - } else { - if (flag & BOOTM_STATE_OS_PREP) - printf(" !!! WARNING !!! Using legacy DTB\n"); - return do_bootm_vxworks_legacy(flag, argc, argv, images); - } -} -#endif - -#if defined(CONFIG_CMD_ELF) -static int do_bootm_qnxelf(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - char *local_args[2]; - char str[16]; - int dcache; - - if (flag != BOOTM_STATE_OS_GO) - return 0; - -#if defined(CONFIG_FIT) - if (!images->legacy_hdr_valid) { - fit_unsupported_reset("QNX"); - return 1; - } -#endif - - sprintf(str, "%lx", images->ep); /* write entry-point into string */ - local_args[0] = argv[0]; - local_args[1] = str; /* and provide it via the arguments */ - - /* - * QNX images require the data cache is disabled. - */ - dcache = dcache_status(); - if (dcache) - dcache_disable(); - - do_bootelf(NULL, 0, 2, local_args); - - if (dcache) - dcache_enable(); - - return 1; -} -#endif - -#ifdef CONFIG_INTEGRITY -static int do_bootm_integrity(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - void (*entry_point)(void); - - if (flag != BOOTM_STATE_OS_GO) - return 0; - -#if defined(CONFIG_FIT) - if (!images->legacy_hdr_valid) { - fit_unsupported_reset("INTEGRITY"); - return 1; - } -#endif - - entry_point = (void (*)(void))images->ep; - - printf("## Transferring control to INTEGRITY (at address %08lx) ...\n", - (ulong)entry_point); - - bootstage_mark(BOOTSTAGE_ID_RUN_OS); - - /* - * INTEGRITY Parameters: - * None - */ - (*entry_point)(); - - return 1; -} -#endif - -#ifdef CONFIG_BOOTM_OPENRTOS -static int do_bootm_openrtos(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - void (*entry_point)(void); - - if (flag != BOOTM_STATE_OS_GO) - return 0; - - entry_point = (void (*)(void))images->ep; - - printf("## Transferring control to OpenRTOS (at address %08lx) ...\n", - (ulong)entry_point); - - bootstage_mark(BOOTSTAGE_ID_RUN_OS); - - /* - * OpenRTOS Parameters: - * None - */ - (*entry_point)(); - - return 1; -} -#endif - -#ifdef CONFIG_BOOTM_OPTEE -static int do_bootm_tee(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - int ret; - - /* Verify OS type */ - if (images->os.os != IH_OS_TEE) { - return 1; - }; - - /* Validate OPTEE header */ - ret = optee_verify_bootm_image(images->os.image_start, - images->os.load, - images->os.image_len); - if (ret) - return ret; - - /* Locate FDT etc */ - ret = bootm_find_images(flag, argc, argv, 0, 0); - if (ret) - return ret; - - /* From here we can run the regular linux boot path */ - return do_bootm_linux(flag, argc, argv, images); -} -#endif - -#ifdef CONFIG_BOOTM_EFI -static int do_bootm_efi(int flag, int argc, char *const argv[], - bootm_headers_t *images) -{ - int ret; - efi_status_t efi_ret; - void *image_buf; - - if (flag != BOOTM_STATE_OS_GO) - return 0; - - /* Locate FDT, if provided */ - ret = bootm_find_images(flag, argc, argv, 0, 0); - if (ret) - return ret; - - /* Initialize EFI drivers */ - efi_ret = efi_init_obj_list(); - if (efi_ret != EFI_SUCCESS) { - printf("## Failed to initialize UEFI sub-system: r = %lu\n", - efi_ret & ~EFI_ERROR_MASK); - return 1; - } - - /* Install device tree */ - efi_ret = efi_install_fdt(images->ft_len - ? images->ft_addr : EFI_FDT_USE_INTERNAL); - if (efi_ret != EFI_SUCCESS) { - printf("## Failed to install device tree: r = %lu\n", - efi_ret & ~EFI_ERROR_MASK); - return 1; - } - - /* Run EFI image */ - printf("## Transferring control to EFI (at address %08lx) ...\n", - images->ep); - bootstage_mark(BOOTSTAGE_ID_RUN_OS); - - /* We expect to return */ - images->os.type = IH_TYPE_STANDALONE; - - image_buf = map_sysmem(images->ep, images->os.image_len); - - efi_ret = efi_run_image(image_buf, images->os.image_len); - if (efi_ret != EFI_SUCCESS) - return 1; - return 0; -} -#endif - -static boot_os_fn *boot_os[] = { - [IH_OS_U_BOOT] = do_bootm_standalone, -#ifdef CONFIG_BOOTM_LINUX - [IH_OS_LINUX] = do_bootm_linux, -#endif -#ifdef CONFIG_BOOTM_NETBSD - [IH_OS_NETBSD] = do_bootm_netbsd, -#endif -#ifdef CONFIG_LYNXKDI - [IH_OS_LYNXOS] = do_bootm_lynxkdi, -#endif -#ifdef CONFIG_BOOTM_RTEMS - [IH_OS_RTEMS] = do_bootm_rtems, -#endif -#if defined(CONFIG_BOOTM_OSE) - [IH_OS_OSE] = do_bootm_ose, -#endif -#if defined(CONFIG_BOOTM_PLAN9) - [IH_OS_PLAN9] = do_bootm_plan9, -#endif -#if defined(CONFIG_BOOTM_VXWORKS) && \ - (defined(CONFIG_PPC) || defined(CONFIG_ARM) || defined(CONFIG_RISCV)) - [IH_OS_VXWORKS] = do_bootm_vxworks, -#endif -#if defined(CONFIG_CMD_ELF) - [IH_OS_QNX] = do_bootm_qnxelf, -#endif -#ifdef CONFIG_INTEGRITY - [IH_OS_INTEGRITY] = do_bootm_integrity, -#endif -#ifdef CONFIG_BOOTM_OPENRTOS - [IH_OS_OPENRTOS] = do_bootm_openrtos, -#endif -#ifdef CONFIG_BOOTM_OPTEE - [IH_OS_TEE] = do_bootm_tee, -#endif -#ifdef CONFIG_BOOTM_EFI - [IH_OS_EFI] = do_bootm_efi, -#endif -}; - -/* Allow for arch specific config before we boot */ -__weak void arch_preboot_os(void) -{ - /* please define platform specific arch_preboot_os() */ -} - -/* Allow for board specific config before we boot */ -__weak void board_preboot_os(void) -{ - /* please define board specific board_preboot_os() */ -} - -int boot_selected_os(int argc, char *const argv[], int state, - bootm_headers_t *images, boot_os_fn *boot_fn) -{ - arch_preboot_os(); - board_preboot_os(); - boot_fn(state, argc, argv, images); - - /* Stand-alone may return when 'autostart' is 'no' */ - if (images->os.type == IH_TYPE_STANDALONE || - IS_ENABLED(CONFIG_SANDBOX) || - state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */ - return 0; - bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED); - debug("\n## Control returned to monitor - resetting...\n"); - - return BOOTM_ERR_RESET; -} - -boot_os_fn *bootm_os_get_boot_func(int os) -{ -#ifdef CONFIG_NEEDS_MANUAL_RELOC - static bool relocated; - - if (!relocated) { - int i; - - /* relocate boot function table */ - for (i = 0; i < ARRAY_SIZE(boot_os); i++) - if (boot_os[i] != NULL) - boot_os[i] += gd->reloc_off; - - relocated = true; - } -#endif - return boot_os[os]; -} diff --git a/common/bootretry.c b/common/bootretry.c deleted file mode 100644 index dac891fbc5e..00000000000 --- a/common/bootretry.c +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#include <common.h> -#include <bootretry.h> -#include <cli.h> -#include <env.h> -#include <errno.h> -#include <time.h> -#include <watchdog.h> - -#ifndef CONFIG_BOOT_RETRY_MIN -#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME -#endif - -static uint64_t endtime; /* must be set, default is instant timeout */ -static int retry_time = -1; /* -1 so can call readline before main_loop */ - -/*************************************************************************** - * initialize command line timeout - */ -void bootretry_init_cmd_timeout(void) -{ - char *s = env_get("bootretry"); - - if (s != NULL) - retry_time = (int)simple_strtol(s, NULL, 10); - else - retry_time = CONFIG_BOOT_RETRY_TIME; - - if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN) - retry_time = CONFIG_BOOT_RETRY_MIN; -} - -/*************************************************************************** - * reset command line timeout to retry_time seconds - */ -void bootretry_reset_cmd_timeout(void) -{ - endtime = endtick(retry_time); -} - -int bootretry_tstc_timeout(void) -{ - while (!tstc()) { /* while no incoming data */ - if (retry_time >= 0 && get_ticks() > endtime) - return -ETIMEDOUT; - WATCHDOG_RESET(); - } - - return 0; -} - -void bootretry_dont_retry(void) -{ - retry_time = -1; -} diff --git a/common/common_fit.c b/common/common_fit.c deleted file mode 100644 index cde2dc45e90..00000000000 --- a/common/common_fit.c +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2016 Google, Inc - * Written by Simon Glass <sjg@chromium.org> - */ - -#include <common.h> -#include <errno.h> -#include <image.h> -#include <log.h> -#include <linux/libfdt.h> - -ulong fdt_getprop_u32(const void *fdt, int node, const char *prop) -{ - const u32 *cell; - int len; - - cell = fdt_getprop(fdt, node, prop, &len); - if (!cell || len != sizeof(*cell)) - return FDT_ERROR; - - return fdt32_to_cpu(*cell); -} - -__weak int board_fit_config_name_match(const char *name) -{ - return -EINVAL; -} - -/* - * Iterate over all /configurations subnodes and call a platform specific - * function to find the matching configuration. - * Returns the node offset or a negative error number. - */ -int fit_find_config_node(const void *fdt) -{ - const char *name; - int conf, node, len; - const char *dflt_conf_name; - const char *dflt_conf_desc = NULL; - int dflt_conf_node = -ENOENT; - - conf = fdt_path_offset(fdt, FIT_CONFS_PATH); - if (conf < 0) { - debug("%s: Cannot find /configurations node: %d\n", __func__, - conf); - return -EINVAL; - } - - dflt_conf_name = fdt_getprop(fdt, conf, "default", &len); - - for (node = fdt_first_subnode(fdt, conf); - node >= 0; - node = fdt_next_subnode(fdt, node)) { - name = fdt_getprop(fdt, node, "description", &len); - if (!name) { -#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - printf("%s: Missing FDT description in DTB\n", - __func__); -#endif - return -EINVAL; - } - - if (dflt_conf_name) { - const char *node_name = fdt_get_name(fdt, node, NULL); - if (strcmp(dflt_conf_name, node_name) == 0) { - dflt_conf_node = node; - dflt_conf_desc = name; - } - } - - if (board_fit_config_name_match(name)) - continue; - - debug("Selecting config '%s'\n", name); - - return node; - } - - if (dflt_conf_node != -ENOENT) { - debug("Selecting default config '%s'\n", dflt_conf_desc); - return dflt_conf_node; - } - - return -ENOENT; -} diff --git a/common/fdt_region.c b/common/fdt_region.c deleted file mode 100644 index e4ef0ca7703..00000000000 --- a/common/fdt_region.c +++ /dev/null @@ -1,671 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2013 Google, Inc - * Written by Simon Glass <sjg@chromium.org> - */ - -#include <fdt_support.h> -#include <linux/libfdt_env.h> -#include <fdt_region.h> - -#ifndef USE_HOSTCC -#include <fdt.h> -#include <linux/libfdt.h> -#else -#include "fdt_host.h" -#endif - -#define FDT_MAX_DEPTH 32 - -static int str_in_list(const char *str, char * const list[], int count) -{ - int i; - - for (i = 0; i < count; i++) - if (!strcmp(list[i], str)) - return 1; - - return 0; -} - -int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, - char * const exc_prop[], int exc_prop_count, - struct fdt_region region[], int max_regions, - char *path, int path_len, int add_string_tab) -{ - int stack[FDT_MAX_DEPTH] = { 0 }; - char *end; - int nextoffset = 0; - uint32_t tag; - int count = 0; - int start = -1; - int depth = -1; - int want = 0; - int base = fdt_off_dt_struct(fdt); - bool expect_end = false; - - end = path; - *end = '\0'; - do { - const struct fdt_property *prop; - const char *name; - const char *str; - int include = 0; - int stop_at = 0; - int offset; - int len; - - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - stop_at = nextoffset; - - /* If we see two root nodes, something is wrong */ - if (expect_end && tag != FDT_END) - return -FDT_ERR_BADLAYOUT; - - switch (tag) { - case FDT_PROP: - include = want >= 2; - stop_at = offset; - prop = fdt_get_property_by_offset(fdt, offset, NULL); - str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - if (!str) - return -FDT_ERR_BADSTRUCTURE; - if (str_in_list(str, exc_prop, exc_prop_count)) - include = 0; - break; - - case FDT_NOP: - include = want >= 2; - stop_at = offset; - break; - - case FDT_BEGIN_NODE: - depth++; - if (depth == FDT_MAX_DEPTH) - return -FDT_ERR_BADSTRUCTURE; - name = fdt_get_name(fdt, offset, &len); - - /* The root node must have an empty name */ - if (!depth && *name) - return -FDT_ERR_BADLAYOUT; - if (end - path + 2 + len >= path_len) - return -FDT_ERR_NOSPACE; - if (end != path + 1) - *end++ = '/'; - strcpy(end, name); - end += len; - stack[depth] = want; - if (want == 1) - stop_at = offset; - if (str_in_list(path, inc, inc_count)) - want = 2; - else if (want) - want--; - else - stop_at = offset; - include = want; - break; - - case FDT_END_NODE: - /* Depth must never go below -1 */ - if (depth < 0) - return -FDT_ERR_BADSTRUCTURE; - include = want; - want = stack[depth--]; - while (end > path && *--end != '/') - ; - *end = '\0'; - if (depth == -1) - expect_end = true; - break; - - case FDT_END: - include = 1; - break; - } - - if (include && start == -1) { - /* Should we merge with previous? */ - if (count && count <= max_regions && - offset == region[count - 1].offset + - region[count - 1].size - base) - start = region[--count].offset - base; - else - start = offset; - } - - if (!include && start != -1) { - if (count < max_regions) { - region[count].offset = base + start; - region[count].size = stop_at - start; - } - count++; - start = -1; - } - } while (tag != FDT_END); - - if (nextoffset != fdt_size_dt_struct(fdt)) - return -FDT_ERR_BADLAYOUT; - - /* Add a region for the END tag and the string table */ - if (count < max_regions) { - region[count].offset = base + start; - region[count].size = nextoffset - start; - if (add_string_tab) - region[count].size += fdt_size_dt_strings(fdt); - } - count++; - - return count; -} - -/** - * fdt_add_region() - Add a new region to our list - * @info: State information - * @offset: Start offset of region - * @size: Size of region - * - * The region is added if there is space, but in any case we increment the - * count. If permitted, and the new region overlaps the last one, we merge - * them. - */ -static int fdt_add_region(struct fdt_region_state *info, int offset, int size) -{ - struct fdt_region *reg; - - reg = info->region ? &info->region[info->count - 1] : NULL; - if (info->can_merge && info->count && - info->count <= info->max_regions && - reg && offset <= reg->offset + reg->size) { - reg->size = offset + size - reg->offset; - } else if (info->count++ < info->max_regions) { - if (reg) { - reg++; - reg->offset = offset; - reg->size = size; - } - } else { - return -1; - } - - return 0; -} - -static int region_list_contains_offset(struct fdt_region_state *info, - const void *fdt, int target) -{ - struct fdt_region *reg; - int num; - - target += fdt_off_dt_struct(fdt); - for (reg = info->region, num = 0; num < info->count; reg++, num++) { - if (target >= reg->offset && target < reg->offset + reg->size) - return 1; - } - - return 0; -} - -/** - * fdt_add_alias_regions() - Add regions covering the aliases that we want - * - * The /aliases node is not automatically included by fdtgrep unless the - * command-line arguments cause to be included (or not excluded). However - * aliases are special in that we generally want to include those which - * reference a node that fdtgrep includes. - * - * In fact we want to include only aliases for those nodes still included in - * the fdt, and drop the other aliases since they point to nodes that will not - * be present. - * - * This function scans the aliases and adds regions for those which we want - * to keep. - * - * @fdt: Device tree to scan - * @region: List of regions - * @count: Number of regions in the list so far (i.e. starting point for this - * function) - * @max_regions: Maximum number of regions in @region list - * @info: Place to put the region state - * @return number of regions after processing, or -FDT_ERR_NOSPACE if we did - * not have enough room in the regions table for the regions we wanted to add. - */ -int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count, - int max_regions, struct fdt_region_state *info) -{ - int base = fdt_off_dt_struct(fdt); - int node, node_end, offset; - int did_alias_header; - - node = fdt_subnode_offset(fdt, 0, "aliases"); - if (node < 0) - return -FDT_ERR_NOTFOUND; - - /* - * Find the next node so that we know where the /aliases node ends. We - * need special handling if /aliases is the last node. - */ - node_end = fdt_next_subnode(fdt, node); - if (node_end == -FDT_ERR_NOTFOUND) - /* Move back to the FDT_END_NODE tag of '/' */ - node_end = fdt_size_dt_struct(fdt) - sizeof(fdt32_t) * 2; - else if (node_end < 0) /* other error */ - return node_end; - node_end -= sizeof(fdt32_t); /* Move to FDT_END_NODE tag of /aliases */ - - did_alias_header = 0; - info->region = region; - info->count = count; - info->can_merge = 0; - info->max_regions = max_regions; - - for (offset = fdt_first_property_offset(fdt, node); - offset >= 0; - offset = fdt_next_property_offset(fdt, offset)) { - const struct fdt_property *prop; - const char *name; - int target, next; - - prop = fdt_get_property_by_offset(fdt, offset, NULL); - name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - target = fdt_path_offset(fdt, name); - if (!region_list_contains_offset(info, fdt, target)) - continue; - next = fdt_next_property_offset(fdt, offset); - if (next < 0) - next = node_end; - - if (!did_alias_header) { - fdt_add_region(info, base + node, 12); - did_alias_header = 1; - } - fdt_add_region(info, base + offset, next - offset); - } - - /* Add the FDT_END_NODE tag */ - if (did_alias_header) - fdt_add_region(info, base + node_end, sizeof(fdt32_t)); - - return info->count < max_regions ? info->count : -FDT_ERR_NOSPACE; -} - -/** - * fdt_include_supernodes() - Include supernodes required by this node - * @info: State information - * @depth: Current stack depth - * - * When we decided to include a node or property which is not at the top - * level, this function forces the inclusion of higher level nodes. For - * example, given this tree: - * - * / { - * testing { - * } - * } - * - * If we decide to include testing then we need the root node to have a valid - * tree. This function adds those regions. - */ -static int fdt_include_supernodes(struct fdt_region_state *info, int depth) -{ - int base = fdt_off_dt_struct(info->fdt); - int start, stop_at; - int i; - - /* - * Work down the stack looking for supernodes that we didn't include. - * The algortihm here is actually pretty simple, since we know that - * no previous subnode had to include these nodes, or if it did, we - * marked them as included (on the stack) already. - */ - for (i = 0; i <= depth; i++) { - if (!info->stack[i].included) { - start = info->stack[i].offset; - - /* Add the FDT_BEGIN_NODE tag of this supernode */ - fdt_next_tag(info->fdt, start, &stop_at); - if (fdt_add_region(info, base + start, stop_at - start)) - return -1; - - /* Remember that this supernode is now included */ - info->stack[i].included = 1; - info->can_merge = 1; - } - - /* Force (later) generation of the FDT_END_NODE tag */ - if (!info->stack[i].want) - info->stack[i].want = WANT_NODES_ONLY; - } - - return 0; -} - -enum { - FDT_DONE_NOTHING, - FDT_DONE_MEM_RSVMAP, - FDT_DONE_STRUCT, - FDT_DONE_END, - FDT_DONE_STRINGS, - FDT_DONE_ALL, -}; - -int fdt_first_region(const void *fdt, - int (*h_include)(void *priv, const void *fdt, int offset, - int type, const char *data, int size), - void *priv, struct fdt_region *region, - char *path, int path_len, int flags, - struct fdt_region_state *info) -{ - struct fdt_region_ptrs *p = &info->ptrs; - - /* Set up our state */ - info->fdt = fdt; - info->can_merge = 1; - info->max_regions = 1; - info->start = -1; - p->want = WANT_NOTHING; - p->end = path; - *p->end = '\0'; - p->nextoffset = 0; - p->depth = -1; - p->done = FDT_DONE_NOTHING; - - return fdt_next_region(fdt, h_include, priv, region, - path, path_len, flags, info); -} - -/*********************************************************************** - * - * Theory of operation - * - * Note: in this description 'included' means that a node (or other part - * of the tree) should be included in the region list, i.e. it will have - * a region which covers its part of the tree. - * - * This function maintains some state from the last time it is called. - * It checks the next part of the tree that it is supposed to look at - * (p.nextoffset) to see if that should be included or not. When it - * finds something to include, it sets info->start to its offset. This - * marks the start of the region we want to include. - * - * Once info->start is set to the start (i.e. not -1), we continue - * scanning until we find something that we don't want included. This - * will be the end of a region. At this point we can close off the - * region and add it to the list. So we do so, and reset info->start - * to -1. - * - * One complication here is that we want to merge regions. So when we - * come to add another region later, we may in fact merge it with the - * previous one if one ends where the other starts. - * - * The function fdt_add_region() will return -1 if it fails to add the - * region, because we already have a region ready to be returned, and - * the new one cannot be merged in with it. In this case, we must return - * the region we found, and wait for another call to this function. - * When it comes, we will repeat the processing of the tag and again - * try to add a region. This time it will succeed. - * - * The current state of the pointers (stack, offset, etc.) is maintained - * in a ptrs member. At the start of every loop iteration we make a copy - * of it. The copy is then updated as the tag is processed. Only if we - * get to the end of the loop iteration (and successfully call - * fdt_add_region() if we need to) can we commit the changes we have - * made to these pointers. For example, if we see an FDT_END_NODE tag, - * we will decrement the depth value. But if we need to add a region - * for this tag (let's say because the previous tag is included and this - * FDT_END_NODE tag is not included) then we will only commit the result - * if we were able to add the region. That allows us to retry again next - * time. - * - * We keep track of a variable called 'want' which tells us what we want - * to include when there is no specific information provided by the - * h_include function for a particular property. This basically handles - * the inclusion of properties which are pulled in by virtue of the node - * they are in. So if you include a node, its properties are also - * included. In this case 'want' will be WANT_NODES_AND_PROPS. The - * FDT_REG_DIRECT_SUBNODES feature also makes use of 'want'. While we - * are inside the subnode, 'want' will be set to WANT_NODES_ONLY, so - * that only the subnode's FDT_BEGIN_NODE and FDT_END_NODE tags will be - * included, and properties will be skipped. If WANT_NOTHING is - * selected, then we will just rely on what the h_include() function - * tells us. - * - * Using 'want' we work out 'include', which tells us whether this - * current tag should be included or not. As you can imagine, if the - * value of 'include' changes, that means we are on a boundary between - * nodes to include and nodes to exclude. At this point we either close - * off a previous region and add it to the list, or mark the start of a - * new region. - * - * Apart from the nodes, we have mem_rsvmap, the FDT_END tag and the - * string list. Each of these dealt with as a whole (i.e. we create a - * region for each if it is to be included). For mem_rsvmap we don't - * allow it to merge with the first struct region. For the stringlist, - * we don't allow it to merge with the last struct region (which - * contains at minimum the FDT_END tag). - * - *********************************************************************/ - -int fdt_next_region(const void *fdt, - int (*h_include)(void *priv, const void *fdt, int offset, - int type, const char *data, int size), - void *priv, struct fdt_region *region, - char *path, int path_len, int flags, - struct fdt_region_state *info) -{ - int base = fdt_off_dt_struct(fdt); - int last_node = 0; - const char *str; - - info->region = region; - info->count = 0; - if (info->ptrs.done < FDT_DONE_MEM_RSVMAP && - (flags & FDT_REG_ADD_MEM_RSVMAP)) { - /* Add the memory reserve map into its own region */ - if (fdt_add_region(info, fdt_off_mem_rsvmap(fdt), - fdt_off_dt_struct(fdt) - - fdt_off_mem_rsvmap(fdt))) - return 0; - info->can_merge = 0; /* Don't allow merging with this */ - info->ptrs.done = FDT_DONE_MEM_RSVMAP; - } - - /* - * Work through the tags one by one, deciding whether each needs to - * be included or not. We set the variable 'include' to indicate our - * decision. 'want' is used to track what we want to include - it - * allows us to pick up all the properties (and/or subnode tags) of - * a node. - */ - while (info->ptrs.done < FDT_DONE_STRUCT) { - const struct fdt_property *prop; - struct fdt_region_ptrs p; - const char *name; - int include = 0; - int stop_at = 0; - uint32_t tag; - int offset; - int val; - int len; - - /* - * Make a copy of our pointers. If we make it to the end of - * this block then we will commit them back to info->ptrs. - * Otherwise we can try again from the same starting state - * next time we are called. - */ - p = info->ptrs; - - /* - * Find the tag, and the offset of the next one. If we need to - * stop including tags, then by default we stop *after* - * including the current tag - */ - offset = p.nextoffset; - tag = fdt_next_tag(fdt, offset, &p.nextoffset); - stop_at = p.nextoffset; - - switch (tag) { - case FDT_PROP: - stop_at = offset; - prop = fdt_get_property_by_offset(fdt, offset, NULL); - str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - val = h_include(priv, fdt, last_node, FDT_IS_PROP, str, - strlen(str) + 1); - if (val == -1) { - include = p.want >= WANT_NODES_AND_PROPS; - } else { - include = val; - /* - * Make sure we include the } for this block. - * It might be more correct to have this done - * by the call to fdt_include_supernodes() in - * the case where it adds the node we are - * currently in, but this is equivalent. - */ - if ((flags & FDT_REG_SUPERNODES) && val && - !p.want) - p.want = WANT_NODES_ONLY; - } - - /* Value grepping is not yet supported */ - break; - - case FDT_NOP: - include = p.want >= WANT_NODES_AND_PROPS; - stop_at = offset; - break; - - case FDT_BEGIN_NODE: - last_node = offset; - p.depth++; - if (p.depth == FDT_MAX_DEPTH) - return -FDT_ERR_BADSTRUCTURE; - name = fdt_get_name(fdt, offset, &len); - if (p.end - path + 2 + len >= path_len) - return -FDT_ERR_NOSPACE; - - /* Build the full path of this node */ - if (p.end != path + 1) - *p.end++ = '/'; - strcpy(p.end, name); - p.end += len; - info->stack[p.depth].want = p.want; - info->stack[p.depth].offset = offset; - - /* - * If we are not intending to include this node unless - * it matches, make sure we stop *before* its tag. - */ - if (p.want == WANT_NODES_ONLY || - !(flags & (FDT_REG_DIRECT_SUBNODES | - FDT_REG_ALL_SUBNODES))) { - stop_at = offset; - p.want = WANT_NOTHING; - } - val = h_include(priv, fdt, offset, FDT_IS_NODE, path, - p.end - path + 1); - - /* Include this if requested */ - if (val) { - p.want = (flags & FDT_REG_ALL_SUBNODES) ? - WANT_ALL_NODES_AND_PROPS : - WANT_NODES_AND_PROPS; - } - - /* If not requested, decay our 'p.want' value */ - else if (p.want) { - if (p.want != WANT_ALL_NODES_AND_PROPS) - p.want--; - - /* Not including this tag, so stop now */ - } else { - stop_at = offset; - } - - /* - * Decide whether to include this tag, and update our - * stack with the state for this node - */ - include = p.want; - info->stack[p.depth].included = include; - break; - - case FDT_END_NODE: - include = p.want; - if (p.depth < 0) - return -FDT_ERR_BADSTRUCTURE; - - /* - * If we don't want this node, stop right away, unless - * we are including subnodes - */ - if (!p.want && !(flags & FDT_REG_DIRECT_SUBNODES)) - stop_at = offset; - p.want = info->stack[p.depth].want; - p.depth--; - while (p.end > path && *--p.end != '/') - ; - *p.end = '\0'; - break; - - case FDT_END: - /* We always include the end tag */ - include = 1; - p.done = FDT_DONE_STRUCT; - break; - } - - /* If this tag is to be included, mark it as region start */ - if (include && info->start == -1) { - /* Include any supernodes required by this one */ - if (flags & FDT_REG_SUPERNODES) { - if (fdt_include_supernodes(info, p.depth)) - return 0; - } - info->start = offset; - } - - /* - * If this tag is not to be included, finish up the current - * region. - */ - if (!include && info->start != -1) { - if (fdt_add_region(info, base + info->start, - stop_at - info->start)) - return 0; - info->start = -1; - info->can_merge = 1; - } - - /* If we have made it this far, we can commit our pointers */ - info->ptrs = p; - } - - /* Add a region for the END tag and a separate one for string table */ - if (info->ptrs.done < FDT_DONE_END) { - if (info->ptrs.nextoffset != fdt_size_dt_struct(fdt)) - return -FDT_ERR_BADSTRUCTURE; - - if (fdt_add_region(info, base + info->start, - info->ptrs.nextoffset - info->start)) - return 0; - info->ptrs.done++; - } - if (info->ptrs.done < FDT_DONE_STRINGS) { - if (flags & FDT_REG_ADD_STRING_TAB) { - info->can_merge = 0; - if (fdt_off_dt_strings(fdt) < - base + info->ptrs.nextoffset) - return -FDT_ERR_BADLAYOUT; - if (fdt_add_region(info, fdt_off_dt_strings(fdt), - fdt_size_dt_strings(fdt))) - return 0; - } - info->ptrs.done++; - } - - return info->count > 0 ? 0 : -FDT_ERR_NOTFOUND; -} diff --git a/common/image-android-dt.c b/common/image-android-dt.c deleted file mode 100644 index a2d52df4a2a..00000000000 --- a/common/image-android-dt.c +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2018 Linaro Ltd. - * Sam Protsenko <semen.protsenko@linaro.org> - */ - -#include <image-android-dt.h> -#include <dt_table.h> -#include <common.h> -#include <linux/libfdt.h> -#include <mapmem.h> - -/** - * Check if image header is correct. - * - * @param hdr_addr Start address of DT image - * @return true if header is correct or false if header is incorrect - */ -bool android_dt_check_header(ulong hdr_addr) -{ - const struct dt_table_header *hdr; - u32 magic; - - hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - magic = fdt32_to_cpu(hdr->magic); - unmap_sysmem(hdr); - - return magic == DT_TABLE_MAGIC; -} - -/** - * Get the address of FDT (dtb or dtbo) in memory by its index in image. - * - * @param hdr_addr Start address of DT image - * @param index Index of desired FDT in image (starting from 0) - * @param[out] addr If not NULL, will contain address to specified FDT - * @param[out] size If not NULL, will contain size of specified FDT - * - * @return true on success or false on error - */ -bool android_dt_get_fdt_by_index(ulong hdr_addr, u32 index, ulong *addr, - u32 *size) -{ - const struct dt_table_header *hdr; - const struct dt_table_entry *e; - u32 entry_count, entries_offset, entry_size; - ulong e_addr; - u32 dt_offset, dt_size; - - hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - entry_count = fdt32_to_cpu(hdr->dt_entry_count); - entries_offset = fdt32_to_cpu(hdr->dt_entries_offset); - entry_size = fdt32_to_cpu(hdr->dt_entry_size); - unmap_sysmem(hdr); - - if (index >= entry_count) { - printf("Error: index >= dt_entry_count (%u >= %u)\n", index, - entry_count); - return false; - } - - e_addr = hdr_addr + entries_offset + index * entry_size; - e = map_sysmem(e_addr, sizeof(*e)); - dt_offset = fdt32_to_cpu(e->dt_offset); - dt_size = fdt32_to_cpu(e->dt_size); - unmap_sysmem(e); - - if (addr) - *addr = hdr_addr + dt_offset; - if (size) - *size = dt_size; - - return true; -} - -#if !defined(CONFIG_SPL_BUILD) -static void android_dt_print_fdt_info(const struct fdt_header *fdt) -{ - u32 fdt_size; - int root_node_off; - const char *compatible; - - root_node_off = fdt_path_offset(fdt, "/"); - if (root_node_off < 0) { - printf("Error: Root node not found\n"); - return; - } - - fdt_size = fdt_totalsize(fdt); - compatible = fdt_getprop(fdt, root_node_off, "compatible", - NULL); - - printf(" (FDT)size = %d\n", fdt_size); - printf(" (FDT)compatible = %s\n", - compatible ? compatible : "(unknown)"); -} - -/** - * Print information about DT image structure. - * - * @param hdr_addr Start address of DT image - */ -void android_dt_print_contents(ulong hdr_addr) -{ - const struct dt_table_header *hdr; - u32 entry_count, entries_offset, entry_size; - u32 i; - - hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - entry_count = fdt32_to_cpu(hdr->dt_entry_count); - entries_offset = fdt32_to_cpu(hdr->dt_entries_offset); - entry_size = fdt32_to_cpu(hdr->dt_entry_size); - - /* Print image header info */ - printf("dt_table_header:\n"); - printf(" magic = %08x\n", fdt32_to_cpu(hdr->magic)); - printf(" total_size = %d\n", fdt32_to_cpu(hdr->total_size)); - printf(" header_size = %d\n", fdt32_to_cpu(hdr->header_size)); - printf(" dt_entry_size = %d\n", entry_size); - printf(" dt_entry_count = %d\n", entry_count); - printf(" dt_entries_offset = %d\n", entries_offset); - printf(" page_size = %d\n", fdt32_to_cpu(hdr->page_size)); - printf(" version = %d\n", fdt32_to_cpu(hdr->version)); - - unmap_sysmem(hdr); - - /* Print image entries info */ - for (i = 0; i < entry_count; ++i) { - const ulong e_addr = hdr_addr + entries_offset + i * entry_size; - const struct dt_table_entry *e; - const struct fdt_header *fdt; - u32 dt_offset, dt_size; - u32 j; - - e = map_sysmem(e_addr, sizeof(*e)); - dt_offset = fdt32_to_cpu(e->dt_offset); - dt_size = fdt32_to_cpu(e->dt_size); - - printf("dt_table_entry[%d]:\n", i); - printf(" dt_size = %d\n", dt_size); - printf(" dt_offset = %d\n", dt_offset); - printf(" id = %08x\n", fdt32_to_cpu(e->id)); - printf(" rev = %08x\n", fdt32_to_cpu(e->rev)); - for (j = 0; j < 4; ++j) { - printf(" custom[%d] = %08x\n", j, - fdt32_to_cpu(e->custom[j])); - } - - unmap_sysmem(e); - - /* Print FDT info for this entry */ - fdt = map_sysmem(hdr_addr + dt_offset, sizeof(*fdt)); - android_dt_print_fdt_info(fdt); - unmap_sysmem(fdt); - } -} -#endif diff --git a/common/image-android.c b/common/image-android.c deleted file mode 100644 index 1fbbbba1eb0..00000000000 --- a/common/image-android.c +++ /dev/null @@ -1,539 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> - */ - -#include <common.h> -#include <env.h> -#include <image.h> -#include <image-android-dt.h> -#include <android_image.h> -#include <malloc.h> -#include <errno.h> -#include <asm/unaligned.h> -#include <mapmem.h> -#include <linux/libfdt.h> - -#define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000 - -static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1]; - -static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr) -{ - /* - * All the Android tools that generate a boot.img use this - * address as the default. - * - * Even though it doesn't really make a lot of sense, and it - * might be valid on some platforms, we treat that adress as - * the default value for this field, and try to execute the - * kernel in place in such a case. - * - * Otherwise, we will return the actual value set by the user. - */ - if (hdr->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR) - return (ulong)hdr + hdr->page_size; - - /* - * abootimg creates images where all load addresses are 0 - * and we need to fix them. - */ - if (hdr->kernel_addr == 0 && hdr->ramdisk_addr == 0) - return env_get_ulong("kernel_addr_r", 16, 0); - - return hdr->kernel_addr; -} - -/** - * android_image_get_kernel() - processes kernel part of Android boot images - * @hdr: Pointer to image header, which is at the start - * of the image. - * @verify: Checksum verification flag. Currently unimplemented. - * @os_data: Pointer to a ulong variable, will hold os data start - * address. - * @os_len: Pointer to a ulong variable, will hold os data length. - * - * This function returns the os image's start address and length. Also, - * it appends the kernel command line to the bootargs env variable. - * - * Return: Zero, os start address and length on success, - * otherwise on failure. - */ -int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, - ulong *os_data, ulong *os_len) -{ - u32 kernel_addr = android_image_get_kernel_addr(hdr); - const struct image_header *ihdr = (const struct image_header *) - ((uintptr_t)hdr + hdr->page_size); - - /* - * Not all Android tools use the id field for signing the image with - * sha1 (or anything) so we don't check it. It is not obvious that the - * string is null terminated so we take care of this. - */ - strncpy(andr_tmp_str, hdr->name, ANDR_BOOT_NAME_SIZE); - andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0'; - if (strlen(andr_tmp_str)) - printf("Android's image name: %s\n", andr_tmp_str); - - printf("Kernel load addr 0x%08x size %u KiB\n", - kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024)); - - int len = 0; - if (*hdr->cmdline) { - printf("Kernel command line: %s\n", hdr->cmdline); - len += strlen(hdr->cmdline); - } - - char *bootargs = env_get("bootargs"); - if (bootargs) - len += strlen(bootargs); - - char *newbootargs = malloc(len + 2); - if (!newbootargs) { - puts("Error: malloc in android_image_get_kernel failed!\n"); - return -ENOMEM; - } - *newbootargs = '\0'; - - if (bootargs) { - strcpy(newbootargs, bootargs); - strcat(newbootargs, " "); - } - if (*hdr->cmdline) - strcat(newbootargs, hdr->cmdline); - - env_set("bootargs", newbootargs); - - if (os_data) { - if (image_get_magic(ihdr) == IH_MAGIC) { - *os_data = image_get_data(ihdr); - } else { - *os_data = (ulong)hdr; - *os_data += hdr->page_size; - } - } - if (os_len) { - if (image_get_magic(ihdr) == IH_MAGIC) - *os_len = image_get_data_size(ihdr); - else - *os_len = hdr->kernel_size; - } - return 0; -} - -int android_image_check_header(const struct andr_img_hdr *hdr) -{ - return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE); -} - -ulong android_image_get_end(const struct andr_img_hdr *hdr) -{ - ulong end; - - /* - * The header takes a full page, the remaining components are aligned - * on page boundary - */ - end = (ulong)hdr; - end += hdr->page_size; - end += ALIGN(hdr->kernel_size, hdr->page_size); - end += ALIGN(hdr->ramdisk_size, hdr->page_size); - end += ALIGN(hdr->second_size, hdr->page_size); - - if (hdr->header_version >= 1) - end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); - - if (hdr->header_version >= 2) - end += ALIGN(hdr->dtb_size, hdr->page_size); - - return end; -} - -ulong android_image_get_kload(const struct andr_img_hdr *hdr) -{ - return android_image_get_kernel_addr(hdr); -} - -ulong android_image_get_kcomp(const struct andr_img_hdr *hdr) -{ - const void *p = (void *)((uintptr_t)hdr + hdr->page_size); - - if (image_get_magic((image_header_t *)p) == IH_MAGIC) - return image_get_comp((image_header_t *)p); - else if (get_unaligned_le32(p) == LZ4F_MAGIC) - return IH_COMP_LZ4; - else - return image_decomp_type(p, sizeof(u32)); -} - -int android_image_get_ramdisk(const struct andr_img_hdr *hdr, - ulong *rd_data, ulong *rd_len) -{ - if (!hdr->ramdisk_size) { - *rd_data = *rd_len = 0; - return -1; - } - - printf("RAM disk load addr 0x%08x size %u KiB\n", - hdr->ramdisk_addr, DIV_ROUND_UP(hdr->ramdisk_size, 1024)); - - *rd_data = (unsigned long)hdr; - *rd_data += hdr->page_size; - *rd_data += ALIGN(hdr->kernel_size, hdr->page_size); - - *rd_len = hdr->ramdisk_size; - return 0; -} - -int android_image_get_second(const struct andr_img_hdr *hdr, - ulong *second_data, ulong *second_len) -{ - if (!hdr->second_size) { - *second_data = *second_len = 0; - return -1; - } - - *second_data = (unsigned long)hdr; - *second_data += hdr->page_size; - *second_data += ALIGN(hdr->kernel_size, hdr->page_size); - *second_data += ALIGN(hdr->ramdisk_size, hdr->page_size); - - printf("second address is 0x%lx\n",*second_data); - - *second_len = hdr->second_size; - return 0; -} - -/** - * android_image_get_dtbo() - Get address and size of recovery DTBO image. - * @hdr_addr: Boot image header address - * @addr: If not NULL, will contain address of recovery DTBO image - * @size: If not NULL, will contain size of recovery DTBO image - * - * Get the address and size of DTBO image in "Recovery DTBO" area of Android - * Boot Image in RAM. The format of this image is Android DTBO (see - * corresponding "DTB/DTBO Partitions" AOSP documentation for details). Once - * the address is obtained from this function, one can use 'adtimg' U-Boot - * command or android_dt_*() functions to extract desired DTBO blob. - * - * This DTBO (included in boot image) is only needed for non-A/B devices, and it - * only can be found in recovery image. On A/B devices we can always rely on - * "dtbo" partition. See "Including DTBO in Recovery for Non-A/B Devices" in - * AOSP documentation for details. - * - * Return: true on success or false on error. - */ -bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size) -{ - const struct andr_img_hdr *hdr; - ulong dtbo_img_addr; - bool ret = true; - - hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - if (android_image_check_header(hdr)) { - printf("Error: Boot Image header is incorrect\n"); - ret = false; - goto exit; - } - - if (hdr->header_version < 1) { - printf("Error: header_version must be >= 1 to get dtbo\n"); - ret = false; - goto exit; - } - - if (hdr->recovery_dtbo_size == 0) { - printf("Error: recovery_dtbo_size is 0\n"); - ret = false; - goto exit; - } - - /* Calculate the address of DTB area in boot image */ - dtbo_img_addr = hdr_addr; - dtbo_img_addr += hdr->page_size; - dtbo_img_addr += ALIGN(hdr->kernel_size, hdr->page_size); - dtbo_img_addr += ALIGN(hdr->ramdisk_size, hdr->page_size); - dtbo_img_addr += ALIGN(hdr->second_size, hdr->page_size); - - if (addr) - *addr = dtbo_img_addr; - if (size) - *size = hdr->recovery_dtbo_size; - -exit: - unmap_sysmem(hdr); - return ret; -} - -/** - * android_image_get_dtb_img_addr() - Get the address of DTB area in boot image. - * @hdr_addr: Boot image header address - * @addr: Will contain the address of DTB area in boot image - * - * Return: true on success or false on fail. - */ -static bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong *addr) -{ - const struct andr_img_hdr *hdr; - ulong dtb_img_addr; - bool ret = true; - - hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - if (android_image_check_header(hdr)) { - printf("Error: Boot Image header is incorrect\n"); - ret = false; - goto exit; - } - - if (hdr->header_version < 2) { - printf("Error: header_version must be >= 2 to get dtb\n"); - ret = false; - goto exit; - } - - if (hdr->dtb_size == 0) { - printf("Error: dtb_size is 0\n"); - ret = false; - goto exit; - } - - /* Calculate the address of DTB area in boot image */ - dtb_img_addr = hdr_addr; - dtb_img_addr += hdr->page_size; - dtb_img_addr += ALIGN(hdr->kernel_size, hdr->page_size); - dtb_img_addr += ALIGN(hdr->ramdisk_size, hdr->page_size); - dtb_img_addr += ALIGN(hdr->second_size, hdr->page_size); - dtb_img_addr += ALIGN(hdr->recovery_dtbo_size, hdr->page_size); - - *addr = dtb_img_addr; - -exit: - unmap_sysmem(hdr); - return ret; -} - -/** - * android_image_get_dtb_by_index() - Get address and size of blob in DTB area. - * @hdr_addr: Boot image header address - * @index: Index of desired DTB in DTB area (starting from 0) - * @addr: If not NULL, will contain address to specified DTB - * @size: If not NULL, will contain size of specified DTB - * - * Get the address and size of DTB blob by its index in DTB area of Android - * Boot Image in RAM. - * - * Return: true on success or false on error. - */ -bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, - u32 *size) -{ - const struct andr_img_hdr *hdr; - bool res; - ulong dtb_img_addr; /* address of DTB part in boot image */ - u32 dtb_img_size; /* size of DTB payload in boot image */ - ulong dtb_addr; /* address of DTB blob with specified index */ - u32 i; /* index iterator */ - - res = android_image_get_dtb_img_addr(hdr_addr, &dtb_img_addr); - if (!res) - return false; - - /* Check if DTB area of boot image is in DTBO format */ - if (android_dt_check_header(dtb_img_addr)) { - return android_dt_get_fdt_by_index(dtb_img_addr, index, addr, - size); - } - - /* Find out the address of DTB with specified index in concat blobs */ - hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - dtb_img_size = hdr->dtb_size; - unmap_sysmem(hdr); - i = 0; - dtb_addr = dtb_img_addr; - while (dtb_addr < dtb_img_addr + dtb_img_size) { - const struct fdt_header *fdt; - u32 dtb_size; - - fdt = map_sysmem(dtb_addr, sizeof(*fdt)); - if (fdt_check_header(fdt) != 0) { - unmap_sysmem(fdt); - printf("Error: Invalid FDT header for index %u\n", i); - return false; - } - - dtb_size = fdt_totalsize(fdt); - unmap_sysmem(fdt); - - if (i == index) { - if (size) - *size = dtb_size; - if (addr) - *addr = dtb_addr; - return true; - } - - dtb_addr += dtb_size; - ++i; - } - - printf("Error: Index is out of bounds (%u/%u)\n", index, i); - return false; -} - -#if !defined(CONFIG_SPL_BUILD) -/** - * android_print_contents - prints out the contents of the Android format image - * @hdr: pointer to the Android format image header - * - * android_print_contents() formats a multi line Android image contents - * description. - * The routine prints out Android image properties - * - * returns: - * no returned results - */ -void android_print_contents(const struct andr_img_hdr *hdr) -{ - const char * const p = IMAGE_INDENT_STRING; - /* os_version = ver << 11 | lvl */ - u32 os_ver = hdr->os_version >> 11; - u32 os_lvl = hdr->os_version & ((1U << 11) - 1); - - printf("%skernel size: %x\n", p, hdr->kernel_size); - printf("%skernel address: %x\n", p, hdr->kernel_addr); - printf("%sramdisk size: %x\n", p, hdr->ramdisk_size); - printf("%sramdisk address: %x\n", p, hdr->ramdisk_addr); - printf("%ssecond size: %x\n", p, hdr->second_size); - printf("%ssecond address: %x\n", p, hdr->second_addr); - printf("%stags address: %x\n", p, hdr->tags_addr); - printf("%spage size: %x\n", p, hdr->page_size); - /* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C) - * lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M) */ - printf("%sos_version: %x (ver: %u.%u.%u, level: %u.%u)\n", - p, hdr->os_version, - (os_ver >> 7) & 0x7F, (os_ver >> 14) & 0x7F, os_ver & 0x7F, - (os_lvl >> 4) + 2000, os_lvl & 0x0F); - printf("%sname: %s\n", p, hdr->name); - printf("%scmdline: %s\n", p, hdr->cmdline); - printf("%sheader_version: %d\n", p, hdr->header_version); - - if (hdr->header_version >= 1) { - printf("%srecovery dtbo size: %x\n", p, - hdr->recovery_dtbo_size); - printf("%srecovery dtbo offset: %llx\n", p, - hdr->recovery_dtbo_offset); - printf("%sheader size: %x\n", p, - hdr->header_size); - } - - if (hdr->header_version >= 2) { - printf("%sdtb size: %x\n", p, hdr->dtb_size); - printf("%sdtb addr: %llx\n", p, hdr->dtb_addr); - } -} - -/** - * android_image_print_dtb_info - Print info for one DTB blob in DTB area. - * @fdt: DTB header - * @index: Number of DTB blob in DTB area. - * - * Return: true on success or false on error. - */ -static bool android_image_print_dtb_info(const struct fdt_header *fdt, - u32 index) -{ - int root_node_off; - u32 fdt_size; - const char *model; - const char *compatible; - - root_node_off = fdt_path_offset(fdt, "/"); - if (root_node_off < 0) { - printf("Error: Root node not found\n"); - return false; - } - - fdt_size = fdt_totalsize(fdt); - compatible = fdt_getprop(fdt, root_node_off, "compatible", - NULL); - model = fdt_getprop(fdt, root_node_off, "model", NULL); - - printf(" - DTB #%u:\n", index); - printf(" (DTB)size = %d\n", fdt_size); - printf(" (DTB)model = %s\n", model ? model : "(unknown)"); - printf(" (DTB)compatible = %s\n", - compatible ? compatible : "(unknown)"); - - return true; -} - -/** - * android_image_print_dtb_contents() - Print info for DTB blobs in DTB area. - * @hdr_addr: Boot image header address - * - * DTB payload in Android Boot Image v2+ can be in one of following formats: - * 1. Concatenated DTB blobs - * 2. Android DTBO format (see CONFIG_CMD_ADTIMG for details) - * - * This function does next: - * 1. Prints out the format used in DTB area - * 2. Iterates over all DTB blobs in DTB area and prints out the info for - * each blob. - * - * Return: true on success or false on error. - */ -bool android_image_print_dtb_contents(ulong hdr_addr) -{ - const struct andr_img_hdr *hdr; - bool res; - ulong dtb_img_addr; /* address of DTB part in boot image */ - u32 dtb_img_size; /* size of DTB payload in boot image */ - ulong dtb_addr; /* address of DTB blob with specified index */ - u32 i; /* index iterator */ - - res = android_image_get_dtb_img_addr(hdr_addr, &dtb_img_addr); - if (!res) - return false; - - /* Check if DTB area of boot image is in DTBO format */ - if (android_dt_check_header(dtb_img_addr)) { - printf("## DTB area contents (DTBO format):\n"); - android_dt_print_contents(dtb_img_addr); - return true; - } - - printf("## DTB area contents (concat format):\n"); - - /* Iterate over concatenated DTB blobs */ - hdr = map_sysmem(hdr_addr, sizeof(*hdr)); - dtb_img_size = hdr->dtb_size; - unmap_sysmem(hdr); - i = 0; - dtb_addr = dtb_img_addr; - while (dtb_addr < dtb_img_addr + dtb_img_size) { - const struct fdt_header *fdt; - u32 dtb_size; - - fdt = map_sysmem(dtb_addr, sizeof(*fdt)); - if (fdt_check_header(fdt) != 0) { - unmap_sysmem(fdt); - printf("Error: Invalid FDT header for index %u\n", i); - return false; - } - - res = android_image_print_dtb_info(fdt, i); - if (!res) { - unmap_sysmem(fdt); - return false; - } - - dtb_size = fdt_totalsize(fdt); - unmap_sysmem(fdt); - dtb_addr += dtb_size; - ++i; - } - - return true; -} -#endif diff --git a/common/image-board.c b/common/image-board.c deleted file mode 100644 index ddf30c67302..00000000000 --- a/common/image-board.c +++ /dev/null @@ -1,956 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Image code used by boards (and not host tools) - * - * (C) Copyright 2008 Semihalf - * - * (C) Copyright 2000-2006 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#include <common.h> -#include <bootstage.h> -#include <cpu_func.h> -#include <env.h> -#include <fpga.h> -#include <image.h> -#include <mapmem.h> -#include <rtc.h> -#include <watchdog.h> -#include <asm/cache.h> -#include <asm/global_data.h> - -#ifndef CONFIG_SYS_BARGSIZE -#define CONFIG_SYS_BARGSIZE 512 -#endif - -DECLARE_GLOBAL_DATA_PTR; - -/** - * image_get_ramdisk - get and verify ramdisk image - * @rd_addr: ramdisk image start address - * @arch: expected ramdisk architecture - * @verify: checksum verification flag - * - * image_get_ramdisk() returns a pointer to the verified ramdisk image - * header. Routine receives image start address and expected architecture - * flag. Verification done covers data and header integrity and os/type/arch - * fields checking. - * - * returns: - * pointer to a ramdisk image header, if image was found and valid - * otherwise, return NULL - */ -static const image_header_t *image_get_ramdisk(ulong rd_addr, u8 arch, - int verify) -{ - const image_header_t *rd_hdr = (const image_header_t *)rd_addr; - - if (!image_check_magic(rd_hdr)) { - puts("Bad Magic Number\n"); - bootstage_error(BOOTSTAGE_ID_RD_MAGIC); - return NULL; - } - - if (!image_check_hcrc(rd_hdr)) { - puts("Bad Header Checksum\n"); - bootstage_error(BOOTSTAGE_ID_RD_HDR_CHECKSUM); - return NULL; - } - - bootstage_mark(BOOTSTAGE_ID_RD_MAGIC); - image_print_contents(rd_hdr); - - if (verify) { - puts(" Verifying Checksum ... "); - if (!image_check_dcrc(rd_hdr)) { - puts("Bad Data CRC\n"); - bootstage_error(BOOTSTAGE_ID_RD_CHECKSUM); - return NULL; - } - puts("OK\n"); - } - - bootstage_mark(BOOTSTAGE_ID_RD_HDR_CHECKSUM); - - if (!image_check_os(rd_hdr, IH_OS_LINUX) || - !image_check_arch(rd_hdr, arch) || - !image_check_type(rd_hdr, IH_TYPE_RAMDISK)) { - printf("No Linux %s Ramdisk Image\n", - genimg_get_arch_name(arch)); - bootstage_error(BOOTSTAGE_ID_RAMDISK); - return NULL; - } - - return rd_hdr; -} - -/*****************************************************************************/ -/* Shared dual-format routines */ -/*****************************************************************************/ -ulong image_load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */ -ulong image_save_addr; /* Default Save Address */ -ulong image_save_size; /* Default Save Size (in bytes) */ - -static int on_loadaddr(const char *name, const char *value, enum env_op op, - int flags) -{ - switch (op) { - case env_op_create: - case env_op_overwrite: - image_load_addr = hextoul(value, NULL); - break; - default: - break; - } - - return 0; -} -U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr); - -ulong env_get_bootm_low(void) -{ - char *s = env_get("bootm_low"); - - if (s) { - ulong tmp = hextoul(s, NULL); - return tmp; - } - -#if defined(CONFIG_SYS_SDRAM_BASE) - return CONFIG_SYS_SDRAM_BASE; -#elif defined(CONFIG_ARM) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_RISCV) - return gd->bd->bi_dram[0].start; -#else - return 0; -#endif -} - -phys_size_t env_get_bootm_size(void) -{ - phys_size_t tmp, size; - phys_addr_t start; - char *s = env_get("bootm_size"); - - if (s) { - tmp = (phys_size_t)simple_strtoull(s, NULL, 16); - return tmp; - } - - start = gd->ram_base; - size = gd->ram_size; - - if (start + size > gd->ram_top) - size = gd->ram_top - start; - - s = env_get("bootm_low"); - if (s) - tmp = (phys_size_t)simple_strtoull(s, NULL, 16); - else - tmp = start; - - return size - (tmp - start); -} - -phys_size_t env_get_bootm_mapsize(void) -{ - phys_size_t tmp; - char *s = env_get("bootm_mapsize"); - - if (s) { - tmp = (phys_size_t)simple_strtoull(s, NULL, 16); - return tmp; - } - -#if defined(CONFIG_SYS_BOOTMAPSZ) - return CONFIG_SYS_BOOTMAPSZ; -#else - return env_get_bootm_size(); -#endif -} - -void memmove_wd(void *to, void *from, size_t len, ulong chunksz) -{ - if (to == from) - return; - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - if (to > from) { - from += len; - to += len; - } - while (len > 0) { - size_t tail = (len > chunksz) ? chunksz : len; - - WATCHDOG_RESET(); - if (to > from) { - to -= tail; - from -= tail; - } - memmove(to, from, tail); - if (to < from) { - to += tail; - from += tail; - } - len -= tail; - } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - memmove(to, from, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ -} - -/** - * genimg_get_kernel_addr_fit - get the real kernel address and return 2 - * FIT strings - * @img_addr: a string might contain real image address - * @fit_uname_config: double pointer to a char, will hold pointer to a - * configuration unit name - * @fit_uname_kernel: double pointer to a char, will hold pointer to a subimage - * name - * - * genimg_get_kernel_addr_fit get the real kernel start address from a string - * which is normally the first argv of bootm/bootz - * - * returns: - * kernel start address - */ -ulong genimg_get_kernel_addr_fit(char * const img_addr, - const char **fit_uname_config, - const char **fit_uname_kernel) -{ - ulong kernel_addr; - - /* find out kernel image address */ - if (!img_addr) { - kernel_addr = image_load_addr; - debug("* kernel: default image load address = 0x%08lx\n", - image_load_addr); - } else if (CONFIG_IS_ENABLED(FIT) && - fit_parse_conf(img_addr, image_load_addr, &kernel_addr, - fit_uname_config)) { - debug("* kernel: config '%s' from image at 0x%08lx\n", - *fit_uname_config, kernel_addr); - } else if (CONFIG_IS_ENABLED(FIT) && - fit_parse_subimage(img_addr, image_load_addr, &kernel_addr, - fit_uname_kernel)) { - debug("* kernel: subimage '%s' from image at 0x%08lx\n", - *fit_uname_kernel, kernel_addr); - } else { - kernel_addr = hextoul(img_addr, NULL); - debug("* kernel: cmdline image address = 0x%08lx\n", - kernel_addr); - } - - return kernel_addr; -} - -/** - * genimg_get_kernel_addr() is the simple version of - * genimg_get_kernel_addr_fit(). It ignores those return FIT strings - */ -ulong genimg_get_kernel_addr(char * const img_addr) -{ - const char *fit_uname_config = NULL; - const char *fit_uname_kernel = NULL; - - return genimg_get_kernel_addr_fit(img_addr, &fit_uname_config, - &fit_uname_kernel); -} - -/** - * genimg_get_format - get image format type - * @img_addr: image start address - * - * genimg_get_format() checks whether provided address points to a valid - * legacy or FIT image. - * - * New uImage format and FDT blob are based on a libfdt. FDT blob - * may be passed directly or embedded in a FIT image. In both situations - * genimg_get_format() must be able to dectect libfdt header. - * - * returns: - * image format type or IMAGE_FORMAT_INVALID if no image is present - */ -int genimg_get_format(const void *img_addr) -{ - if (CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)) { - const image_header_t *hdr; - - hdr = (const image_header_t *)img_addr; - if (image_check_magic(hdr)) - return IMAGE_FORMAT_LEGACY; - } - if (CONFIG_IS_ENABLED(FIT) || CONFIG_IS_ENABLED(OF_LIBFDT)) { - if (!fdt_check_header(img_addr)) - return IMAGE_FORMAT_FIT; - } - if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE) && - !android_image_check_header(img_addr)) - return IMAGE_FORMAT_ANDROID; - - return IMAGE_FORMAT_INVALID; -} - -/** - * fit_has_config - check if there is a valid FIT configuration - * @images: pointer to the bootm command headers structure - * - * fit_has_config() checks if there is a FIT configuration in use - * (if FTI support is present). - * - * returns: - * 0, no FIT support or no configuration found - * 1, configuration found - */ -int genimg_has_config(bootm_headers_t *images) -{ - if (CONFIG_IS_ENABLED(FIT) && images->fit_uname_cfg) - return 1; - - return 0; -} - -/** - * select_ramdisk() - Select and locate the ramdisk to use - * - * @images: pointer to the bootm images structure - * @select: name of ramdisk to select, or NULL for any - * @arch: expected ramdisk architecture - * @rd_datap: pointer to a ulong variable, will hold ramdisk pointer - * @rd_lenp: pointer to a ulong variable, will hold ramdisk length - * @return 0 if OK, -ENOPKG if no ramdisk (but an error should not be reported), - * other -ve value on other error - */ -static int select_ramdisk(bootm_headers_t *images, const char *select, u8 arch, - ulong *rd_datap, ulong *rd_lenp) -{ - ulong rd_addr = 0; - char *buf; - const char *fit_uname_config = images->fit_uname_cfg; - const char *fit_uname_ramdisk = NULL; - bool processed; - int rd_noffset; - - if (select) { - ulong default_addr; - bool done = true; - - if (CONFIG_IS_ENABLED(FIT)) { - /* - * If the init ramdisk comes from the FIT image and - * the FIT image address is omitted in the command - * line argument, try to use os FIT image address or - * default load address. - */ - if (images->fit_uname_os) - default_addr = (ulong)images->fit_hdr_os; - else - default_addr = image_load_addr; - - if (fit_parse_conf(select, default_addr, &rd_addr, - &fit_uname_config)) { - debug("* ramdisk: config '%s' from image at 0x%08lx\n", - fit_uname_config, rd_addr); - } else if (fit_parse_subimage(select, default_addr, - &rd_addr, - &fit_uname_ramdisk)) { - debug("* ramdisk: subimage '%s' from image at 0x%08lx\n", - fit_uname_ramdisk, rd_addr); - } else { - done = false; - } - } - if (!done) { - rd_addr = hextoul(select, NULL); - debug("* ramdisk: cmdline image address = 0x%08lx\n", - rd_addr); - } - } else if (CONFIG_IS_ENABLED(FIT)) { - /* use FIT configuration provided in first bootm - * command argument. If the property is not defined, - * quit silently (with -ENOPKG ) - */ - rd_addr = map_to_sysmem(images->fit_hdr_os); - rd_noffset = fit_get_node_from_config(images, FIT_RAMDISK_PROP, - rd_addr); - if (rd_noffset == -ENOENT) - return -ENOPKG; - else if (rd_noffset < 0) - return rd_noffset; - } - - /* - * Check if there is an initrd image at the - * address provided in the second bootm argument - * check image type, for FIT images get FIT node. - */ - buf = map_sysmem(rd_addr, 0); - processed = false; - switch (genimg_get_format(buf)) { - case IMAGE_FORMAT_LEGACY: - if (CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)) { - const image_header_t *rd_hdr; - - printf("## Loading init Ramdisk from Legacy Image at %08lx ...\n", - rd_addr); - - bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK); - rd_hdr = image_get_ramdisk(rd_addr, arch, images->verify); - if (!rd_hdr) - return -ENOENT; - - *rd_datap = image_get_data(rd_hdr); - *rd_lenp = image_get_data_size(rd_hdr); - processed = true; - } - break; - case IMAGE_FORMAT_FIT: - if (CONFIG_IS_ENABLED(FIT)) { - rd_noffset = fit_image_load(images, rd_addr, - &fit_uname_ramdisk, - &fit_uname_config, arch, - IH_TYPE_RAMDISK, - BOOTSTAGE_ID_FIT_RD_START, - FIT_LOAD_OPTIONAL_NON_ZERO, - rd_datap, rd_lenp); - if (rd_noffset < 0) - return rd_noffset; - - images->fit_hdr_rd = map_sysmem(rd_addr, 0); - images->fit_uname_rd = fit_uname_ramdisk; - images->fit_noffset_rd = rd_noffset; - processed = true; - } - break; - case IMAGE_FORMAT_ANDROID: - if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE)) { - android_image_get_ramdisk((void *)images->os.start, - rd_datap, rd_lenp); - processed = true; - } - break; - } - - if (!processed) { - if (IS_ENABLED(CONFIG_SUPPORT_RAW_INITRD)) { - char *end = NULL; - - if (select) - end = strchr(select, ':'); - if (end) { - *rd_lenp = hextoul(++end, NULL); - *rd_datap = rd_addr; - processed = true; - } - } - - if (!processed) { - puts("Wrong Ramdisk Image Format\n"); - return -EINVAL; - } - } - - return 0; -} - -/** - * boot_get_ramdisk - main ramdisk handling routine - * @argc: command argument count - * @argv: command argument list - * @images: pointer to the bootm images structure - * @arch: expected ramdisk architecture - * @rd_start: pointer to a ulong variable, will hold ramdisk start address - * @rd_end: pointer to a ulong variable, will hold ramdisk end - * - * boot_get_ramdisk() is responsible for finding a valid ramdisk image. - * Currently supported are the following ramdisk sources: - * - multicomponent kernel/ramdisk image, - * - commandline provided address of decicated ramdisk image. - * - * returns: - * 0, if ramdisk image was found and valid, or skiped - * rd_start and rd_end are set to ramdisk start/end addresses if - * ramdisk image is found and valid - * - * 1, if ramdisk image is found but corrupted, or invalid - * rd_start and rd_end are set to 0 if no ramdisk exists - */ -int boot_get_ramdisk(int argc, char *const argv[], bootm_headers_t *images, - u8 arch, ulong *rd_start, ulong *rd_end) -{ - ulong rd_data, rd_len; - const char *select = NULL; - - *rd_start = 0; - *rd_end = 0; - - if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE)) { - char *buf; - - /* Look for an Android boot image */ - buf = map_sysmem(images->os.start, 0); - if (buf && genimg_get_format(buf) == IMAGE_FORMAT_ANDROID) - select = (argc == 0) ? env_get("loadaddr") : argv[0]; - } - - if (argc >= 2) - select = argv[1]; - - /* - * Look for a '-' which indicates to ignore the - * ramdisk argument - */ - if (select && strcmp(select, "-") == 0) { - debug("## Skipping init Ramdisk\n"); - rd_len = 0; - rd_data = 0; - } else if (select || genimg_has_config(images)) { - int ret; - - ret = select_ramdisk(images, select, arch, &rd_data, &rd_len); - if (ret == -ENOPKG) - return 0; - else if (ret) - return ret; - } else if (images->legacy_hdr_valid && - image_check_type(&images->legacy_hdr_os_copy, - IH_TYPE_MULTI)) { - /* - * Now check if we have a legacy mult-component image, - * get second entry data start address and len. - */ - bootstage_mark(BOOTSTAGE_ID_RAMDISK); - printf("## Loading init Ramdisk from multi component Legacy Image at %08lx ...\n", - (ulong)images->legacy_hdr_os); - - image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len); - } else { - /* - * no initrd image - */ - bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK); - rd_len = 0; - rd_data = 0; - } - - if (!rd_data) { - debug("## No init Ramdisk\n"); - } else { - *rd_start = rd_data; - *rd_end = rd_data + rd_len; - } - debug(" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", - *rd_start, *rd_end); - - return 0; -} - -/** - * boot_ramdisk_high - relocate init ramdisk - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @rd_data: ramdisk data start address - * @rd_len: ramdisk data length - * @initrd_start: pointer to a ulong variable, will hold final init ramdisk - * start address (after possible relocation) - * @initrd_end: pointer to a ulong variable, will hold final init ramdisk - * end address (after possible relocation) - * - * boot_ramdisk_high() takes a relocation hint from "initrd_high" environment - * variable and if requested ramdisk data is moved to a specified location. - * - * Initrd_start and initrd_end are set to final (after relocation) ramdisk - * start/end addresses if ramdisk image start and len were provided, - * otherwise set initrd_start and initrd_end set to zeros. - * - * returns: - * 0 - success - * -1 - failure - */ -int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, - ulong *initrd_start, ulong *initrd_end) -{ - char *s; - ulong initrd_high; - int initrd_copy_to_ram = 1; - - s = env_get("initrd_high"); - if (s) { - /* a value of "no" or a similar string will act like 0, - * turning the "load high" feature off. This is intentional. - */ - initrd_high = hextoul(s, NULL); - if (initrd_high == ~0) - initrd_copy_to_ram = 0; - } else { - initrd_high = env_get_bootm_mapsize() + env_get_bootm_low(); - } - - debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n", - initrd_high, initrd_copy_to_ram); - - if (rd_data) { - if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ - debug(" in-place initrd\n"); - *initrd_start = rd_data; - *initrd_end = rd_data + rd_len; - lmb_reserve(lmb, rd_data, rd_len); - } else { - if (initrd_high) - *initrd_start = (ulong)lmb_alloc_base(lmb, - rd_len, 0x1000, initrd_high); - else - *initrd_start = (ulong)lmb_alloc(lmb, rd_len, - 0x1000); - - if (*initrd_start == 0) { - puts("ramdisk - allocation error\n"); - goto error; - } - bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK); - - *initrd_end = *initrd_start + rd_len; - printf(" Loading Ramdisk to %08lx, end %08lx ... ", - *initrd_start, *initrd_end); - - memmove_wd((void *)*initrd_start, - (void *)rd_data, rd_len, CHUNKSZ); - - /* - * Ensure the image is flushed to memory to handle - * AMP boot scenarios in which we might not be - * HW cache coherent - */ - if (IS_ENABLED(CONFIG_MP)) { - flush_cache((unsigned long)*initrd_start, - ALIGN(rd_len, ARCH_DMA_MINALIGN)); - } - puts("OK\n"); - } - } else { - *initrd_start = 0; - *initrd_end = 0; - } - debug(" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", - *initrd_start, *initrd_end); - - return 0; - -error: - return -1; -} - -int boot_get_setup(bootm_headers_t *images, u8 arch, - ulong *setup_start, ulong *setup_len) -{ - if (!CONFIG_IS_ENABLED(FIT)) - return -ENOENT; - - return boot_get_setup_fit(images, arch, setup_start, setup_len); -} - -int boot_get_fpga(int argc, char *const argv[], bootm_headers_t *images, - u8 arch, const ulong *ld_start, ulong * const ld_len) -{ - ulong tmp_img_addr, img_data, img_len; - void *buf; - int conf_noffset; - int fit_img_result; - const char *uname, *name; - int err; - int devnum = 0; /* TODO support multi fpga platforms */ - - if (!IS_ENABLED(CONFIG_FPGA)) - return -ENOSYS; - - /* Check to see if the images struct has a FIT configuration */ - if (!genimg_has_config(images)) { - debug("## FIT configuration was not specified\n"); - return 0; - } - - /* - * Obtain the os FIT header from the images struct - */ - tmp_img_addr = map_to_sysmem(images->fit_hdr_os); - buf = map_sysmem(tmp_img_addr, 0); - /* - * Check image type. For FIT images get FIT node - * and attempt to locate a generic binary. - */ - switch (genimg_get_format(buf)) { - case IMAGE_FORMAT_FIT: - conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg); - - uname = fdt_stringlist_get(buf, conf_noffset, FIT_FPGA_PROP, 0, - NULL); - if (!uname) { - debug("## FPGA image is not specified\n"); - return 0; - } - fit_img_result = fit_image_load(images, - tmp_img_addr, - (const char **)&uname, - &images->fit_uname_cfg, - arch, - IH_TYPE_FPGA, - BOOTSTAGE_ID_FPGA_INIT, - FIT_LOAD_OPTIONAL_NON_ZERO, - &img_data, &img_len); - - debug("FPGA image (%s) loaded to 0x%lx/size 0x%lx\n", - uname, img_data, img_len); - - if (fit_img_result < 0) { - /* Something went wrong! */ - return fit_img_result; - } - - if (!fpga_is_partial_data(devnum, img_len)) { - name = "full"; - err = fpga_loadbitstream(devnum, (char *)img_data, - img_len, BIT_FULL); - if (err) - err = fpga_load(devnum, (const void *)img_data, - img_len, BIT_FULL); - } else { - name = "partial"; - err = fpga_loadbitstream(devnum, (char *)img_data, - img_len, BIT_PARTIAL); - if (err) - err = fpga_load(devnum, (const void *)img_data, - img_len, BIT_PARTIAL); - } - - if (err) - return err; - - printf(" Programming %s bitstream... OK\n", name); - break; - default: - printf("The given image format is not supported (corrupt?)\n"); - return 1; - } - - return 0; -} - -static void fit_loadable_process(u8 img_type, - ulong img_data, - ulong img_len) -{ - int i; - const unsigned int count = - ll_entry_count(struct fit_loadable_tbl, fit_loadable); - struct fit_loadable_tbl *fit_loadable_handler = - ll_entry_start(struct fit_loadable_tbl, fit_loadable); - /* For each loadable handler */ - for (i = 0; i < count; i++, fit_loadable_handler++) - /* matching this type */ - if (fit_loadable_handler->type == img_type) - /* call that handler with this image data */ - fit_loadable_handler->handler(img_data, img_len); -} - -int boot_get_loadable(int argc, char *const argv[], bootm_headers_t *images, - u8 arch, const ulong *ld_start, ulong * const ld_len) -{ - /* - * These variables are used to hold the current image location - * in system memory. - */ - ulong tmp_img_addr; - /* - * These two variables are requirements for fit_image_load, but - * their values are not used - */ - ulong img_data, img_len; - void *buf; - int loadables_index; - int conf_noffset; - int fit_img_result; - const char *uname; - u8 img_type; - - /* Check to see if the images struct has a FIT configuration */ - if (!genimg_has_config(images)) { - debug("## FIT configuration was not specified\n"); - return 0; - } - - /* - * Obtain the os FIT header from the images struct - */ - tmp_img_addr = map_to_sysmem(images->fit_hdr_os); - buf = map_sysmem(tmp_img_addr, 0); - /* - * Check image type. For FIT images get FIT node - * and attempt to locate a generic binary. - */ - switch (genimg_get_format(buf)) { - case IMAGE_FORMAT_FIT: - conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg); - - for (loadables_index = 0; - uname = fdt_stringlist_get(buf, conf_noffset, - FIT_LOADABLE_PROP, - loadables_index, NULL), uname; - loadables_index++) { - fit_img_result = fit_image_load(images, tmp_img_addr, - &uname, - &images->fit_uname_cfg, - arch, IH_TYPE_LOADABLE, - BOOTSTAGE_ID_FIT_LOADABLE_START, - FIT_LOAD_OPTIONAL_NON_ZERO, - &img_data, &img_len); - if (fit_img_result < 0) { - /* Something went wrong! */ - return fit_img_result; - } - - fit_img_result = fit_image_get_node(buf, uname); - if (fit_img_result < 0) { - /* Something went wrong! */ - return fit_img_result; - } - fit_img_result = fit_image_get_type(buf, - fit_img_result, - &img_type); - if (fit_img_result < 0) { - /* Something went wrong! */ - return fit_img_result; - } - - fit_loadable_process(img_type, img_data, img_len); - } - break; - default: - printf("The given image format is not supported (corrupt?)\n"); - return 1; - } - - return 0; -} - -/** - * boot_get_cmdline - allocate and initialize kernel cmdline - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @cmd_start: pointer to a ulong variable, will hold cmdline start - * @cmd_end: pointer to a ulong variable, will hold cmdline end - * - * boot_get_cmdline() allocates space for kernel command line below - * BOOTMAPSZ + env_get_bootm_low() address. If "bootargs" U-Boot environment - * variable is present its contents is copied to allocated kernel - * command line. - * - * returns: - * 0 - success - * -1 - failure - */ -int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end) -{ - char *cmdline; - char *s; - - cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf, - env_get_bootm_mapsize() + env_get_bootm_low()); - if (!cmdline) - return -1; - - s = env_get("bootargs"); - if (!s) - s = ""; - - strcpy(cmdline, s); - - *cmd_start = (ulong)cmdline; - *cmd_end = *cmd_start + strlen(cmdline); - - debug("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); - - return 0; -} - -/** - * boot_get_kbd - allocate and initialize kernel copy of board info - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @kbd: double pointer to board info data - * - * boot_get_kbd() allocates space for kernel copy of board info data below - * BOOTMAPSZ + env_get_bootm_low() address and kernel board info is initialized - * with the current u-boot board info data. - * - * returns: - * 0 - success - * -1 - failure - */ -int boot_get_kbd(struct lmb *lmb, struct bd_info **kbd) -{ - *kbd = (struct bd_info *)(ulong)lmb_alloc_base(lmb, - sizeof(struct bd_info), - 0xf, - env_get_bootm_mapsize() + - env_get_bootm_low()); - if (!*kbd) - return -1; - - **kbd = *gd->bd; - - debug("## kernel board info at 0x%08lx\n", (ulong)*kbd); - -#if defined(DEBUG) - if (IS_ENABLED(CONFIG_CMD_BDI)) - do_bdinfo(NULL, 0, 0, NULL); -#endif - - return 0; -} - -int image_setup_linux(bootm_headers_t *images) -{ - ulong of_size = images->ft_len; - char **of_flat_tree = &images->ft_addr; - struct lmb *lmb = &images->lmb; - int ret; - - if (CONFIG_IS_ENABLED(OF_LIBFDT)) - boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree); - - if (IS_ENABLED(CONFIG_SYS_BOOT_GET_CMDLINE)) { - ret = boot_get_cmdline(lmb, &images->cmdline_start, - &images->cmdline_end); - if (ret) { - puts("ERROR with allocation of cmdline\n"); - return ret; - } - } - - if (CONFIG_IS_ENABLED(OF_LIBFDT)) { - ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); - if (ret) - return ret; - } - - if (CONFIG_IS_ENABLED(OF_LIBFDT) && of_size) { - ret = image_setup_libfdt(images, *of_flat_tree, of_size, lmb); - if (ret) - return ret; - } - - return 0; -} - -void genimg_print_size(uint32_t size) -{ - printf("%d Bytes = ", size); - print_size(size, "\n"); -} - -void genimg_print_time(time_t timestamp) -{ - struct rtc_time tm; - - rtc_to_tm(timestamp, &tm); - printf("%4d-%02d-%02d %2d:%02d:%02d UTC\n", - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); -} diff --git a/common/image-cipher.c b/common/image-cipher.c deleted file mode 100644 index b9061489396..00000000000 --- a/common/image-cipher.c +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2019, Softathome - */ - -#ifdef USE_HOSTCC -#include "mkimage.h" -#include <time.h> -#else -#include <common.h> -#include <malloc.h> -#include <asm/global_data.h> -DECLARE_GLOBAL_DATA_PTR; -#endif /* !USE_HOSdTCC*/ -#include <image.h> -#include <uboot_aes.h> -#include <u-boot/aes.h> - -struct cipher_algo cipher_algos[] = { - { - .name = "aes128", - .key_len = AES128_KEY_LENGTH, - .iv_len = AES_BLOCK_LENGTH, -#if IMAGE_ENABLE_ENCRYPT - .calculate_type = EVP_aes_128_cbc, -#endif - .encrypt = image_aes_encrypt, - .decrypt = image_aes_decrypt, - .add_cipher_data = image_aes_add_cipher_data - }, - { - .name = "aes192", - .key_len = AES192_KEY_LENGTH, - .iv_len = AES_BLOCK_LENGTH, -#if IMAGE_ENABLE_ENCRYPT - .calculate_type = EVP_aes_192_cbc, -#endif - .encrypt = image_aes_encrypt, - .decrypt = image_aes_decrypt, - .add_cipher_data = image_aes_add_cipher_data - }, - { - .name = "aes256", - .key_len = AES256_KEY_LENGTH, - .iv_len = AES_BLOCK_LENGTH, -#if IMAGE_ENABLE_ENCRYPT - .calculate_type = EVP_aes_256_cbc, -#endif - .encrypt = image_aes_encrypt, - .decrypt = image_aes_decrypt, - .add_cipher_data = image_aes_add_cipher_data - } -}; - -struct cipher_algo *image_get_cipher_algo(const char *full_name) -{ - int i; - const char *name; - - for (i = 0; i < ARRAY_SIZE(cipher_algos); i++) { - name = cipher_algos[i].name; - if (!strncmp(name, full_name, strlen(name))) - return &cipher_algos[i]; - } - - return NULL; -} - -static int fit_image_setup_decrypt(struct image_cipher_info *info, - const void *fit, int image_noffset, - int cipher_noffset) -{ - const void *fdt = gd_fdt_blob(); - const char *node_name; - char node_path[128]; - int noffset; - char *algo_name; - int ret; - - node_name = fit_get_name(fit, image_noffset, NULL); - if (!node_name) { - printf("Can't get node name\n"); - return -1; - } - - if (fit_image_cipher_get_algo(fit, cipher_noffset, &algo_name)) { - printf("Can't get algo name for cipher '%s' in image '%s'\n", - node_name, node_name); - return -1; - } - - info->keyname = fdt_getprop(fit, cipher_noffset, FIT_KEY_HINT, NULL); - if (!info->keyname) { - printf("Can't get key name\n"); - return -1; - } - - info->iv = fdt_getprop(fit, cipher_noffset, "iv", NULL); - info->ivname = fdt_getprop(fit, cipher_noffset, "iv-name-hint", NULL); - - if (!info->iv && !info->ivname) { - printf("Can't get IV or IV name\n"); - return -1; - } - - info->fit = fit; - info->node_noffset = image_noffset; - info->name = algo_name; - info->cipher = image_get_cipher_algo(algo_name); - if (!info->cipher) { - printf("Can't get cipher\n"); - return -1; - } - - ret = fit_image_get_data_size_unciphered(fit, image_noffset, - &info->size_unciphered); - if (ret) { - printf("Can't get size of unciphered data\n"); - return -1; - } - - /* - * Search the cipher node in the u-boot fdt - * the path should be: /cipher/key-<algo>-<key>-<iv> - */ - if (info->ivname) - snprintf(node_path, sizeof(node_path), "/%s/key-%s-%s-%s", - FIT_CIPHER_NODENAME, algo_name, info->keyname, info->ivname); - else - snprintf(node_path, sizeof(node_path), "/%s/key-%s-%s", - FIT_CIPHER_NODENAME, algo_name, info->keyname); - - noffset = fdt_path_offset(fdt, node_path); - if (noffset < 0) { - printf("Can't found cipher node offset\n"); - return -1; - } - - /* read key */ - info->key = fdt_getprop(fdt, noffset, "key", NULL); - if (!info->key) { - printf("Can't get key in cipher node '%s'\n", node_path); - return -1; - } - - /* read iv */ - if (!info->iv) { - info->iv = fdt_getprop(fdt, noffset, "iv", NULL); - if (!info->iv) { - printf("Can't get IV in cipher node '%s'\n", node_path); - return -1; - } - } - - return 0; -} - -int fit_image_decrypt_data(const void *fit, - int image_noffset, int cipher_noffset, - const void *data_ciphered, size_t size_ciphered, - void **data_unciphered, size_t *size_unciphered) -{ - struct image_cipher_info info; - int ret; - - ret = fit_image_setup_decrypt(&info, fit, image_noffset, - cipher_noffset); - if (ret < 0) - goto out; - - ret = info.cipher->decrypt(&info, data_ciphered, size_ciphered, - data_unciphered, size_unciphered); - - out: - return ret; -} diff --git a/common/image-fdt.c b/common/image-fdt.c deleted file mode 100644 index 7aad6d57b89..00000000000 --- a/common/image-fdt.c +++ /dev/null @@ -1,666 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2013, Google Inc. - * - * (C) Copyright 2008 Semihalf - * - * (C) Copyright 2000-2006 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#include <common.h> -#include <fdt_support.h> -#include <fdtdec.h> -#include <env.h> -#include <errno.h> -#include <image.h> -#include <lmb.h> -#include <log.h> -#include <malloc.h> -#include <asm/global_data.h> -#include <linux/libfdt.h> -#include <mapmem.h> -#include <asm/io.h> -#include <tee/optee.h> - -#ifndef CONFIG_SYS_FDT_PAD -#define CONFIG_SYS_FDT_PAD 0x3000 -#endif - -/* adding a ramdisk needs 0x44 bytes in version 2008.10 */ -#define FDT_RAMDISK_OVERHEAD 0x80 - -DECLARE_GLOBAL_DATA_PTR; - -static void fdt_error(const char *msg) -{ - puts("ERROR: "); - puts(msg); - puts(" - must RESET the board to recover.\n"); -} - -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) -static const image_header_t *image_get_fdt(ulong fdt_addr) -{ - const image_header_t *fdt_hdr = map_sysmem(fdt_addr, 0); - - image_print_contents(fdt_hdr); - - puts(" Verifying Checksum ... "); - if (!image_check_hcrc(fdt_hdr)) { - fdt_error("fdt header checksum invalid"); - return NULL; - } - - if (!image_check_dcrc(fdt_hdr)) { - fdt_error("fdt checksum invalid"); - return NULL; - } - puts("OK\n"); - - if (!image_check_type(fdt_hdr, IH_TYPE_FLATDT)) { - fdt_error("uImage is not a fdt"); - return NULL; - } - if (image_get_comp(fdt_hdr) != IH_COMP_NONE) { - fdt_error("uImage is compressed"); - return NULL; - } - if (fdt_check_header((void *)image_get_data(fdt_hdr)) != 0) { - fdt_error("uImage data is not a fdt"); - return NULL; - } - return fdt_hdr; -} -#endif - -static void boot_fdt_reserve_region(struct lmb *lmb, uint64_t addr, - uint64_t size, enum lmb_flags flags) -{ - long ret; - - ret = lmb_reserve_flags(lmb, addr, size, flags); - if (ret >= 0) { - debug(" reserving fdt memory region: addr=%llx size=%llx flags=%x\n", - (unsigned long long)addr, - (unsigned long long)size, flags); - } else { - puts("ERROR: reserving fdt memory region failed "); - printf("(addr=%llx size=%llx flags=%x)\n", - (unsigned long long)addr, - (unsigned long long)size, flags); - } -} - -/** - * boot_fdt_add_mem_rsv_regions - Mark the memreserve and reserved-memory - * sections as unusable - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @fdt_blob: pointer to fdt blob base address - * - * Adds the and reserved-memorymemreserve regions in the dtb to the lmb block. - * Adding the memreserve regions prevents u-boot from using them to store the - * initrd or the fdt blob. - */ -void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob) -{ - uint64_t addr, size; - int i, total, ret; - int nodeoffset, subnode; - struct fdt_resource res; - enum lmb_flags flags; - - if (fdt_check_header(fdt_blob) != 0) - return; - - /* process memreserve sections */ - total = fdt_num_mem_rsv(fdt_blob); - for (i = 0; i < total; i++) { - if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0) - continue; - boot_fdt_reserve_region(lmb, addr, size, LMB_NONE); - } - - /* process reserved-memory */ - nodeoffset = fdt_subnode_offset(fdt_blob, 0, "reserved-memory"); - if (nodeoffset >= 0) { - subnode = fdt_first_subnode(fdt_blob, nodeoffset); - while (subnode >= 0) { - /* check if this subnode has a reg property */ - ret = fdt_get_resource(fdt_blob, subnode, "reg", 0, - &res); - if (!ret && fdtdec_get_is_enabled(fdt_blob, subnode)) { - flags = LMB_NONE; - if (fdtdec_get_bool(fdt_blob, subnode, - "no-map")) - flags = LMB_NOMAP; - addr = res.start; - size = res.end - res.start + 1; - boot_fdt_reserve_region(lmb, addr, size, flags); - } - - subnode = fdt_next_subnode(fdt_blob, subnode); - } - } -} - -/** - * boot_relocate_fdt - relocate flat device tree - * @lmb: pointer to lmb handle, will be used for memory mgmt - * @of_flat_tree: pointer to a char* variable, will hold fdt start address - * @of_size: pointer to a ulong variable, will hold fdt length - * - * boot_relocate_fdt() allocates a region of memory within the bootmap and - * relocates the of_flat_tree into that region, even if the fdt is already in - * the bootmap. It also expands the size of the fdt by CONFIG_SYS_FDT_PAD - * bytes. - * - * of_flat_tree and of_size are set to final (after relocation) values - * - * returns: - * 0 - success - * 1 - failure - */ -int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) -{ - void *fdt_blob = *of_flat_tree; - void *of_start = NULL; - char *fdt_high; - ulong of_len = 0; - int err; - int disable_relocation = 0; - - /* nothing to do */ - if (*of_size == 0) - return 0; - - if (fdt_check_header(fdt_blob) != 0) { - fdt_error("image is not a fdt"); - goto error; - } - - /* position on a 4K boundary before the alloc_current */ - /* Pad the FDT by a specified amount */ - of_len = *of_size + CONFIG_SYS_FDT_PAD; - - /* If fdt_high is set use it to select the relocation address */ - fdt_high = env_get("fdt_high"); - if (fdt_high) { - void *desired_addr = (void *)hextoul(fdt_high, NULL); - - if (((ulong) desired_addr) == ~0UL) { - /* All ones means use fdt in place */ - of_start = fdt_blob; - lmb_reserve(lmb, (ulong)of_start, of_len); - disable_relocation = 1; - } else if (desired_addr) { - of_start = - (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, - (ulong)desired_addr); - if (of_start == NULL) { - puts("Failed using fdt_high value for Device Tree"); - goto error; - } - } else { - of_start = - (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000); - } - } else { - of_start = - (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, - env_get_bootm_mapsize() - + env_get_bootm_low()); - } - - if (of_start == NULL) { - puts("device tree - allocation error\n"); - goto error; - } - - if (disable_relocation) { - /* - * We assume there is space after the existing fdt to use - * for padding - */ - fdt_set_totalsize(of_start, of_len); - printf(" Using Device Tree in place at %p, end %p\n", - of_start, of_start + of_len - 1); - } else { - debug("## device tree at %p ... %p (len=%ld [0x%lX])\n", - fdt_blob, fdt_blob + *of_size - 1, of_len, of_len); - - printf(" Loading Device Tree to %p, end %p ... ", - of_start, of_start + of_len - 1); - - err = fdt_open_into(fdt_blob, of_start, of_len); - if (err != 0) { - fdt_error("fdt move failed"); - goto error; - } - puts("OK\n"); - } - - *of_flat_tree = of_start; - *of_size = of_len; - - if (CONFIG_IS_ENABLED(CMD_FDT)) - set_working_fdt_addr(map_to_sysmem(*of_flat_tree)); - return 0; - -error: - return 1; -} - -/** - * select_fdt() - Select and locate the FDT to use - * - * @images: pointer to the bootm images structure - * @select: name of FDT to select, or NULL for any - * @arch: expected FDT architecture - * @fdt_addrp: pointer to a ulong variable, will hold FDT pointer - * @return 0 if OK, -ENOPKG if no FDT (but an error should not be reported), - * other -ve value on other error - */ - -static int select_fdt(bootm_headers_t *images, const char *select, u8 arch, - ulong *fdt_addrp) -{ - const char *buf; - ulong fdt_addr; - -#if CONFIG_IS_ENABLED(FIT) - const char *fit_uname_config = images->fit_uname_cfg; - const char *fit_uname_fdt = NULL; - ulong default_addr; - int fdt_noffset; - - if (select) { - /* - * If the FDT blob comes from the FIT image and the - * FIT image address is omitted in the command line - * argument, try to use ramdisk or os FIT image - * address or default load address. - */ - if (images->fit_uname_rd) - default_addr = (ulong)images->fit_hdr_rd; - else if (images->fit_uname_os) - default_addr = (ulong)images->fit_hdr_os; - else - default_addr = image_load_addr; - - if (fit_parse_conf(select, default_addr, &fdt_addr, - &fit_uname_config)) { - debug("* fdt: config '%s' from image at 0x%08lx\n", - fit_uname_config, fdt_addr); - } else if (fit_parse_subimage(select, default_addr, &fdt_addr, - &fit_uname_fdt)) { - debug("* fdt: subimage '%s' from image at 0x%08lx\n", - fit_uname_fdt, fdt_addr); - } else -#endif - { - fdt_addr = hextoul(select, NULL); - debug("* fdt: cmdline image address = 0x%08lx\n", - fdt_addr); - } -#if CONFIG_IS_ENABLED(FIT) - } else { - /* use FIT configuration provided in first bootm - * command argument - */ - fdt_addr = map_to_sysmem(images->fit_hdr_os); - fdt_noffset = fit_get_node_from_config(images, FIT_FDT_PROP, - fdt_addr); - if (fdt_noffset == -ENOENT) - return -ENOPKG; - else if (fdt_noffset < 0) - return fdt_noffset; - } -#endif - debug("## Checking for 'FDT'/'FDT Image' at %08lx\n", - fdt_addr); - - /* - * Check if there is an FDT image at the - * address provided in the second bootm argument - * check image type, for FIT images get a FIT node. - */ - buf = map_sysmem(fdt_addr, 0); - switch (genimg_get_format(buf)) { -#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - case IMAGE_FORMAT_LEGACY: { - const image_header_t *fdt_hdr; - ulong load, load_end; - ulong image_start, image_data, image_end; - - /* verify fdt_addr points to a valid image header */ - printf("## Flattened Device Tree from Legacy Image at %08lx\n", - fdt_addr); - fdt_hdr = image_get_fdt(fdt_addr); - if (!fdt_hdr) - return -ENOPKG; - - /* - * move image data to the load address, - * make sure we don't overwrite initial image - */ - image_start = (ulong)fdt_hdr; - image_data = (ulong)image_get_data(fdt_hdr); - image_end = image_get_image_end(fdt_hdr); - - load = image_get_load(fdt_hdr); - load_end = load + image_get_data_size(fdt_hdr); - - if (load == image_start || - load == image_data) { - fdt_addr = load; - break; - } - - if ((load < image_end) && (load_end > image_start)) { - fdt_error("fdt overwritten"); - return -EFAULT; - } - - debug(" Loading FDT from 0x%08lx to 0x%08lx\n", - image_data, load); - - memmove((void *)load, - (void *)image_data, - image_get_data_size(fdt_hdr)); - - fdt_addr = load; - break; - } -#endif - case IMAGE_FORMAT_FIT: - /* - * This case will catch both: new uImage format - * (libfdt based) and raw FDT blob (also libfdt - * based). - */ -#if CONFIG_IS_ENABLED(FIT) - /* check FDT blob vs FIT blob */ - if (!fit_check_format(buf, IMAGE_SIZE_INVAL)) { - ulong load, len; - - fdt_noffset = boot_get_fdt_fit(images, fdt_addr, - &fit_uname_fdt, - &fit_uname_config, - arch, &load, &len); - - if (fdt_noffset < 0) - return -ENOENT; - - images->fit_hdr_fdt = map_sysmem(fdt_addr, 0); - images->fit_uname_fdt = fit_uname_fdt; - images->fit_noffset_fdt = fdt_noffset; - fdt_addr = load; - - break; - } else -#endif - { - /* - * FDT blob - */ - debug("* fdt: raw FDT blob\n"); - printf("## Flattened Device Tree blob at %08lx\n", - (long)fdt_addr); - } - break; - default: - puts("ERROR: Did not find a cmdline Flattened Device Tree\n"); - return -ENOENT; - } - *fdt_addrp = fdt_addr; - - return 0; -} - -/** - * boot_get_fdt - main fdt handling routine - * @argc: command argument count - * @argv: command argument list - * @arch: architecture (IH_ARCH_...) - * @images: pointer to the bootm images structure - * @of_flat_tree: pointer to a char* variable, will hold fdt start address - * @of_size: pointer to a ulong variable, will hold fdt length - * - * boot_get_fdt() is responsible for finding a valid flat device tree image. - * Currently supported are the following ramdisk sources: - * - multicomponent kernel/ramdisk image, - * - commandline provided address of decicated ramdisk image. - * - * returns: - * 0, if fdt image was found and valid, or skipped - * of_flat_tree and of_size are set to fdt start address and length if - * fdt image is found and valid - * - * 1, if fdt image is found but corrupted - * of_flat_tree and of_size are set to 0 if no fdt exists - */ -int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, - bootm_headers_t *images, char **of_flat_tree, ulong *of_size) -{ - ulong img_addr; - ulong fdt_addr; - char *fdt_blob = NULL; - void *buf; - const char *select = NULL; - - *of_flat_tree = NULL; - *of_size = 0; - - img_addr = (argc == 0) ? image_load_addr : hextoul(argv[0], NULL); - buf = map_sysmem(img_addr, 0); - - if (argc > 2) - select = argv[2]; - if (select || genimg_has_config(images)) { - int ret; - - ret = select_fdt(images, select, arch, &fdt_addr); - if (ret == -ENOPKG) - goto no_fdt; - else if (ret) - return 1; - printf(" Booting using the fdt blob at %#08lx\n", fdt_addr); - fdt_blob = map_sysmem(fdt_addr, 0); - } else if (images->legacy_hdr_valid && - image_check_type(&images->legacy_hdr_os_copy, - IH_TYPE_MULTI)) { - ulong fdt_data, fdt_len; - - /* - * Now check if we have a legacy multi-component image, - * get second entry data start address and len. - */ - printf("## Flattened Device Tree from multi component Image at %08lX\n", - (ulong)images->legacy_hdr_os); - - image_multi_getimg(images->legacy_hdr_os, 2, &fdt_data, - &fdt_len); - if (fdt_len) { - fdt_blob = (char *)fdt_data; - printf(" Booting using the fdt at 0x%p\n", fdt_blob); - - if (fdt_check_header(fdt_blob) != 0) { - fdt_error("image is not a fdt"); - goto error; - } - - if (fdt_totalsize(fdt_blob) != fdt_len) { - fdt_error("fdt size != image size"); - goto error; - } - } else { - debug("## No Flattened Device Tree\n"); - goto no_fdt; - } -#ifdef CONFIG_ANDROID_BOOT_IMAGE - } else if (genimg_get_format(buf) == IMAGE_FORMAT_ANDROID) { - struct andr_img_hdr *hdr = buf; - ulong fdt_data, fdt_len; - u32 fdt_size, dtb_idx; - /* - * Firstly check if this android boot image has dtb field. - */ - dtb_idx = (u32)env_get_ulong("adtb_idx", 10, 0); - if (android_image_get_dtb_by_index((ulong)hdr, dtb_idx, &fdt_addr, &fdt_size)) { - fdt_blob = (char *)map_sysmem(fdt_addr, 0); - if (fdt_check_header(fdt_blob)) - goto no_fdt; - - debug("## Using FDT in Android image dtb area with idx %u\n", dtb_idx); - } else if (!android_image_get_second(hdr, &fdt_data, &fdt_len) && - !fdt_check_header((char *)fdt_data)) { - fdt_blob = (char *)fdt_data; - if (fdt_totalsize(fdt_blob) != fdt_len) - goto error; - - debug("## Using FDT in Android image second area\n"); - } else { - fdt_addr = env_get_hex("fdtaddr", 0); - if (!fdt_addr) - goto no_fdt; - - fdt_blob = map_sysmem(fdt_addr, 0); - if (fdt_check_header(fdt_blob)) - goto no_fdt; - - debug("## Using FDT at ${fdtaddr}=Ox%lx\n", fdt_addr); - } -#endif - } else { - debug("## No Flattened Device Tree\n"); - goto no_fdt; - } - - *of_flat_tree = fdt_blob; - *of_size = fdt_totalsize(fdt_blob); - debug(" of_flat_tree at 0x%08lx size 0x%08lx\n", - (ulong)*of_flat_tree, *of_size); - - return 0; - -no_fdt: - debug("Continuing to boot without FDT\n"); - return 0; -error: - return 1; -} - -/* - * Verify the device tree. - * - * This function is called after all device tree fix-ups have been enacted, - * so that the final device tree can be verified. The definition of "verified" - * is up to the specific implementation. However, it generally means that the - * addresses of some of the devices in the device tree are compared with the - * actual addresses at which U-Boot has placed them. - * - * Returns 1 on success, 0 on failure. If 0 is returned, U-Boot will halt the - * boot process. - */ -__weak int ft_verify_fdt(void *fdt) -{ - return 1; -} - -__weak int arch_fixup_fdt(void *blob) -{ - return 0; -} - -int image_setup_libfdt(bootm_headers_t *images, void *blob, - int of_size, struct lmb *lmb) -{ - ulong *initrd_start = &images->initrd_start; - ulong *initrd_end = &images->initrd_end; - int ret = -EPERM; - int fdt_ret; - - if (fdt_root(blob) < 0) { - printf("ERROR: root node setup failed\n"); - goto err; - } - if (fdt_chosen(blob) < 0) { - printf("ERROR: /chosen node create failed\n"); - goto err; - } - if (arch_fixup_fdt(blob) < 0) { - printf("ERROR: arch-specific fdt fixup failed\n"); - goto err; - } - - fdt_ret = optee_copy_fdt_nodes(blob); - if (fdt_ret) { - printf("ERROR: transfer of optee nodes to new fdt failed: %s\n", - fdt_strerror(fdt_ret)); - goto err; - } - - /* Update ethernet nodes */ - fdt_fixup_ethernet(blob); -#if CONFIG_IS_ENABLED(CMD_PSTORE) - /* Append PStore configuration */ - fdt_fixup_pstore(blob); -#endif - if (IS_ENABLED(CONFIG_OF_BOARD_SETUP)) { - const char *skip_board_fixup; - - skip_board_fixup = env_get("skip_board_fixup"); - if (skip_board_fixup && ((int)simple_strtol(skip_board_fixup, NULL, 10) == 1)) { - printf("skip board fdt fixup\n"); - } else { - fdt_ret = ft_board_setup(blob, gd->bd); - if (fdt_ret) { - printf("ERROR: board-specific fdt fixup failed: %s\n", - fdt_strerror(fdt_ret)); - goto err; - } - } - } - if (IS_ENABLED(CONFIG_OF_SYSTEM_SETUP)) { - fdt_ret = ft_system_setup(blob, gd->bd); - if (fdt_ret) { - printf("ERROR: system-specific fdt fixup failed: %s\n", - fdt_strerror(fdt_ret)); - goto err; - } - } - - /* Delete the old LMB reservation */ - if (lmb) - lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob, - (phys_size_t)fdt_totalsize(blob)); - - ret = fdt_shrink_to_minimum(blob, 0); - if (ret < 0) - goto err; - of_size = ret; - - if (*initrd_start && *initrd_end) { - of_size += FDT_RAMDISK_OVERHEAD; - fdt_set_totalsize(blob, of_size); - } - /* Create a new LMB reservation */ - if (lmb) - lmb_reserve(lmb, (ulong)blob, of_size); - - fdt_initrd(blob, *initrd_start, *initrd_end); - if (!ft_verify_fdt(blob)) - goto err; - -#if defined(CONFIG_ARCH_KEYSTONE) - if (IS_ENABLED(CONFIG_OF_BOARD_SETUP)) - ft_board_setup_ex(blob, gd->bd); -#endif - - return 0; -err: - printf(" - must RESET the board to recover.\n\n"); - - return ret; -} diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c deleted file mode 100644 index 63e5423c925..00000000000 --- a/common/image-fit-sig.c +++ /dev/null @@ -1,486 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2013, Google Inc. - */ - -#ifdef USE_HOSTCC -#include "mkimage.h" -#include <time.h> -#else -#include <common.h> -#include <log.h> -#include <malloc.h> -#include <asm/global_data.h> -DECLARE_GLOBAL_DATA_PTR; -#endif /* !USE_HOSTCC*/ -#include <fdt_region.h> -#include <image.h> -#include <u-boot/rsa.h> -#include <u-boot/hash-checksum.h> - -#define IMAGE_MAX_HASHED_NODES 100 - -/** - * fit_region_make_list() - Make a list of image regions - * - * Given a list of fdt_regions, create a list of image_regions. This is a - * simple conversion routine since the FDT and image code use different - * structures. - * - * @fit: FIT image - * @fdt_regions: Pointer to FDT regions - * @count: Number of FDT regions - * @region: Pointer to image regions, which must hold @count records. If - * region is NULL, then (except for an SPL build) the array will be - * allocated. - * @return: Pointer to image regions - */ -struct image_region *fit_region_make_list(const void *fit, - struct fdt_region *fdt_regions, - int count, - struct image_region *region) -{ - int i; - - debug("Hash regions:\n"); - debug("%10s %10s\n", "Offset", "Size"); - - /* - * Use malloc() except in SPL (to save code size). In SPL the caller - * must allocate the array. - */ - if (!IS_ENABLED(CONFIG_SPL_BUILD) && !region) - region = calloc(sizeof(*region), count); - if (!region) - return NULL; - for (i = 0; i < count; i++) { - debug("%10x %10x\n", fdt_regions[i].offset, - fdt_regions[i].size); - region[i].data = fit + fdt_regions[i].offset; - region[i].size = fdt_regions[i].size; - } - - return region; -} - -static int fit_image_setup_verify(struct image_sign_info *info, - const void *fit, int noffset, - int required_keynode, char **err_msgp) -{ - char *algo_name; - const char *padding_name; - - if (fdt_totalsize(fit) > CONFIG_VAL(FIT_SIGNATURE_MAX_SIZE)) { - *err_msgp = "Total size too large"; - return 1; - } - if (fit_image_hash_get_algo(fit, noffset, &algo_name)) { - *err_msgp = "Can't get hash algo property"; - return -1; - } - - padding_name = fdt_getprop(fit, noffset, "padding", NULL); - if (!padding_name) - padding_name = RSA_DEFAULT_PADDING_NAME; - - memset(info, '\0', sizeof(*info)); - info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL); - info->fit = fit; - info->node_offset = noffset; - info->name = algo_name; - info->checksum = image_get_checksum_algo(algo_name); - info->crypto = image_get_crypto_algo(algo_name); - info->padding = image_get_padding_algo(padding_name); - info->fdt_blob = gd_fdt_blob(); - info->required_keynode = required_keynode; - printf("%s:%s", algo_name, info->keyname); - - if (!info->checksum || !info->crypto || !info->padding) { - *err_msgp = "Unknown signature algorithm"; - return -1; - } - - return 0; -} - -int fit_image_check_sig(const void *fit, int noffset, const void *data, - size_t size, int required_keynode, char **err_msgp) -{ - struct image_sign_info info; - struct image_region region; - uint8_t *fit_value; - int fit_value_len; - - *err_msgp = NULL; - if (fit_image_setup_verify(&info, fit, noffset, required_keynode, - err_msgp)) - return -1; - - if (fit_image_hash_get_value(fit, noffset, &fit_value, - &fit_value_len)) { - *err_msgp = "Can't get hash value property"; - return -1; - } - - region.data = data; - region.size = size; - - if (info.crypto->verify(&info, ®ion, 1, fit_value, fit_value_len)) { - *err_msgp = "Verification failed"; - return -1; - } - - return 0; -} - -static int fit_image_verify_sig(const void *fit, int image_noffset, - const char *data, size_t size, - const void *sig_blob, int sig_offset) -{ - int noffset; - char *err_msg = ""; - int verified = 0; - int ret; - - /* Process all hash subnodes of the component image node */ - fdt_for_each_subnode(noffset, fit, image_noffset) { - const char *name = fit_get_name(fit, noffset, NULL); - - /* - * We don't support this since libfdt considers names with the - * name root but different @ suffix to be equal - */ - if (strchr(name, '@')) { - err_msg = "Node name contains @"; - goto error; - } - if (!strncmp(name, FIT_SIG_NODENAME, - strlen(FIT_SIG_NODENAME))) { - ret = fit_image_check_sig(fit, noffset, data, - size, -1, &err_msg); - if (ret) { - puts("- "); - } else { - puts("+ "); - verified = 1; - break; - } - } - } - - if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { - err_msg = "Corrupted or truncated tree"; - goto error; - } - - return verified ? 0 : -EPERM; - -error: - printf(" error!\n%s for '%s' hash node in '%s' image node\n", - err_msg, fit_get_name(fit, noffset, NULL), - fit_get_name(fit, image_noffset, NULL)); - return -1; -} - -int fit_image_verify_required_sigs(const void *fit, int image_noffset, - const char *data, size_t size, - const void *sig_blob, int *no_sigsp) -{ - int verify_count = 0; - int noffset; - int sig_node; - - /* Work out what we need to verify */ - *no_sigsp = 1; - sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); - if (sig_node < 0) { - debug("%s: No signature node found: %s\n", __func__, - fdt_strerror(sig_node)); - return 0; - } - - fdt_for_each_subnode(noffset, sig_blob, sig_node) { - const char *required; - int ret; - - required = fdt_getprop(sig_blob, noffset, FIT_KEY_REQUIRED, - NULL); - if (!required || strcmp(required, "image")) - continue; - ret = fit_image_verify_sig(fit, image_noffset, data, size, - sig_blob, noffset); - if (ret) { - printf("Failed to verify required signature '%s'\n", - fit_get_name(sig_blob, noffset, NULL)); - return ret; - } - verify_count++; - } - - if (verify_count) - *no_sigsp = 0; - - return 0; -} - -/** - * fit_config_check_sig() - Check the signature of a config - * - * @fit: FIT to check - * @noffset: Offset of configuration node (e.g. /configurations/conf-1) - * @required_keynode: Offset in the control FDT of the required key node, - * if any. If this is given, then the configuration wil not - * pass verification unless that key is used. If this is - * -1 then any signature will do. - * @conf_noffset: Offset of the configuration subnode being checked (e.g. - * /configurations/conf-1/kernel) - * @err_msgp: In the event of an error, this will be pointed to a - * help error string to display to the user. - * @return 0 if all verified ok, <0 on error - */ -static int fit_config_check_sig(const void *fit, int noffset, - int required_keynode, int conf_noffset, - char **err_msgp) -{ - static char * const exc_prop[] = { - "data", - "data-size", - "data-position", - "data-offset" - }; - - const char *prop, *end, *name; - struct image_sign_info info; - const uint32_t *strings; - const char *config_name; - uint8_t *fit_value; - int fit_value_len; - bool found_config; - int max_regions; - int i, prop_len; - char path[200]; - int count; - - config_name = fit_get_name(fit, conf_noffset, NULL); - debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(), - fit_get_name(fit, noffset, NULL), - fit_get_name(gd_fdt_blob(), required_keynode, NULL)); - *err_msgp = NULL; - if (fit_image_setup_verify(&info, fit, noffset, required_keynode, - err_msgp)) - return -1; - - if (fit_image_hash_get_value(fit, noffset, &fit_value, - &fit_value_len)) { - *err_msgp = "Can't get hash value property"; - return -1; - } - - /* Count the number of strings in the property */ - prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len); - end = prop ? prop + prop_len : prop; - for (name = prop, count = 0; name < end; name++) - if (!*name) - count++; - if (!count) { - *err_msgp = "Can't get hashed-nodes property"; - return -1; - } - - if (prop && prop_len > 0 && prop[prop_len - 1] != '\0') { - *err_msgp = "hashed-nodes property must be null-terminated"; - return -1; - } - - /* Add a sanity check here since we are using the stack */ - if (count > IMAGE_MAX_HASHED_NODES) { - *err_msgp = "Number of hashed nodes exceeds maximum"; - return -1; - } - - /* Create a list of node names from those strings */ - char *node_inc[count]; - - debug("Hash nodes (%d):\n", count); - found_config = false; - for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) { - debug(" '%s'\n", name); - node_inc[i] = (char *)name; - if (!strncmp(FIT_CONFS_PATH, name, strlen(FIT_CONFS_PATH)) && - name[sizeof(FIT_CONFS_PATH) - 1] == '/' && - !strcmp(name + sizeof(FIT_CONFS_PATH), config_name)) { - debug(" (found config node %s)", config_name); - found_config = true; - } - } - if (!found_config) { - *err_msgp = "Selected config not in hashed nodes"; - return -1; - } - - /* - * Each node can generate one region for each sub-node. Allow for - * 7 sub-nodes (hash-1, signature-1, etc.) and some extra. - */ - max_regions = 20 + count * 7; - struct fdt_region fdt_regions[max_regions]; - - /* Get a list of regions to hash */ - count = fdt_find_regions(fit, node_inc, count, - exc_prop, ARRAY_SIZE(exc_prop), - fdt_regions, max_regions - 1, - path, sizeof(path), 0); - if (count < 0) { - *err_msgp = "Failed to hash configuration"; - return -1; - } - if (count == 0) { - *err_msgp = "No data to hash"; - return -1; - } - if (count >= max_regions - 1) { - *err_msgp = "Too many hash regions"; - return -1; - } - - /* Add the strings */ - strings = fdt_getprop(fit, noffset, "hashed-strings", NULL); - if (strings) { - /* - * The strings region offset must be a static 0x0. - * This is set in tool/image-host.c - */ - fdt_regions[count].offset = fdt_off_dt_strings(fit); - fdt_regions[count].size = fdt32_to_cpu(strings[1]); - count++; - } - - /* Allocate the region list on the stack */ - struct image_region region[count]; - - fit_region_make_list(fit, fdt_regions, count, region); - if (info.crypto->verify(&info, region, count, fit_value, - fit_value_len)) { - *err_msgp = "Verification failed"; - return -1; - } - - return 0; -} - -static int fit_config_verify_sig(const void *fit, int conf_noffset, - const void *sig_blob, int sig_offset) -{ - int noffset; - char *err_msg = "No 'signature' subnode found"; - int verified = 0; - int ret; - - /* Process all hash subnodes of the component conf node */ - fdt_for_each_subnode(noffset, fit, conf_noffset) { - const char *name = fit_get_name(fit, noffset, NULL); - - if (!strncmp(name, FIT_SIG_NODENAME, - strlen(FIT_SIG_NODENAME))) { - ret = fit_config_check_sig(fit, noffset, sig_offset, - conf_noffset, &err_msg); - if (ret) { - puts("- "); - } else { - puts("+ "); - verified = 1; - break; - } - } - } - - if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { - err_msg = "Corrupted or truncated tree"; - goto error; - } - - if (verified) - return 0; - -error: - printf(" error!\n%s for '%s' hash node in '%s' config node\n", - err_msg, fit_get_name(fit, noffset, NULL), - fit_get_name(fit, conf_noffset, NULL)); - return -EPERM; -} - -static int fit_config_verify_required_sigs(const void *fit, int conf_noffset, - const void *sig_blob) -{ - const char *name = fit_get_name(fit, conf_noffset, NULL); - int noffset; - int sig_node; - int verified = 0; - int reqd_sigs = 0; - bool reqd_policy_all = true; - const char *reqd_mode; - - /* - * We don't support this since libfdt considers names with the - * name root but different @ suffix to be equal - */ - if (strchr(name, '@')) { - printf("Configuration node '%s' contains '@'\n", name); - return -EPERM; - } - - /* Work out what we need to verify */ - sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); - if (sig_node < 0) { - debug("%s: No signature node found: %s\n", __func__, - fdt_strerror(sig_node)); - return 0; - } - - /* Get required-mode policy property from DTB */ - reqd_mode = fdt_getprop(sig_blob, sig_node, "required-mode", NULL); - if (reqd_mode && !strcmp(reqd_mode, "any")) - reqd_policy_all = false; - - debug("%s: required-mode policy set to '%s'\n", __func__, - reqd_policy_all ? "all" : "any"); - - fdt_for_each_subnode(noffset, sig_blob, sig_node) { - const char *required; - int ret; - - required = fdt_getprop(sig_blob, noffset, FIT_KEY_REQUIRED, - NULL); - if (!required || strcmp(required, "conf")) - continue; - - reqd_sigs++; - - ret = fit_config_verify_sig(fit, conf_noffset, sig_blob, - noffset); - if (ret) { - if (reqd_policy_all) { - printf("Failed to verify required signature '%s'\n", - fit_get_name(sig_blob, noffset, NULL)); - return ret; - } - } else { - verified++; - if (!reqd_policy_all) - break; - } - } - - if (reqd_sigs && !verified) { - printf("Failed to verify 'any' of the required signature(s)\n"); - return -EPERM; - } - - return 0; -} - -int fit_config_verify(const void *fit, int conf_noffset) -{ - return fit_config_verify_required_sigs(fit, conf_noffset, - gd_fdt_blob()); -} diff --git a/common/image-fit.c b/common/image-fit.c deleted file mode 100644 index 33b4a46028b..00000000000 --- a/common/image-fit.c +++ /dev/null @@ -1,2448 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2013, Google Inc. - * - * (C) Copyright 2008 Semihalf - * - * (C) Copyright 2000-2006 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#define LOG_CATEGORY LOGC_BOOT - -#ifdef USE_HOSTCC -#include "mkimage.h" -#include <time.h> -#include <linux/libfdt.h> -#include <u-boot/crc.h> -#else -#include <linux/compiler.h> -#include <linux/sizes.h> -#include <common.h> -#include <errno.h> -#include <log.h> -#include <mapmem.h> -#include <asm/io.h> -#include <malloc.h> -#include <asm/global_data.h> -#ifdef CONFIG_DM_HASH -#include <dm.h> -#include <u-boot/hash.h> -#endif -DECLARE_GLOBAL_DATA_PTR; -#endif /* !USE_HOSTCC*/ - -#include <bootm.h> -#include <image.h> -#include <bootstage.h> -#include <linux/kconfig.h> -#include <u-boot/crc.h> -#include <u-boot/md5.h> -#include <u-boot/sha1.h> -#include <u-boot/sha256.h> -#include <u-boot/sha512.h> - -/*****************************************************************************/ -/* New uImage format routines */ -/*****************************************************************************/ -#ifndef USE_HOSTCC -static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr, - ulong *addr, const char **name) -{ - const char *sep; - - *addr = addr_curr; - *name = NULL; - - sep = strchr(spec, sepc); - if (sep) { - if (sep - spec > 0) - *addr = hextoul(spec, NULL); - - *name = sep + 1; - return 1; - } - - return 0; -} - -/** - * fit_parse_conf - parse FIT configuration spec - * @spec: input string, containing configuration spec - * @add_curr: current image address (to be used as a possible default) - * @addr: pointer to a ulong variable, will hold FIT image address of a given - * configuration - * @conf_name double pointer to a char, will hold pointer to a configuration - * unit name - * - * fit_parse_conf() expects configuration spec in the form of [<addr>]#<conf>, - * where <addr> is a FIT image address that contains configuration - * with a <conf> unit name. - * - * Address part is optional, and if omitted default add_curr will - * be used instead. - * - * returns: - * 1 if spec is a valid configuration string, - * addr and conf_name are set accordingly - * 0 otherwise - */ -int fit_parse_conf(const char *spec, ulong addr_curr, - ulong *addr, const char **conf_name) -{ - return fit_parse_spec(spec, '#', addr_curr, addr, conf_name); -} - -/** - * fit_parse_subimage - parse FIT subimage spec - * @spec: input string, containing subimage spec - * @add_curr: current image address (to be used as a possible default) - * @addr: pointer to a ulong variable, will hold FIT image address of a given - * subimage - * @image_name: double pointer to a char, will hold pointer to a subimage name - * - * fit_parse_subimage() expects subimage spec in the form of - * [<addr>]:<subimage>, where <addr> is a FIT image address that contains - * subimage with a <subimg> unit name. - * - * Address part is optional, and if omitted default add_curr will - * be used instead. - * - * returns: - * 1 if spec is a valid subimage string, - * addr and image_name are set accordingly - * 0 otherwise - */ -int fit_parse_subimage(const char *spec, ulong addr_curr, - ulong *addr, const char **image_name) -{ - return fit_parse_spec(spec, ':', addr_curr, addr, image_name); -} -#endif /* !USE_HOSTCC */ - -#ifdef USE_HOSTCC -/* Host tools use these implementations for Cipher and Signature support */ -static void *host_blob; - -void image_set_host_blob(void *blob) -{ - host_blob = blob; -} - -void *image_get_host_blob(void) -{ - return host_blob; -} -#endif /* USE_HOSTCC */ - -static void fit_get_debug(const void *fit, int noffset, - char *prop_name, int err) -{ - debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n", - prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL), - fdt_strerror(err)); -} - -/** - * fit_get_subimage_count - get component (sub-image) count - * @fit: pointer to the FIT format image header - * @images_noffset: offset of images node - * - * returns: - * number of image components - */ -int fit_get_subimage_count(const void *fit, int images_noffset) -{ - int noffset; - int ndepth; - int count = 0; - - /* Process its subnodes, print out component images details */ - for (ndepth = 0, count = 0, - noffset = fdt_next_node(fit, images_noffset, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(fit, noffset, &ndepth)) { - if (ndepth == 1) { - count++; - } - } - - return count; -} - -/** - * fit_image_print_data() - prints out the hash node details - * @fit: pointer to the FIT format image header - * @noffset: offset of the hash node - * @p: pointer to prefix string - * @type: Type of information to print ("hash" or "sign") - * - * fit_image_print_data() lists properties for the processed hash node - * - * This function avoid using puts() since it prints a newline on the host - * but does not in U-Boot. - * - * returns: - * no returned results - */ -static void fit_image_print_data(const void *fit, int noffset, const char *p, - const char *type) -{ - const char *keyname; - uint8_t *value; - int value_len; - char *algo; - const char *padding; - bool required; - int ret, i; - - debug("%s %s node: '%s'\n", p, type, - fit_get_name(fit, noffset, NULL)); - printf("%s %s algo: ", p, type); - if (fit_image_hash_get_algo(fit, noffset, &algo)) { - printf("invalid/unsupported\n"); - return; - } - printf("%s", algo); - keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL); - required = fdt_getprop(fit, noffset, FIT_KEY_REQUIRED, NULL) != NULL; - if (keyname) - printf(":%s", keyname); - if (required) - printf(" (required)"); - printf("\n"); - - padding = fdt_getprop(fit, noffset, "padding", NULL); - if (padding) - printf("%s %s padding: %s\n", p, type, padding); - - ret = fit_image_hash_get_value(fit, noffset, &value, - &value_len); - printf("%s %s value: ", p, type); - if (ret) { - printf("unavailable\n"); - } else { - for (i = 0; i < value_len; i++) - printf("%02x", value[i]); - printf("\n"); - } - - debug("%s %s len: %d\n", p, type, value_len); - - /* Signatures have a time stamp */ - if (IMAGE_ENABLE_TIMESTAMP && keyname) { - time_t timestamp; - - printf("%s Timestamp: ", p); - if (fit_get_timestamp(fit, noffset, ×tamp)) - printf("unavailable\n"); - else - genimg_print_time(timestamp); - } -} - -/** - * fit_image_print_verification_data() - prints out the hash/signature details - * @fit: pointer to the FIT format image header - * @noffset: offset of the hash or signature node - * @p: pointer to prefix string - * - * This lists properties for the processed hash node - * - * returns: - * no returned results - */ -static void fit_image_print_verification_data(const void *fit, int noffset, - const char *p) -{ - const char *name; - - /* - * Check subnode name, must be equal to "hash" or "signature". - * Multiple hash/signature nodes require unique unit node - * names, e.g. hash-1, hash-2, signature-1, signature-2, etc. - */ - name = fit_get_name(fit, noffset, NULL); - if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) { - fit_image_print_data(fit, noffset, p, "Hash"); - } else if (!strncmp(name, FIT_SIG_NODENAME, - strlen(FIT_SIG_NODENAME))) { - fit_image_print_data(fit, noffset, p, "Sign"); - } -} - -/** - * fit_conf_print - prints out the FIT configuration details - * @fit: pointer to the FIT format image header - * @noffset: offset of the configuration node - * @p: pointer to prefix string - * - * fit_conf_print() lists all mandatory properties for the processed - * configuration node. - * - * returns: - * no returned results - */ -static void fit_conf_print(const void *fit, int noffset, const char *p) -{ - char *desc; - const char *uname; - int ret; - int fdt_index, loadables_index; - int ndepth; - - /* Mandatory properties */ - ret = fit_get_desc(fit, noffset, &desc); - printf("%s Description: ", p); - if (ret) - printf("unavailable\n"); - else - printf("%s\n", desc); - - uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL); - printf("%s Kernel: ", p); - if (!uname) - printf("unavailable\n"); - else - printf("%s\n", uname); - - /* Optional properties */ - uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL); - if (uname) - printf("%s Init Ramdisk: %s\n", p, uname); - - uname = fdt_getprop(fit, noffset, FIT_FIRMWARE_PROP, NULL); - if (uname) - printf("%s Firmware: %s\n", p, uname); - - for (fdt_index = 0; - uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP, - fdt_index, NULL), uname; - fdt_index++) { - if (fdt_index == 0) - printf("%s FDT: ", p); - else - printf("%s ", p); - printf("%s\n", uname); - } - - uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL); - if (uname) - printf("%s FPGA: %s\n", p, uname); - - /* Print out all of the specified loadables */ - for (loadables_index = 0; - uname = fdt_stringlist_get(fit, noffset, FIT_LOADABLE_PROP, - loadables_index, NULL), uname; - loadables_index++) { - if (loadables_index == 0) { - printf("%s Loadables: ", p); - } else { - printf("%s ", p); - } - printf("%s\n", uname); - } - - /* Process all hash subnodes of the component configuration node */ - for (ndepth = 0, noffset = fdt_next_node(fit, noffset, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(fit, noffset, &ndepth)) { - if (ndepth == 1) { - /* Direct child node of the component configuration node */ - fit_image_print_verification_data(fit, noffset, p); - } - } -} - -/** - * fit_print_contents - prints out the contents of the FIT format image - * @fit: pointer to the FIT format image header - * @p: pointer to prefix string - * - * fit_print_contents() formats a multi line FIT image contents description. - * The routine prints out FIT image properties (root node level) followed by - * the details of each component image. - * - * returns: - * no returned results - */ -void fit_print_contents(const void *fit) -{ - char *desc; - char *uname; - int images_noffset; - int confs_noffset; - int noffset; - int ndepth; - int count = 0; - int ret; - const char *p; - time_t timestamp; - - if (!CONFIG_IS_ENABLED(FIT_PRINT)) - return; - - /* Indent string is defined in header image.h */ - p = IMAGE_INDENT_STRING; - - /* Root node properties */ - ret = fit_get_desc(fit, 0, &desc); - printf("%sFIT description: ", p); - if (ret) - printf("unavailable\n"); - else - printf("%s\n", desc); - - if (IMAGE_ENABLE_TIMESTAMP) { - ret = fit_get_timestamp(fit, 0, ×tamp); - printf("%sCreated: ", p); - if (ret) - printf("unavailable\n"); - else - genimg_print_time(timestamp); - } - - /* Find images parent node offset */ - images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); - if (images_noffset < 0) { - printf("Can't find images parent node '%s' (%s)\n", - FIT_IMAGES_PATH, fdt_strerror(images_noffset)); - return; - } - - /* Process its subnodes, print out component images details */ - for (ndepth = 0, count = 0, - noffset = fdt_next_node(fit, images_noffset, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(fit, noffset, &ndepth)) { - if (ndepth == 1) { - /* - * Direct child node of the images parent node, - * i.e. component image node. - */ - printf("%s Image %u (%s)\n", p, count++, - fit_get_name(fit, noffset, NULL)); - - fit_image_print(fit, noffset, p); - } - } - - /* Find configurations parent node offset */ - confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); - if (confs_noffset < 0) { - debug("Can't get configurations parent node '%s' (%s)\n", - FIT_CONFS_PATH, fdt_strerror(confs_noffset)); - return; - } - - /* get default configuration unit name from default property */ - uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL); - if (uname) - printf("%s Default Configuration: '%s'\n", p, uname); - - /* Process its subnodes, print out configurations details */ - for (ndepth = 0, count = 0, - noffset = fdt_next_node(fit, confs_noffset, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(fit, noffset, &ndepth)) { - if (ndepth == 1) { - /* - * Direct child node of the configurations parent node, - * i.e. configuration node. - */ - printf("%s Configuration %u (%s)\n", p, count++, - fit_get_name(fit, noffset, NULL)); - - fit_conf_print(fit, noffset, p); - } - } -} - -/** - * fit_image_print - prints out the FIT component image details - * @fit: pointer to the FIT format image header - * @image_noffset: offset of the component image node - * @p: pointer to prefix string - * - * fit_image_print() lists all mandatory properties for the processed component - * image. If present, hash nodes are printed out as well. Load - * address for images of type firmware is also printed out. Since the load - * address is not mandatory for firmware images, it will be output as - * "unavailable" when not present. - * - * returns: - * no returned results - */ -void fit_image_print(const void *fit, int image_noffset, const char *p) -{ - char *desc; - uint8_t type, arch, os, comp; - size_t size; - ulong load, entry; - const void *data; - int noffset; - int ndepth; - int ret; - - if (!CONFIG_IS_ENABLED(FIT_PRINT)) - return; - - /* Mandatory properties */ - ret = fit_get_desc(fit, image_noffset, &desc); - printf("%s Description: ", p); - if (ret) - printf("unavailable\n"); - else - printf("%s\n", desc); - - if (IMAGE_ENABLE_TIMESTAMP) { - time_t timestamp; - - ret = fit_get_timestamp(fit, 0, ×tamp); - printf("%s Created: ", p); - if (ret) - printf("unavailable\n"); - else - genimg_print_time(timestamp); - } - - fit_image_get_type(fit, image_noffset, &type); - printf("%s Type: %s\n", p, genimg_get_type_name(type)); - - fit_image_get_comp(fit, image_noffset, &comp); - printf("%s Compression: %s\n", p, genimg_get_comp_name(comp)); - - ret = fit_image_get_data_and_size(fit, image_noffset, &data, &size); - - if (!tools_build()) { - printf("%s Data Start: ", p); - if (ret) { - printf("unavailable\n"); - } else { - void *vdata = (void *)data; - - printf("0x%08lx\n", (ulong)map_to_sysmem(vdata)); - } - } - - printf("%s Data Size: ", p); - if (ret) - printf("unavailable\n"); - else - genimg_print_size(size); - - /* Remaining, type dependent properties */ - if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || - (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) || - (type == IH_TYPE_FLATDT)) { - fit_image_get_arch(fit, image_noffset, &arch); - printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); - } - - if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK) || - (type == IH_TYPE_FIRMWARE)) { - fit_image_get_os(fit, image_noffset, &os); - printf("%s OS: %s\n", p, genimg_get_os_name(os)); - } - - if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || - (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK) || - (type == IH_TYPE_FPGA)) { - ret = fit_image_get_load(fit, image_noffset, &load); - printf("%s Load Address: ", p); - if (ret) - printf("unavailable\n"); - else - printf("0x%08lx\n", load); - } - - /* optional load address for FDT */ - if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load)) - printf("%s Load Address: 0x%08lx\n", p, load); - - if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || - (type == IH_TYPE_RAMDISK)) { - ret = fit_image_get_entry(fit, image_noffset, &entry); - printf("%s Entry Point: ", p); - if (ret) - printf("unavailable\n"); - else - printf("0x%08lx\n", entry); - } - - /* Process all hash subnodes of the component image node */ - for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(fit, noffset, &ndepth)) { - if (ndepth == 1) { - /* Direct child node of the component image node */ - fit_image_print_verification_data(fit, noffset, p); - } - } -} - -/** - * fit_get_desc - get node description property - * @fit: pointer to the FIT format image header - * @noffset: node offset - * @desc: double pointer to the char, will hold pointer to the description - * - * fit_get_desc() reads description property from a given node, if - * description is found pointer to it is returned in third call argument. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_get_desc(const void *fit, int noffset, char **desc) -{ - int len; - - *desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len); - if (*desc == NULL) { - fit_get_debug(fit, noffset, FIT_DESC_PROP, len); - return -1; - } - - return 0; -} - -/** - * fit_get_timestamp - get node timestamp property - * @fit: pointer to the FIT format image header - * @noffset: node offset - * @timestamp: pointer to the time_t, will hold read timestamp - * - * fit_get_timestamp() reads timestamp property from given node, if timestamp - * is found and has a correct size its value is returned in third call - * argument. - * - * returns: - * 0, on success - * -1, on property read failure - * -2, on wrong timestamp size - */ -int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp) -{ - int len; - const void *data; - - data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len); - if (data == NULL) { - fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len); - return -1; - } - if (len != sizeof(uint32_t)) { - debug("FIT timestamp with incorrect size of (%u)\n", len); - return -2; - } - - *timestamp = uimage_to_cpu(*((uint32_t *)data)); - return 0; -} - -/** - * fit_image_get_node - get node offset for component image of a given unit name - * @fit: pointer to the FIT format image header - * @image_uname: component image node unit name - * - * fit_image_get_node() finds a component image (within the '/images' - * node) of a provided unit name. If image is found its node offset is - * returned to the caller. - * - * returns: - * image node offset when found (>=0) - * negative number on failure (FDT_ERR_* code) - */ -int fit_image_get_node(const void *fit, const char *image_uname) -{ - int noffset, images_noffset; - - images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); - if (images_noffset < 0) { - debug("Can't find images parent node '%s' (%s)\n", - FIT_IMAGES_PATH, fdt_strerror(images_noffset)); - return images_noffset; - } - - noffset = fdt_subnode_offset(fit, images_noffset, image_uname); - if (noffset < 0) { - debug("Can't get node offset for image unit name: '%s' (%s)\n", - image_uname, fdt_strerror(noffset)); - } - - return noffset; -} - -/** - * fit_image_get_os - get os id for a given component image node - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @os: pointer to the uint8_t, will hold os numeric id - * - * fit_image_get_os() finds os property in a given component image node. - * If the property is found, its (string) value is translated to the numeric - * id which is returned to the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_get_os(const void *fit, int noffset, uint8_t *os) -{ - int len; - const void *data; - - /* Get OS name from property data */ - data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len); - if (data == NULL) { - fit_get_debug(fit, noffset, FIT_OS_PROP, len); - *os = -1; - return -1; - } - - /* Translate OS name to id */ - *os = genimg_get_os_id(data); - return 0; -} - -/** - * fit_image_get_arch - get arch id for a given component image node - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @arch: pointer to the uint8_t, will hold arch numeric id - * - * fit_image_get_arch() finds arch property in a given component image node. - * If the property is found, its (string) value is translated to the numeric - * id which is returned to the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch) -{ - int len; - const void *data; - - /* Get architecture name from property data */ - data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len); - if (data == NULL) { - fit_get_debug(fit, noffset, FIT_ARCH_PROP, len); - *arch = -1; - return -1; - } - - /* Translate architecture name to id */ - *arch = genimg_get_arch_id(data); - return 0; -} - -/** - * fit_image_get_type - get type id for a given component image node - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @type: pointer to the uint8_t, will hold type numeric id - * - * fit_image_get_type() finds type property in a given component image node. - * If the property is found, its (string) value is translated to the numeric - * id which is returned to the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_get_type(const void *fit, int noffset, uint8_t *type) -{ - int len; - const void *data; - - /* Get image type name from property data */ - data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len); - if (data == NULL) { - fit_get_debug(fit, noffset, FIT_TYPE_PROP, len); - *type = -1; - return -1; - } - - /* Translate image type name to id */ - *type = genimg_get_type_id(data); - return 0; -} - -/** - * fit_image_get_comp - get comp id for a given component image node - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @comp: pointer to the uint8_t, will hold comp numeric id - * - * fit_image_get_comp() finds comp property in a given component image node. - * If the property is found, its (string) value is translated to the numeric - * id which is returned to the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp) -{ - int len; - const void *data; - - /* Get compression name from property data */ - data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len); - if (data == NULL) { - fit_get_debug(fit, noffset, FIT_COMP_PROP, len); - *comp = -1; - return -1; - } - - /* Translate compression name to id */ - *comp = genimg_get_comp_id(data); - return 0; -} - -static int fit_image_get_address(const void *fit, int noffset, char *name, - ulong *load) -{ - int len, cell_len; - const fdt32_t *cell; - uint64_t load64 = 0; - - cell = fdt_getprop(fit, noffset, name, &len); - if (cell == NULL) { - fit_get_debug(fit, noffset, name, len); - return -1; - } - - cell_len = len >> 2; - /* Use load64 to avoid compiling warning for 32-bit target */ - while (cell_len--) { - load64 = (load64 << 32) | uimage_to_cpu(*cell); - cell++; - } - - if (len > sizeof(ulong) && (uint32_t)(load64 >> 32)) { - printf("Unsupported %s address size\n", name); - return -1; - } - - *load = (ulong)load64; - - return 0; -} -/** - * fit_image_get_load() - get load addr property for given component image node - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @load: pointer to the uint32_t, will hold load address - * - * fit_image_get_load() finds load address property in a given component - * image node. If the property is found, its value is returned to the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_get_load(const void *fit, int noffset, ulong *load) -{ - return fit_image_get_address(fit, noffset, FIT_LOAD_PROP, load); -} - -/** - * fit_image_get_entry() - get entry point address property - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @entry: pointer to the uint32_t, will hold entry point address - * - * This gets the entry point address property for a given component image - * node. - * - * fit_image_get_entry() finds entry point address property in a given - * component image node. If the property is found, its value is returned - * to the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_get_entry(const void *fit, int noffset, ulong *entry) -{ - return fit_image_get_address(fit, noffset, FIT_ENTRY_PROP, entry); -} - -/** - * fit_image_get_data - get data property and its size for a given component image node - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @data: double pointer to void, will hold data property's data address - * @size: pointer to size_t, will hold data property's data size - * - * fit_image_get_data() finds data property in a given component image node. - * If the property is found its data start address and size are returned to - * the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_get_data(const void *fit, int noffset, - const void **data, size_t *size) -{ - int len; - - *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len); - if (*data == NULL) { - fit_get_debug(fit, noffset, FIT_DATA_PROP, len); - *size = 0; - return -1; - } - - *size = len; - return 0; -} - -/** - * Get 'data-offset' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_offset: holds the data-offset property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL); - if (!val) - return -ENOENT; - - *data_offset = fdt32_to_cpu(*val); - - return 0; -} - -/** - * Get 'data-position' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_position: holds the data-position property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -int fit_image_get_data_position(const void *fit, int noffset, - int *data_position) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL); - if (!val) - return -ENOENT; - - *data_position = fdt32_to_cpu(*val); - - return 0; -} - -/** - * Get 'data-size' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_size: holds the data-size property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -int fit_image_get_data_size(const void *fit, int noffset, int *data_size) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL); - if (!val) - return -ENOENT; - - *data_size = fdt32_to_cpu(*val); - - return 0; -} - -/** - * Get 'data-size-unciphered' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_size: holds the data-size property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -int fit_image_get_data_size_unciphered(const void *fit, int noffset, - size_t *data_size) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, "data-size-unciphered", NULL); - if (!val) - return -ENOENT; - - *data_size = (size_t)fdt32_to_cpu(*val); - - return 0; -} - -/** - * fit_image_get_data_and_size - get data and its size including - * both embedded and external data - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @data: double pointer to void, will hold data property's data address - * @size: pointer to size_t, will hold data property's data size - * - * fit_image_get_data_and_size() finds data and its size including - * both embedded and external data. If the property is found - * its data start address and size are returned to the caller. - * - * returns: - * 0, on success - * otherwise, on failure - */ -int fit_image_get_data_and_size(const void *fit, int noffset, - const void **data, size_t *size) -{ - bool external_data = false; - int offset; - int len; - int ret; - - if (!fit_image_get_data_position(fit, noffset, &offset)) { - external_data = true; - } else if (!fit_image_get_data_offset(fit, noffset, &offset)) { - external_data = true; - /* - * For FIT with external data, figure out where - * the external images start. This is the base - * for the data-offset properties in each image. - */ - offset += ((fdt_totalsize(fit) + 3) & ~3); - } - - if (external_data) { - debug("External Data\n"); - ret = fit_image_get_data_size(fit, noffset, &len); - if (!ret) { - *data = fit + offset; - *size = len; - } - } else { - ret = fit_image_get_data(fit, noffset, data, size); - } - - return ret; -} - -/** - * fit_image_hash_get_algo - get hash algorithm name - * @fit: pointer to the FIT format image header - * @noffset: hash node offset - * @algo: double pointer to char, will hold pointer to the algorithm name - * - * fit_image_hash_get_algo() finds hash algorithm property in a given hash node. - * If the property is found its data start address is returned to the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_hash_get_algo(const void *fit, int noffset, char **algo) -{ - int len; - - *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len); - if (*algo == NULL) { - fit_get_debug(fit, noffset, FIT_ALGO_PROP, len); - return -1; - } - - return 0; -} - -/** - * fit_image_hash_get_value - get hash value and length - * @fit: pointer to the FIT format image header - * @noffset: hash node offset - * @value: double pointer to uint8_t, will hold address of a hash value data - * @value_len: pointer to an int, will hold hash data length - * - * fit_image_hash_get_value() finds hash value property in a given hash node. - * If the property is found its data start address and size are returned to - * the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value, - int *value_len) -{ - int len; - - *value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len); - if (*value == NULL) { - fit_get_debug(fit, noffset, FIT_VALUE_PROP, len); - *value_len = 0; - return -1; - } - - *value_len = len; - return 0; -} - -/** - * fit_image_hash_get_ignore - get hash ignore flag - * @fit: pointer to the FIT format image header - * @noffset: hash node offset - * @ignore: pointer to an int, will hold hash ignore flag - * - * fit_image_hash_get_ignore() finds hash ignore property in a given hash node. - * If the property is found and non-zero, the hash algorithm is not verified by - * u-boot automatically. - * - * returns: - * 0, on ignore not found - * value, on ignore found - */ -static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore) -{ - int len; - int *value; - - value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len); - if (value == NULL || len != sizeof(int)) - *ignore = 0; - else - *ignore = *value; - - return 0; -} - -/** - * fit_image_cipher_get_algo - get cipher algorithm name - * @fit: pointer to the FIT format image header - * @noffset: cipher node offset - * @algo: double pointer to char, will hold pointer to the algorithm name - * - * fit_image_cipher_get_algo() finds cipher algorithm property in a given - * cipher node. If the property is found its data start address is returned - * to the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -int fit_image_cipher_get_algo(const void *fit, int noffset, char **algo) -{ - int len; - - *algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len); - if (!*algo) { - fit_get_debug(fit, noffset, FIT_ALGO_PROP, len); - return -1; - } - - return 0; -} - -ulong fit_get_end(const void *fit) -{ - return map_to_sysmem((void *)(fit + fdt_totalsize(fit))); -} - -/** - * fit_set_timestamp - set node timestamp property - * @fit: pointer to the FIT format image header - * @noffset: node offset - * @timestamp: timestamp value to be set - * - * fit_set_timestamp() attempts to set timestamp property in the requested - * node and returns operation status to the caller. - * - * returns: - * 0, on success - * -ENOSPC if no space in device tree, -1 for other error - */ -int fit_set_timestamp(void *fit, int noffset, time_t timestamp) -{ - uint32_t t; - int ret; - - t = cpu_to_uimage(timestamp); - ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t, - sizeof(uint32_t)); - if (ret) { - debug("Can't set '%s' property for '%s' node (%s)\n", - FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL), - fdt_strerror(ret)); - return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -1; - } - - return 0; -} - -/** - * calculate_hash - calculate and return hash for provided input data - * @data: pointer to the input data - * @data_len: data length - * @algo: requested hash algorithm - * @value: pointer to the char, will hold hash value data (caller must - * allocate enough free space) - * value_len: length of the calculated hash - * - * calculate_hash() computes input data hash according to the requested - * algorithm. - * Resulting hash value is placed in caller provided 'value' buffer, length - * of the calculated hash is returned via value_len pointer argument. - * - * returns: - * 0, on success - * -1, when algo is unsupported - */ -int calculate_hash(const void *data, int data_len, const char *name, - uint8_t *value, int *value_len) -{ -#if !defined(USE_HOSTCC) && defined(CONFIG_DM_HASH) - int rc; - enum HASH_ALGO hash_algo; - struct udevice *dev; - - rc = uclass_get_device(UCLASS_HASH, 0, &dev); - if (rc) { - debug("failed to get hash device, rc=%d\n", rc); - return -1; - } - - hash_algo = hash_algo_lookup_by_name(algo); - if (hash_algo == HASH_ALGO_INVALID) { - debug("Unsupported hash algorithm\n"); - return -1; - }; - - rc = hash_digest_wd(dev, hash_algo, data, data_len, value, CHUNKSZ); - if (rc) { - debug("failed to get hash value, rc=%d\n", rc); - return -1; - } - - *value_len = hash_algo_digest_size(hash_algo); -#else - struct hash_algo *algo; - int ret; - - ret = hash_lookup_algo(name, &algo); - if (ret < 0) { - debug("Unsupported hash alogrithm\n"); - return -1; - } - - algo->hash_func_ws(data, data_len, value, algo->chunk_size); - *value_len = algo->digest_size; -#endif - - return 0; -} - -static int fit_image_check_hash(const void *fit, int noffset, const void *data, - size_t size, char **err_msgp) -{ - uint8_t value[FIT_MAX_HASH_LEN]; - int value_len; - char *algo; - uint8_t *fit_value; - int fit_value_len; - int ignore; - - *err_msgp = NULL; - - if (fit_image_hash_get_algo(fit, noffset, &algo)) { - *err_msgp = "Can't get hash algo property"; - return -1; - } - printf("%s", algo); - - if (!tools_build()) { - fit_image_hash_get_ignore(fit, noffset, &ignore); - if (ignore) { - printf("-skipped "); - return 0; - } - } - - if (fit_image_hash_get_value(fit, noffset, &fit_value, - &fit_value_len)) { - *err_msgp = "Can't get hash value property"; - return -1; - } - - if (calculate_hash(data, size, algo, value, &value_len)) { - *err_msgp = "Unsupported hash algorithm"; - return -1; - } - - if (value_len != fit_value_len) { - *err_msgp = "Bad hash value len"; - return -1; - } else if (memcmp(value, fit_value, value_len) != 0) { - *err_msgp = "Bad hash value"; - return -1; - } - - return 0; -} - -int fit_image_verify_with_data(const void *fit, int image_noffset, - const void *data, size_t size) -{ - int noffset = 0; - char *err_msg = ""; - int verify_all = 1; - int ret; - - /* Verify all required signatures */ - if (FIT_IMAGE_ENABLE_VERIFY && - fit_image_verify_required_sigs(fit, image_noffset, data, size, - gd_fdt_blob(), &verify_all)) { - err_msg = "Unable to verify required signature"; - goto error; - } - - /* Process all hash subnodes of the component image node */ - fdt_for_each_subnode(noffset, fit, image_noffset) { - const char *name = fit_get_name(fit, noffset, NULL); - - /* - * Check subnode name, must be equal to "hash". - * Multiple hash nodes require unique unit node - * names, e.g. hash-1, hash-2, etc. - */ - if (!strncmp(name, FIT_HASH_NODENAME, - strlen(FIT_HASH_NODENAME))) { - if (fit_image_check_hash(fit, noffset, data, size, - &err_msg)) - goto error; - puts("+ "); - } else if (FIT_IMAGE_ENABLE_VERIFY && verify_all && - !strncmp(name, FIT_SIG_NODENAME, - strlen(FIT_SIG_NODENAME))) { - ret = fit_image_check_sig(fit, noffset, data, - size, -1, &err_msg); - - /* - * Show an indication on failure, but do not return - * an error. Only keys marked 'required' can cause - * an image validation failure. See the call to - * fit_image_verify_required_sigs() above. - */ - if (ret) - puts("- "); - else - puts("+ "); - } - } - - if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { - err_msg = "Corrupted or truncated tree"; - goto error; - } - - return 1; - -error: - printf(" error!\n%s for '%s' hash node in '%s' image node\n", - err_msg, fit_get_name(fit, noffset, NULL), - fit_get_name(fit, image_noffset, NULL)); - return 0; -} - -/** - * fit_image_verify - verify data integrity - * @fit: pointer to the FIT format image header - * @image_noffset: component image node offset - * - * fit_image_verify() goes over component image hash nodes, - * re-calculates each data hash and compares with the value stored in hash - * node. - * - * returns: - * 1, if all hashes are valid - * 0, otherwise (or on error) - */ -int fit_image_verify(const void *fit, int image_noffset) -{ - const char *name = fit_get_name(fit, image_noffset, NULL); - const void *data; - size_t size; - char *err_msg = ""; - - if (IS_ENABLED(CONFIG_FIT_SIGNATURE) && strchr(name, '@')) { - /* - * We don't support this since libfdt considers names with the - * name root but different @ suffix to be equal - */ - err_msg = "Node name contains @"; - goto err; - } - /* Get image data and data length */ - if (fit_image_get_data_and_size(fit, image_noffset, &data, &size)) { - err_msg = "Can't get image data/size"; - goto err; - } - - return fit_image_verify_with_data(fit, image_noffset, data, size); - -err: - printf("error!\n%s in '%s' image node\n", err_msg, - fit_get_name(fit, image_noffset, NULL)); - return 0; -} - -/** - * fit_all_image_verify - verify data integrity for all images - * @fit: pointer to the FIT format image header - * - * fit_all_image_verify() goes over all images in the FIT and - * for every images checks if all it's hashes are valid. - * - * returns: - * 1, if all hashes of all images are valid - * 0, otherwise (or on error) - */ -int fit_all_image_verify(const void *fit) -{ - int images_noffset; - int noffset; - int ndepth; - int count; - - /* Find images parent node offset */ - images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); - if (images_noffset < 0) { - printf("Can't find images parent node '%s' (%s)\n", - FIT_IMAGES_PATH, fdt_strerror(images_noffset)); - return 0; - } - - /* Process all image subnodes, check hashes for each */ - printf("## Checking hash(es) for FIT Image at %08lx ...\n", - (ulong)fit); - for (ndepth = 0, count = 0, - noffset = fdt_next_node(fit, images_noffset, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(fit, noffset, &ndepth)) { - if (ndepth == 1) { - /* - * Direct child node of the images parent node, - * i.e. component image node. - */ - printf(" Hash(es) for Image %u (%s): ", count, - fit_get_name(fit, noffset, NULL)); - count++; - - if (!fit_image_verify(fit, noffset)) - return 0; - printf("\n"); - } - } - return 1; -} - -static int fit_image_uncipher(const void *fit, int image_noffset, - void **data, size_t *size) -{ - int cipher_noffset, ret; - void *dst; - size_t size_dst; - - cipher_noffset = fdt_subnode_offset(fit, image_noffset, - FIT_CIPHER_NODENAME); - if (cipher_noffset < 0) - return 0; - - ret = fit_image_decrypt_data(fit, image_noffset, cipher_noffset, - *data, *size, &dst, &size_dst); - if (ret) - goto out; - - *data = dst; - *size = size_dst; - - out: - return ret; -} - -/** - * fit_image_check_os - check whether image node is of a given os type - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @os: requested image os - * - * fit_image_check_os() reads image os property and compares its numeric - * id with the requested os. Comparison result is returned to the caller. - * - * returns: - * 1 if image is of given os type - * 0 otherwise (or on error) - */ -int fit_image_check_os(const void *fit, int noffset, uint8_t os) -{ - uint8_t image_os; - - if (fit_image_get_os(fit, noffset, &image_os)) - return 0; - return (os == image_os); -} - -/** - * fit_image_check_arch - check whether image node is of a given arch - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @arch: requested imagearch - * - * fit_image_check_arch() reads image arch property and compares its numeric - * id with the requested arch. Comparison result is returned to the caller. - * - * returns: - * 1 if image is of given arch - * 0 otherwise (or on error) - */ -int fit_image_check_arch(const void *fit, int noffset, uint8_t arch) -{ - uint8_t image_arch; - int aarch32_support = 0; - - /* Let's assume that sandbox can load any architecture */ - if (IS_ENABLED(CONFIG_SANDBOX)) - return true; - - if (IS_ENABLED(CONFIG_ARM64_SUPPORT_AARCH32)) - aarch32_support = 1; - - if (fit_image_get_arch(fit, noffset, &image_arch)) - return 0; - return (arch == image_arch) || - (arch == IH_ARCH_I386 && image_arch == IH_ARCH_X86_64) || - (arch == IH_ARCH_ARM64 && image_arch == IH_ARCH_ARM && - aarch32_support); -} - -/** - * fit_image_check_type - check whether image node is of a given type - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @type: requested image type - * - * fit_image_check_type() reads image type property and compares its numeric - * id with the requested type. Comparison result is returned to the caller. - * - * returns: - * 1 if image is of given type - * 0 otherwise (or on error) - */ -int fit_image_check_type(const void *fit, int noffset, uint8_t type) -{ - uint8_t image_type; - - if (fit_image_get_type(fit, noffset, &image_type)) - return 0; - return (type == image_type); -} - -/** - * fit_image_check_comp - check whether image node uses given compression - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @comp: requested image compression type - * - * fit_image_check_comp() reads image compression property and compares its - * numeric id with the requested compression type. Comparison result is - * returned to the caller. - * - * returns: - * 1 if image uses requested compression - * 0 otherwise (or on error) - */ -int fit_image_check_comp(const void *fit, int noffset, uint8_t comp) -{ - uint8_t image_comp; - - if (fit_image_get_comp(fit, noffset, &image_comp)) - return 0; - return (comp == image_comp); -} - -/** - * fdt_check_no_at() - Check for nodes whose names contain '@' - * - * This checks the parent node and all subnodes recursively - * - * @fit: FIT to check - * @parent: Parent node to check - * @return 0 if OK, -EADDRNOTAVAIL is a node has a name containing '@' - */ -static int fdt_check_no_at(const void *fit, int parent) -{ - const char *name; - int node; - int ret; - - name = fdt_get_name(fit, parent, NULL); - if (!name || strchr(name, '@')) - return -EADDRNOTAVAIL; - - fdt_for_each_subnode(node, fit, parent) { - ret = fdt_check_no_at(fit, node); - if (ret) - return ret; - } - - return 0; -} - -int fit_check_format(const void *fit, ulong size) -{ - int ret; - - /* A FIT image must be a valid FDT */ - ret = fdt_check_header(fit); - if (ret) { - log_debug("Wrong FIT format: not a flattened device tree (err=%d)\n", - ret); - return -ENOEXEC; - } - - if (CONFIG_IS_ENABLED(FIT_FULL_CHECK)) { - /* - * If we are not given the size, make do wtih calculating it. - * This is not as secure, so we should consider a flag to - * control this. - */ - if (size == IMAGE_SIZE_INVAL) - size = fdt_totalsize(fit); - ret = fdt_check_full(fit, size); - if (ret) - ret = -EINVAL; - - /* - * U-Boot stopped using unit addressed in 2017. Since libfdt - * can match nodes ignoring any unit address, signature - * verification can see the wrong node if one is inserted with - * the same name as a valid node but with a unit address - * attached. Protect against this by disallowing unit addresses. - */ - if (!ret && CONFIG_IS_ENABLED(FIT_SIGNATURE)) { - ret = fdt_check_no_at(fit, 0); - - if (ret) { - log_debug("FIT check error %d\n", ret); - return ret; - } - } - if (ret) { - log_debug("FIT check error %d\n", ret); - return ret; - } - } - - /* mandatory / node 'description' property */ - if (!fdt_getprop(fit, 0, FIT_DESC_PROP, NULL)) { - log_debug("Wrong FIT format: no description\n"); - return -ENOMSG; - } - - if (IMAGE_ENABLE_TIMESTAMP) { - /* mandatory / node 'timestamp' property */ - if (!fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL)) { - log_debug("Wrong FIT format: no timestamp\n"); - return -EBADMSG; - } - } - - /* mandatory subimages parent '/images' node */ - if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) { - log_debug("Wrong FIT format: no images parent node\n"); - return -ENOENT; - } - - return 0; -} - -/** - * fit_conf_find_compat - * @fit: pointer to the FIT format image header - * @fdt: pointer to the device tree to compare against - * - * fit_conf_find_compat() attempts to find the configuration whose fdt is the - * most compatible with the passed in device tree. - * - * Example: - * - * / o image-tree - * |-o images - * | |-o fdt-1 - * | |-o fdt-2 - * | - * |-o configurations - * |-o config-1 - * | |-fdt = fdt-1 - * | - * |-o config-2 - * |-fdt = fdt-2 - * - * / o U-Boot fdt - * |-compatible = "foo,bar", "bim,bam" - * - * / o kernel fdt1 - * |-compatible = "foo,bar", - * - * / o kernel fdt2 - * |-compatible = "bim,bam", "baz,biz" - * - * Configuration 1 would be picked because the first string in U-Boot's - * compatible list, "foo,bar", matches a compatible string in the root of fdt1. - * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1. - * - * As an optimization, the compatible property from the FDT's root node can be - * copied into the configuration node in the FIT image. This is required to - * match configurations with compressed FDTs. - * - * returns: - * offset to the configuration to use if one was found - * -1 otherwise - */ -int fit_conf_find_compat(const void *fit, const void *fdt) -{ - int ndepth = 0; - int noffset, confs_noffset, images_noffset; - const void *fdt_compat; - int fdt_compat_len; - int best_match_offset = 0; - int best_match_pos = 0; - - confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); - images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); - if (confs_noffset < 0 || images_noffset < 0) { - debug("Can't find configurations or images nodes.\n"); - return -1; - } - - fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len); - if (!fdt_compat) { - debug("Fdt for comparison has no \"compatible\" property.\n"); - return -1; - } - - /* - * Loop over the configurations in the FIT image. - */ - for (noffset = fdt_next_node(fit, confs_noffset, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(fit, noffset, &ndepth)) { - const void *fdt; - const char *kfdt_name; - int kfdt_noffset, compat_noffset; - const char *cur_fdt_compat; - int len; - size_t sz; - int i; - - if (ndepth > 1) - continue; - - /* If there's a compat property in the config node, use that. */ - if (fdt_getprop(fit, noffset, "compatible", NULL)) { - fdt = fit; /* search in FIT image */ - compat_noffset = noffset; /* search under config node */ - } else { /* Otherwise extract it from the kernel FDT. */ - kfdt_name = fdt_getprop(fit, noffset, "fdt", &len); - if (!kfdt_name) { - debug("No fdt property found.\n"); - continue; - } - kfdt_noffset = fdt_subnode_offset(fit, images_noffset, - kfdt_name); - if (kfdt_noffset < 0) { - debug("No image node named \"%s\" found.\n", - kfdt_name); - continue; - } - - if (!fit_image_check_comp(fit, kfdt_noffset, - IH_COMP_NONE)) { - debug("Can't extract compat from \"%s\" " - "(compressed)\n", kfdt_name); - continue; - } - - /* search in this config's kernel FDT */ - if (fit_image_get_data_and_size(fit, kfdt_noffset, - &fdt, &sz)) { - debug("Failed to get fdt \"%s\".\n", kfdt_name); - continue; - } - - compat_noffset = 0; /* search kFDT under root node */ - } - - len = fdt_compat_len; - cur_fdt_compat = fdt_compat; - /* - * Look for a match for each U-Boot compatibility string in - * turn in the compat string property. - */ - for (i = 0; len > 0 && - (!best_match_offset || best_match_pos > i); i++) { - int cur_len = strlen(cur_fdt_compat) + 1; - - if (!fdt_node_check_compatible(fdt, compat_noffset, - cur_fdt_compat)) { - best_match_offset = noffset; - best_match_pos = i; - break; - } - len -= cur_len; - cur_fdt_compat += cur_len; - } - } - if (!best_match_offset) { - debug("No match found.\n"); - return -1; - } - - return best_match_offset; -} - -int fit_conf_get_node(const void *fit, const char *conf_uname) -{ - int noffset, confs_noffset; - int len; - const char *s; - char *conf_uname_copy = NULL; - - confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); - if (confs_noffset < 0) { - debug("Can't find configurations parent node '%s' (%s)\n", - FIT_CONFS_PATH, fdt_strerror(confs_noffset)); - return confs_noffset; - } - - if (conf_uname == NULL) { - /* get configuration unit name from the default property */ - debug("No configuration specified, trying default...\n"); - if (!tools_build() && IS_ENABLED(CONFIG_MULTI_DTB_FIT)) { - noffset = fit_find_config_node(fit); - if (noffset < 0) - return noffset; - conf_uname = fdt_get_name(fit, noffset, NULL); - } else { - conf_uname = (char *)fdt_getprop(fit, confs_noffset, - FIT_DEFAULT_PROP, &len); - if (conf_uname == NULL) { - fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP, - len); - return len; - } - } - debug("Found default configuration: '%s'\n", conf_uname); - } - - s = strchr(conf_uname, '#'); - if (s) { - len = s - conf_uname; - conf_uname_copy = malloc(len + 1); - if (!conf_uname_copy) { - debug("Can't allocate uname copy: '%s'\n", - conf_uname); - return -ENOMEM; - } - memcpy(conf_uname_copy, conf_uname, len); - conf_uname_copy[len] = '\0'; - conf_uname = conf_uname_copy; - } - - noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname); - if (noffset < 0) { - debug("Can't get node offset for configuration unit name: '%s' (%s)\n", - conf_uname, fdt_strerror(noffset)); - } - - if (conf_uname_copy) - free(conf_uname_copy); - - return noffset; -} - -int fit_conf_get_prop_node_count(const void *fit, int noffset, - const char *prop_name) -{ - return fdt_stringlist_count(fit, noffset, prop_name); -} - -int fit_conf_get_prop_node_index(const void *fit, int noffset, - const char *prop_name, int index) -{ - const char *uname; - int len; - - /* get kernel image unit name from configuration kernel property */ - uname = fdt_stringlist_get(fit, noffset, prop_name, index, &len); - if (uname == NULL) - return len; - - return fit_image_get_node(fit, uname); -} - -int fit_conf_get_prop_node(const void *fit, int noffset, - const char *prop_name) -{ - return fit_conf_get_prop_node_index(fit, noffset, prop_name, 0); -} - -static int fit_image_select(const void *fit, int rd_noffset, int verify) -{ - fit_image_print(fit, rd_noffset, " "); - - if (verify) { - puts(" Verifying Hash Integrity ... "); - if (!fit_image_verify(fit, rd_noffset)) { - puts("Bad Data Hash\n"); - return -EACCES; - } - puts("OK\n"); - } - - return 0; -} - -int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, - ulong addr) -{ - int cfg_noffset; - void *fit_hdr; - int noffset; - - debug("* %s: using config '%s' from image at 0x%08lx\n", - prop_name, images->fit_uname_cfg, addr); - - /* Check whether configuration has this property defined */ - fit_hdr = map_sysmem(addr, 0); - cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg); - if (cfg_noffset < 0) { - debug("* %s: no such config\n", prop_name); - return -EINVAL; - } - - noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name); - if (noffset < 0) { - debug("* %s: no '%s' in config\n", prop_name, prop_name); - return -ENOENT; - } - - return noffset; -} - -/** - * fit_get_image_type_property() - get property name for IH_TYPE_... - * - * @return the properly name where we expect to find the image in the - * config node - */ -static const char *fit_get_image_type_property(int type) -{ - /* - * This is sort-of available in the uimage_type[] table in image.c - * but we don't have access to the short name, and "fdt" is different - * anyway. So let's just keep it here. - */ - switch (type) { - case IH_TYPE_FLATDT: - return FIT_FDT_PROP; - case IH_TYPE_KERNEL: - return FIT_KERNEL_PROP; - case IH_TYPE_FIRMWARE: - return FIT_FIRMWARE_PROP; - case IH_TYPE_RAMDISK: - return FIT_RAMDISK_PROP; - case IH_TYPE_X86_SETUP: - return FIT_SETUP_PROP; - case IH_TYPE_LOADABLE: - return FIT_LOADABLE_PROP; - case IH_TYPE_FPGA: - return FIT_FPGA_PROP; - case IH_TYPE_STANDALONE: - return FIT_STANDALONE_PROP; - } - - return "unknown"; -} - -int fit_image_load(bootm_headers_t *images, ulong addr, - const char **fit_unamep, const char **fit_uname_configp, - int arch, int image_type, int bootstage_id, - enum fit_load_op load_op, ulong *datap, ulong *lenp) -{ - int cfg_noffset, noffset; - const char *fit_uname; - const char *fit_uname_config; - const char *fit_base_uname_config; - const void *fit; - void *buf; - void *loadbuf; - size_t size; - int type_ok, os_ok; - ulong load, load_end, data, len; - uint8_t os, comp; - const char *prop_name; - int ret; - - fit = map_sysmem(addr, 0); - fit_uname = fit_unamep ? *fit_unamep : NULL; - fit_uname_config = fit_uname_configp ? *fit_uname_configp : NULL; - fit_base_uname_config = NULL; - prop_name = fit_get_image_type_property(image_type); - printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr); - - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT); - ret = fit_check_format(fit, IMAGE_SIZE_INVAL); - if (ret) { - printf("Bad FIT %s image format! (err=%d)\n", prop_name, ret); - if (CONFIG_IS_ENABLED(FIT_SIGNATURE) && ret == -EADDRNOTAVAIL) - printf("Signature checking prevents use of unit addresses (@) in nodes\n"); - bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT); - return ret; - } - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK); - if (fit_uname) { - /* get FIT component image node offset */ - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME); - noffset = fit_image_get_node(fit, fit_uname); - } else { - /* - * no image node unit name, try to get config - * node first. If config unit node name is NULL - * fit_conf_get_node() will try to find default config node - */ - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME); - if (IS_ENABLED(CONFIG_FIT_BEST_MATCH) && !fit_uname_config) { - cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob()); - } else { - cfg_noffset = fit_conf_get_node(fit, - fit_uname_config); - } - if (cfg_noffset < 0) { - puts("Could not find configuration node\n"); - bootstage_error(bootstage_id + - BOOTSTAGE_SUB_NO_UNIT_NAME); - return -ENOENT; - } - - fit_base_uname_config = fdt_get_name(fit, cfg_noffset, NULL); - printf(" Using '%s' configuration\n", fit_base_uname_config); - /* Remember this config */ - if (image_type == IH_TYPE_KERNEL) - images->fit_uname_cfg = fit_base_uname_config; - - if (FIT_IMAGE_ENABLE_VERIFY && images->verify) { - puts(" Verifying Hash Integrity ... "); - if (fit_config_verify(fit, cfg_noffset)) { - puts("Bad Data Hash\n"); - bootstage_error(bootstage_id + - BOOTSTAGE_SUB_HASH); - return -EACCES; - } - puts("OK\n"); - } - - bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG); - - noffset = fit_conf_get_prop_node(fit, cfg_noffset, - prop_name); - fit_uname = fit_get_name(fit, noffset, NULL); - } - if (noffset < 0) { - printf("Could not find subimage node type '%s'\n", prop_name); - bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE); - return -ENOENT; - } - - printf(" Trying '%s' %s subimage\n", fit_uname, prop_name); - - ret = fit_image_select(fit, noffset, images->verify); - if (ret) { - bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH); - return ret; - } - - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); - if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX)) { - if (!fit_image_check_target_arch(fit, noffset)) { - puts("Unsupported Architecture\n"); - bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH); - return -ENOEXEC; - } - } - -#ifndef USE_HOSTCC - { - uint8_t os_arch; - - fit_image_get_arch(fit, noffset, &os_arch); - images->os.arch = os_arch; - } -#endif - - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); - type_ok = fit_image_check_type(fit, noffset, image_type) || - fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) || - fit_image_check_type(fit, noffset, IH_TYPE_TEE) || - (image_type == IH_TYPE_KERNEL && - fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD)); - - os_ok = image_type == IH_TYPE_FLATDT || - image_type == IH_TYPE_FPGA || - fit_image_check_os(fit, noffset, IH_OS_LINUX) || - fit_image_check_os(fit, noffset, IH_OS_U_BOOT) || - fit_image_check_os(fit, noffset, IH_OS_TEE) || - fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || - fit_image_check_os(fit, noffset, IH_OS_EFI) || - fit_image_check_os(fit, noffset, IH_OS_VXWORKS); - - /* - * If either of the checks fail, we should report an error, but - * if the image type is coming from the "loadables" field, we - * don't care what it is - */ - if ((!type_ok || !os_ok) && image_type != IH_TYPE_LOADABLE) { - fit_image_get_os(fit, noffset, &os); - printf("No %s %s %s Image\n", - genimg_get_os_name(os), - genimg_get_arch_name(arch), - genimg_get_type_name(image_type)); - bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); - return -EIO; - } - - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); - - /* get image data address and length */ - if (fit_image_get_data_and_size(fit, noffset, - (const void **)&buf, &size)) { - printf("Could not find %s subimage data!\n", prop_name); - bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); - return -ENOENT; - } - - /* Decrypt data before uncompress/move */ - if (IS_ENABLED(CONFIG_FIT_CIPHER) && IMAGE_ENABLE_DECRYPT) { - puts(" Decrypting Data ... "); - if (fit_image_uncipher(fit, noffset, &buf, &size)) { - puts("Error\n"); - return -EACCES; - } - puts("OK\n"); - } - - /* perform any post-processing on the image data */ - if (!tools_build() && IS_ENABLED(CONFIG_FIT_IMAGE_POST_PROCESS)) - board_fit_image_post_process(fit, noffset, &buf, &size); - - len = (ulong)size; - - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); - - data = map_to_sysmem(buf); - load = data; - if (load_op == FIT_LOAD_IGNORED) { - /* Don't load */ - } else if (fit_image_get_load(fit, noffset, &load)) { - if (load_op == FIT_LOAD_REQUIRED) { - printf("Can't get %s subimage load address!\n", - prop_name); - bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD); - return -EBADF; - } - } else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) { - ulong image_start, image_end; - - /* - * move image data to the load address, - * make sure we don't overwrite initial image - */ - image_start = addr; - image_end = addr + fit_get_size(fit); - - load_end = load + len; - if (image_type != IH_TYPE_KERNEL && - load < image_end && load_end > image_start) { - printf("Error: %s overwritten\n", prop_name); - return -EXDEV; - } - - printf(" Loading %s from 0x%08lx to 0x%08lx\n", - prop_name, data, load); - } else { - load = data; /* No load address specified */ - } - - comp = IH_COMP_NONE; - loadbuf = buf; - /* Kernel images get decompressed later in bootm_load_os(). */ - if (!fit_image_get_comp(fit, noffset, &comp) && - comp != IH_COMP_NONE && - !(image_type == IH_TYPE_KERNEL || - image_type == IH_TYPE_KERNEL_NOLOAD || - image_type == IH_TYPE_RAMDISK)) { - ulong max_decomp_len = len * 20; - if (load == data) { - loadbuf = malloc(max_decomp_len); - load = map_to_sysmem(loadbuf); - } else { - loadbuf = map_sysmem(load, max_decomp_len); - } - if (image_decomp(comp, load, data, image_type, - loadbuf, buf, len, max_decomp_len, &load_end)) { - printf("Error decompressing %s\n", prop_name); - - return -ENOEXEC; - } - len = load_end - load; - } else if (load != data) { - loadbuf = map_sysmem(load, len); - memcpy(loadbuf, buf, len); - } - - if (image_type == IH_TYPE_RAMDISK && comp != IH_COMP_NONE) - puts("WARNING: 'compression' nodes for ramdisks are deprecated," - " please fix your .its file!\n"); - - /* verify that image data is a proper FDT blob */ - if (image_type == IH_TYPE_FLATDT && fdt_check_header(loadbuf)) { - puts("Subimage data is not a FDT"); - return -ENOEXEC; - } - - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); - - *datap = load; - *lenp = len; - if (fit_unamep) - *fit_unamep = (char *)fit_uname; - if (fit_uname_configp) - *fit_uname_configp = (char *)(fit_uname_config ? : - fit_base_uname_config); - - return noffset; -} - -int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, - ulong *setup_start, ulong *setup_len) -{ - int noffset; - ulong addr; - ulong len; - int ret; - - addr = map_to_sysmem(images->fit_hdr_os); - noffset = fit_get_node_from_config(images, FIT_SETUP_PROP, addr); - if (noffset < 0) - return noffset; - - ret = fit_image_load(images, addr, NULL, NULL, arch, - IH_TYPE_X86_SETUP, BOOTSTAGE_ID_FIT_SETUP_START, - FIT_LOAD_REQUIRED, setup_start, &len); - - return ret; -} - -#ifndef USE_HOSTCC -int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, - const char **fit_unamep, const char **fit_uname_configp, - int arch, ulong *datap, ulong *lenp) -{ - int fdt_noffset, cfg_noffset, count; - const void *fit; - const char *fit_uname = NULL; - const char *fit_uname_config = NULL; - char *fit_uname_config_copy = NULL; - char *next_config = NULL; - ulong load, len; -#ifdef CONFIG_OF_LIBFDT_OVERLAY - ulong image_start, image_end; - ulong ovload, ovlen, ovcopylen; - const char *uconfig; - const char *uname; - void *base, *ov, *ovcopy = NULL; - int i, err, noffset, ov_noffset; -#endif - - fit_uname = fit_unamep ? *fit_unamep : NULL; - - if (fit_uname_configp && *fit_uname_configp) { - fit_uname_config_copy = strdup(*fit_uname_configp); - if (!fit_uname_config_copy) - return -ENOMEM; - - next_config = strchr(fit_uname_config_copy, '#'); - if (next_config) - *next_config++ = '\0'; - if (next_config - 1 > fit_uname_config_copy) - fit_uname_config = fit_uname_config_copy; - } - - fdt_noffset = fit_image_load(images, - addr, &fit_uname, &fit_uname_config, - arch, IH_TYPE_FLATDT, - BOOTSTAGE_ID_FIT_FDT_START, - FIT_LOAD_OPTIONAL, &load, &len); - - if (fdt_noffset < 0) - goto out; - - debug("fit_uname=%s, fit_uname_config=%s\n", - fit_uname ? fit_uname : "<NULL>", - fit_uname_config ? fit_uname_config : "<NULL>"); - - fit = map_sysmem(addr, 0); - - cfg_noffset = fit_conf_get_node(fit, fit_uname_config); - - /* single blob, or error just return as well */ - count = fit_conf_get_prop_node_count(fit, cfg_noffset, FIT_FDT_PROP); - if (count <= 1 && !next_config) - goto out; - - /* we need to apply overlays */ - -#ifdef CONFIG_OF_LIBFDT_OVERLAY - image_start = addr; - image_end = addr + fit_get_size(fit); - /* verify that relocation took place by load address not being in fit */ - if (load >= image_start && load < image_end) { - /* check is simplified; fit load checks for overlaps */ - printf("Overlayed FDT requires relocation\n"); - fdt_noffset = -EBADF; - goto out; - } - - base = map_sysmem(load, len); - - /* apply extra configs in FIT first, followed by args */ - for (i = 1; ; i++) { - if (i < count) { - noffset = fit_conf_get_prop_node_index(fit, cfg_noffset, - FIT_FDT_PROP, i); - uname = fit_get_name(fit, noffset, NULL); - uconfig = NULL; - } else { - if (!next_config) - break; - uconfig = next_config; - next_config = strchr(next_config, '#'); - if (next_config) - *next_config++ = '\0'; - uname = NULL; - - /* - * fit_image_load() would load the first FDT from the - * extra config only when uconfig is specified. - * Check if the extra config contains multiple FDTs and - * if so, load them. - */ - cfg_noffset = fit_conf_get_node(fit, uconfig); - - i = 0; - count = fit_conf_get_prop_node_count(fit, cfg_noffset, - FIT_FDT_PROP); - } - - debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig); - - ov_noffset = fit_image_load(images, - addr, &uname, &uconfig, - arch, IH_TYPE_FLATDT, - BOOTSTAGE_ID_FIT_FDT_START, - FIT_LOAD_IGNORED, &ovload, &ovlen); - if (ov_noffset < 0) { - printf("load of %s failed\n", uname); - continue; - } - debug("%s loaded at 0x%08lx len=0x%08lx\n", - uname, ovload, ovlen); - ov = map_sysmem(ovload, ovlen); - - ovcopylen = ALIGN(fdt_totalsize(ov), SZ_4K); - ovcopy = malloc(ovcopylen); - if (!ovcopy) { - printf("failed to duplicate DTO before application\n"); - fdt_noffset = -ENOMEM; - goto out; - } - - err = fdt_open_into(ov, ovcopy, ovcopylen); - if (err < 0) { - printf("failed on fdt_open_into for DTO\n"); - fdt_noffset = err; - goto out; - } - - base = map_sysmem(load, len + ovlen); - err = fdt_open_into(base, base, len + ovlen); - if (err < 0) { - printf("failed on fdt_open_into\n"); - fdt_noffset = err; - goto out; - } - - /* the verbose method prints out messages on error */ - err = fdt_overlay_apply_verbose(base, ovcopy); - if (err < 0) { - fdt_noffset = err; - goto out; - } - fdt_pack(base); - len = fdt_totalsize(base); - - free(ovcopy); - ovcopy = NULL; - } -#else - printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n"); - fdt_noffset = -EBADF; -#endif - -out: - if (datap) - *datap = load; - if (lenp) - *lenp = len; - if (fit_unamep) - *fit_unamep = fit_uname; - if (fit_uname_configp) - *fit_uname_configp = fit_uname_config; - -#ifdef CONFIG_OF_LIBFDT_OVERLAY - if (ovcopy) - free(ovcopy); -#endif - if (fit_uname_config_copy) - free(fit_uname_config_copy); - return fdt_noffset; -} -#endif diff --git a/common/image-host.c b/common/image-host.c deleted file mode 100644 index 20a9521948b..00000000000 --- a/common/image-host.c +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Image code used by host tools (and not boards) - * - * (C) Copyright 2008 Semihalf - * - * (C) Copyright 2000-2006 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#include <time.h> - -void memmove_wd(void *to, void *from, size_t len, ulong chunksz) -{ - memmove(to, from, len); -} - -void genimg_print_size(uint32_t size) -{ - printf("%d Bytes = %.2f KiB = %.2f MiB\n", size, (double)size / 1.024e3, - (double)size / 1.048576e6); -} - -void genimg_print_time(time_t timestamp) -{ - printf("%s", ctime(×tamp)); -} diff --git a/common/image-sig.c b/common/image-sig.c deleted file mode 100644 index 1aa0b586450..00000000000 --- a/common/image-sig.c +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2013, Google Inc. - */ - -#include <common.h> -#include <log.h> -#include <malloc.h> -#include <asm/global_data.h> -DECLARE_GLOBAL_DATA_PTR; -#include <image.h> -#include <relocate.h> -#include <u-boot/ecdsa.h> -#include <u-boot/rsa.h> -#include <u-boot/hash-checksum.h> - -#define IMAGE_MAX_HASHED_NODES 100 - -struct checksum_algo checksum_algos[] = { - { - .name = "sha1", - .checksum_len = SHA1_SUM_LEN, - .der_len = SHA1_DER_LEN, - .der_prefix = sha1_der_prefix, - .calculate = hash_calculate, - }, - { - .name = "sha256", - .checksum_len = SHA256_SUM_LEN, - .der_len = SHA256_DER_LEN, - .der_prefix = sha256_der_prefix, - .calculate = hash_calculate, - }, -#ifdef CONFIG_SHA384 - { - .name = "sha384", - .checksum_len = SHA384_SUM_LEN, - .der_len = SHA384_DER_LEN, - .der_prefix = sha384_der_prefix, - .calculate = hash_calculate, - }, -#endif -#ifdef CONFIG_SHA512 - { - .name = "sha512", - .checksum_len = SHA512_SUM_LEN, - .der_len = SHA512_DER_LEN, - .der_prefix = sha512_der_prefix, - .calculate = hash_calculate, - }, -#endif - -}; - -struct checksum_algo *image_get_checksum_algo(const char *full_name) -{ - int i; - const char *name; - - if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) { - static bool done; - - if (!done) { - done = true; - for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) { - struct checksum_algo *algo = &checksum_algos[i]; - - MANUAL_RELOC(algo->name); - MANUAL_RELOC(algo->calculate); - } - } - } - - for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) { - name = checksum_algos[i].name; - /* Make sure names match and next char is a comma */ - if (!strncmp(name, full_name, strlen(name)) && - full_name[strlen(name)] == ',') - return &checksum_algos[i]; - } - - return NULL; -} - -struct crypto_algo *image_get_crypto_algo(const char *full_name) -{ - struct crypto_algo *crypto, *end; - const char *name; - - if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) { - static bool done; - - if (!done) { - done = true; - crypto = ll_entry_start(struct crypto_algo, cryptos); - end = ll_entry_end(struct crypto_algo, cryptos); - for (; crypto < end; crypto++) { - MANUAL_RELOC(crypto->name); - MANUAL_RELOC(crypto->verify); - } - } - } - - /* Move name to after the comma */ - name = strchr(full_name, ','); - if (!name) - return NULL; - name += 1; - - crypto = ll_entry_start(struct crypto_algo, cryptos); - end = ll_entry_end(struct crypto_algo, cryptos); - for (; crypto < end; crypto++) { - if (!strcmp(crypto->name, name)) - return crypto; - } - - /* Not found */ - return NULL; -} - -struct padding_algo *image_get_padding_algo(const char *name) -{ - struct padding_algo *padding, *end; - - if (!name) - return NULL; - - padding = ll_entry_start(struct padding_algo, paddings); - end = ll_entry_end(struct padding_algo, paddings); - for (; padding < end; padding++) { - if (!strcmp(padding->name, name)) - return padding; - } - - return NULL; -} diff --git a/common/image.c b/common/image.c deleted file mode 100644 index 3fa60b58279..00000000000 --- a/common/image.c +++ /dev/null @@ -1,738 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2008 Semihalf - * - * (C) Copyright 2000-2006 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#ifndef USE_HOSTCC -#include <common.h> -#include <env.h> -#include <lmb.h> -#include <log.h> -#include <malloc.h> -#include <u-boot/crc.h> - -#ifdef CONFIG_SHOW_BOOT_PROGRESS -#include <status_led.h> -#endif - -#if CONFIG_IS_ENABLED(FIT) || CONFIG_IS_ENABLED(OF_LIBFDT) -#include <linux/libfdt.h> -#include <fdt_support.h> -#endif - -#include <asm/global_data.h> -#include <u-boot/md5.h> -#include <u-boot/sha1.h> -#include <linux/errno.h> -#include <asm/io.h> - -#ifdef CONFIG_CMD_BDI -extern int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]); -#endif - -DECLARE_GLOBAL_DATA_PTR; - -/* Set this if we have less than 4 MB of malloc() space */ -#if CONFIG_SYS_MALLOC_LEN < (4096 * 1024) -#define CONSERVE_MEMORY true -#else -#define CONSERVE_MEMORY false -#endif - -#else /* USE_HOSTCC */ -#include "mkimage.h" -#include <u-boot/md5.h> -#include <time.h> - -#ifndef __maybe_unused -# define __maybe_unused /* unimplemented */ -#endif - -#define CONSERVE_MEMORY false - -#endif /* !USE_HOSTCC*/ - -#include <abuf.h> -#include <bzlib.h> -#include <display_options.h> -#include <gzip.h> -#include <image.h> -#include <imximage.h> -#include <relocate.h> -#include <linux/lzo.h> -#include <linux/zstd.h> -#include <linux/kconfig.h> -#include <lzma/LzmaTypes.h> -#include <lzma/LzmaDec.h> -#include <lzma/LzmaTools.h> -#include <u-boot/crc.h> -#include <u-boot/lz4.h> - -static const table_entry_t uimage_arch[] = { - { IH_ARCH_INVALID, "invalid", "Invalid ARCH", }, - { IH_ARCH_ALPHA, "alpha", "Alpha", }, - { IH_ARCH_ARM, "arm", "ARM", }, - { IH_ARCH_I386, "x86", "Intel x86", }, - { IH_ARCH_IA64, "ia64", "IA64", }, - { IH_ARCH_M68K, "m68k", "M68K", }, - { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", }, - { IH_ARCH_MIPS, "mips", "MIPS", }, - { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", }, - { IH_ARCH_NIOS2, "nios2", "NIOS II", }, - { IH_ARCH_PPC, "powerpc", "PowerPC", }, - { IH_ARCH_PPC, "ppc", "PowerPC", }, - { IH_ARCH_S390, "s390", "IBM S390", }, - { IH_ARCH_SH, "sh", "SuperH", }, - { IH_ARCH_SPARC, "sparc", "SPARC", }, - { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", }, - { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", }, - { IH_ARCH_AVR32, "avr32", "AVR32", }, - { IH_ARCH_NDS32, "nds32", "NDS32", }, - { IH_ARCH_OPENRISC, "or1k", "OpenRISC 1000",}, - { IH_ARCH_SANDBOX, "sandbox", "Sandbox", }, - { IH_ARCH_ARM64, "arm64", "AArch64", }, - { IH_ARCH_ARC, "arc", "ARC", }, - { IH_ARCH_X86_64, "x86_64", "AMD x86_64", }, - { IH_ARCH_XTENSA, "xtensa", "Xtensa", }, - { IH_ARCH_RISCV, "riscv", "RISC-V", }, - { -1, "", "", }, -}; - -static const table_entry_t uimage_os[] = { - { IH_OS_INVALID, "invalid", "Invalid OS", }, - { IH_OS_ARM_TRUSTED_FIRMWARE, "arm-trusted-firmware", "ARM Trusted Firmware" }, - { IH_OS_LINUX, "linux", "Linux", }, -#if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC) - { IH_OS_LYNXOS, "lynxos", "LynxOS", }, -#endif - { IH_OS_NETBSD, "netbsd", "NetBSD", }, - { IH_OS_OSE, "ose", "Enea OSE", }, - { IH_OS_PLAN9, "plan9", "Plan 9", }, - { IH_OS_RTEMS, "rtems", "RTEMS", }, - { IH_OS_TEE, "tee", "Trusted Execution Environment" }, - { IH_OS_U_BOOT, "u-boot", "U-Boot", }, - { IH_OS_VXWORKS, "vxworks", "VxWorks", }, -#if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC) - { IH_OS_QNX, "qnx", "QNX", }, -#endif -#if defined(CONFIG_INTEGRITY) || defined(USE_HOSTCC) - { IH_OS_INTEGRITY,"integrity", "INTEGRITY", }, -#endif -#ifdef USE_HOSTCC - { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, - { IH_OS_DELL, "dell", "Dell", }, - { IH_OS_ESIX, "esix", "Esix", }, - { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, - { IH_OS_IRIX, "irix", "Irix", }, - { IH_OS_NCR, "ncr", "NCR", }, - { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, - { IH_OS_PSOS, "psos", "pSOS", }, - { IH_OS_SCO, "sco", "SCO", }, - { IH_OS_SOLARIS, "solaris", "Solaris", }, - { IH_OS_SVR4, "svr4", "SVR4", }, -#endif -#if defined(CONFIG_BOOTM_OPENRTOS) || defined(USE_HOSTCC) - { IH_OS_OPENRTOS, "openrtos", "OpenRTOS", }, -#endif - { IH_OS_OPENSBI, "opensbi", "RISC-V OpenSBI", }, - { IH_OS_EFI, "efi", "EFI Firmware" }, - - { -1, "", "", }, -}; - -static const table_entry_t uimage_type[] = { - { IH_TYPE_AISIMAGE, "aisimage", "Davinci AIS image",}, - { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", }, - { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, - { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, - { IH_TYPE_GPIMAGE, "gpimage", "TI Keystone SPL Image",}, - { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, - { IH_TYPE_KERNEL_NOLOAD, "kernel_noload", "Kernel Image (no loading done)", }, - { IH_TYPE_KWBIMAGE, "kwbimage", "Kirkwood Boot Image",}, - { IH_TYPE_IMXIMAGE, "imximage", "Freescale i.MX Boot Image",}, - { IH_TYPE_IMX8IMAGE, "imx8image", "NXP i.MX8 Boot Image",}, - { IH_TYPE_IMX8MIMAGE, "imx8mimage", "NXP i.MX8M Boot Image",}, - { IH_TYPE_INVALID, "invalid", "Invalid Image", }, - { IH_TYPE_MULTI, "multi", "Multi-File Image", }, - { IH_TYPE_OMAPIMAGE, "omapimage", "TI OMAP SPL With GP CH",}, - { IH_TYPE_PBLIMAGE, "pblimage", "Freescale PBL Boot Image",}, - { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, - { IH_TYPE_SCRIPT, "script", "Script", }, - { IH_TYPE_SOCFPGAIMAGE, "socfpgaimage", "Altera SoCFPGA CV/AV preloader",}, - { IH_TYPE_SOCFPGAIMAGE_V1, "socfpgaimage_v1", "Altera SoCFPGA A10 preloader",}, - { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, - { IH_TYPE_UBLIMAGE, "ublimage", "Davinci UBL image",}, - { IH_TYPE_MXSIMAGE, "mxsimage", "Freescale MXS Boot Image",}, - { IH_TYPE_ATMELIMAGE, "atmelimage", "ATMEL ROM-Boot Image",}, - { IH_TYPE_X86_SETUP, "x86_setup", "x86 setup.bin", }, - { IH_TYPE_LPC32XXIMAGE, "lpc32xximage", "LPC32XX Boot Image", }, - { IH_TYPE_RKIMAGE, "rkimage", "Rockchip Boot Image" }, - { IH_TYPE_RKSD, "rksd", "Rockchip SD Boot Image" }, - { IH_TYPE_RKSPI, "rkspi", "Rockchip SPI Boot Image" }, - { IH_TYPE_VYBRIDIMAGE, "vybridimage", "Vybrid Boot Image", }, - { IH_TYPE_ZYNQIMAGE, "zynqimage", "Xilinx Zynq Boot Image" }, - { IH_TYPE_ZYNQMPIMAGE, "zynqmpimage", "Xilinx ZynqMP Boot Image" }, - { IH_TYPE_ZYNQMPBIF, "zynqmpbif", "Xilinx ZynqMP Boot Image (bif)" }, - { IH_TYPE_FPGA, "fpga", "FPGA Image" }, - { IH_TYPE_TEE, "tee", "Trusted Execution Environment Image",}, - { IH_TYPE_FIRMWARE_IVT, "firmware_ivt", "Firmware with HABv4 IVT" }, - { IH_TYPE_PMMC, "pmmc", "TI Power Management Micro-Controller Firmware",}, - { IH_TYPE_STM32IMAGE, "stm32image", "STMicroelectronics STM32 Image" }, - { IH_TYPE_MTKIMAGE, "mtk_image", "MediaTek BootROM loadable Image" }, - { IH_TYPE_COPRO, "copro", "Coprocessor Image"}, - { IH_TYPE_SUNXI_EGON, "sunxi_egon", "Allwinner eGON Boot Image" }, - { -1, "", "", }, -}; - -static const table_entry_t uimage_comp[] = { - { IH_COMP_NONE, "none", "uncompressed", }, - { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, - { IH_COMP_GZIP, "gzip", "gzip compressed", }, - { IH_COMP_LZMA, "lzma", "lzma compressed", }, - { IH_COMP_LZO, "lzo", "lzo compressed", }, - { IH_COMP_LZ4, "lz4", "lz4 compressed", }, - { IH_COMP_ZSTD, "zstd", "zstd compressed", }, - { -1, "", "", }, -}; - -struct table_info { - const char *desc; - int count; - const table_entry_t *table; -}; - -static const struct comp_magic_map image_comp[] = { - { IH_COMP_BZIP2, "bzip2", {0x42, 0x5a},}, - { IH_COMP_GZIP, "gzip", {0x1f, 0x8b},}, - { IH_COMP_LZMA, "lzma", {0x5d, 0x00},}, - { IH_COMP_LZO, "lzo", {0x89, 0x4c},}, - { IH_COMP_LZ4, "lz4", {0x04, 0x22},}, - { IH_COMP_ZSTD, "zstd", {0x28, 0xb5},}, - { IH_COMP_NONE, "none", {}, }, -}; - -static const struct table_info table_info[IH_COUNT] = { - { "architecture", IH_ARCH_COUNT, uimage_arch }, - { "compression", IH_COMP_COUNT, uimage_comp }, - { "operating system", IH_OS_COUNT, uimage_os }, - { "image type", IH_TYPE_COUNT, uimage_type }, -}; - -/*****************************************************************************/ -/* Legacy format routines */ -/*****************************************************************************/ -int image_check_hcrc(const image_header_t *hdr) -{ - ulong hcrc; - ulong len = image_get_header_size(); - image_header_t header; - - /* Copy header so we can blank CRC field for re-calculation */ - memmove(&header, (char *)hdr, image_get_header_size()); - image_set_hcrc(&header, 0); - - hcrc = crc32(0, (unsigned char *)&header, len); - - return (hcrc == image_get_hcrc(hdr)); -} - -int image_check_dcrc(const image_header_t *hdr) -{ - ulong data = image_get_data(hdr); - ulong len = image_get_data_size(hdr); - ulong dcrc = crc32_wd(0, (unsigned char *)data, len, CHUNKSZ_CRC32); - - return (dcrc == image_get_dcrc(hdr)); -} - -/** - * image_multi_count - get component (sub-image) count - * @hdr: pointer to the header of the multi component image - * - * image_multi_count() returns number of components in a multi - * component image. - * - * Note: no checking of the image type is done, caller must pass - * a valid multi component image. - * - * returns: - * number of components - */ -ulong image_multi_count(const image_header_t *hdr) -{ - ulong i, count = 0; - uint32_t *size; - - /* get start of the image payload, which in case of multi - * component images that points to a table of component sizes */ - size = (uint32_t *)image_get_data(hdr); - - /* count non empty slots */ - for (i = 0; size[i]; ++i) - count++; - - return count; -} - -/** - * image_multi_getimg - get component data address and size - * @hdr: pointer to the header of the multi component image - * @idx: index of the requested component - * @data: pointer to a ulong variable, will hold component data address - * @len: pointer to a ulong variable, will hold component size - * - * image_multi_getimg() returns size and data address for the requested - * component in a multi component image. - * - * Note: no checking of the image type is done, caller must pass - * a valid multi component image. - * - * returns: - * data address and size of the component, if idx is valid - * 0 in data and len, if idx is out of range - */ -void image_multi_getimg(const image_header_t *hdr, ulong idx, - ulong *data, ulong *len) -{ - int i; - uint32_t *size; - ulong offset, count, img_data; - - /* get number of component */ - count = image_multi_count(hdr); - - /* get start of the image payload, which in case of multi - * component images that points to a table of component sizes */ - size = (uint32_t *)image_get_data(hdr); - - /* get address of the proper component data start, which means - * skipping sizes table (add 1 for last, null entry) */ - img_data = image_get_data(hdr) + (count + 1) * sizeof(uint32_t); - - if (idx < count) { - *len = uimage_to_cpu(size[idx]); - offset = 0; - - /* go over all indices preceding requested component idx */ - for (i = 0; i < idx; i++) { - /* add up i-th component size, rounding up to 4 bytes */ - offset += (uimage_to_cpu(size[i]) + 3) & ~3 ; - } - - /* calculate idx-th component data address */ - *data = img_data + offset; - } else { - *len = 0; - *data = 0; - } -} - -static void image_print_type(const image_header_t *hdr) -{ - const char __maybe_unused *os, *arch, *type, *comp; - - os = genimg_get_os_name(image_get_os(hdr)); - arch = genimg_get_arch_name(image_get_arch(hdr)); - type = genimg_get_type_name(image_get_type(hdr)); - comp = genimg_get_comp_name(image_get_comp(hdr)); - - printf("%s %s %s (%s)\n", arch, os, type, comp); -} - -/** - * image_print_contents - prints out the contents of the legacy format image - * @ptr: pointer to the legacy format image header - * @p: pointer to prefix string - * - * image_print_contents() formats a multi line legacy image contents description. - * The routine prints out all header fields followed by the size/offset data - * for MULTI/SCRIPT images. - * - * returns: - * no returned results - */ -void image_print_contents(const void *ptr) -{ - const image_header_t *hdr = (const image_header_t *)ptr; - const char __maybe_unused *p; - - p = IMAGE_INDENT_STRING; - printf("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name(hdr)); - if (IMAGE_ENABLE_TIMESTAMP) { - printf("%sCreated: ", p); - genimg_print_time((time_t)image_get_time(hdr)); - } - printf("%sImage Type: ", p); - image_print_type(hdr); - printf("%sData Size: ", p); - genimg_print_size(image_get_data_size(hdr)); - printf("%sLoad Address: %08x\n", p, image_get_load(hdr)); - printf("%sEntry Point: %08x\n", p, image_get_ep(hdr)); - - if (image_check_type(hdr, IH_TYPE_MULTI) || - image_check_type(hdr, IH_TYPE_SCRIPT)) { - int i; - ulong data, len; - ulong count = image_multi_count(hdr); - - printf("%sContents:\n", p); - for (i = 0; i < count; i++) { - image_multi_getimg(hdr, i, &data, &len); - - printf("%s Image %d: ", p, i); - genimg_print_size(len); - - if (image_check_type(hdr, IH_TYPE_SCRIPT) && i > 0) { - /* - * the user may need to know offsets - * if planning to do something with - * multiple files - */ - printf("%s Offset = 0x%08lx\n", p, data); - } - } - } else if (image_check_type(hdr, IH_TYPE_FIRMWARE_IVT)) { - printf("HAB Blocks: 0x%08x 0x0000 0x%08x\n", - image_get_load(hdr) - image_get_header_size(), - (int)(image_get_size(hdr) + image_get_header_size() - + sizeof(flash_header_v2_t) - 0x2060)); - } -} - -/** - * print_decomp_msg() - Print a suitable decompression/loading message - * - * @type: OS type (IH_OS_...) - * @comp_type: Compression type being used (IH_COMP_...) - * @is_xip: true if the load address matches the image start - */ -static void print_decomp_msg(int comp_type, int type, bool is_xip) -{ - const char *name = genimg_get_type_name(type); - - if (comp_type == IH_COMP_NONE) - printf(" %s %s\n", is_xip ? "XIP" : "Loading", name); - else - printf(" Uncompressing %s\n", name); -} - -int image_decomp_type(const unsigned char *buf, ulong len) -{ - const struct comp_magic_map *cmagic = image_comp; - - if (len < 2) - return -EINVAL; - - for (; cmagic->comp_id > 0; cmagic++) { - if (!memcmp(buf, cmagic->magic, 2)) - break; - } - - return cmagic->comp_id; -} - -int image_decomp(int comp, ulong load, ulong image_start, int type, - void *load_buf, void *image_buf, ulong image_len, - uint unc_len, ulong *load_end) -{ - int ret = -ENOSYS; - - *load_end = load; - print_decomp_msg(comp, type, load == image_start); - - /* - * Load the image to the right place, decompressing if needed. After - * this, image_len will be set to the number of uncompressed bytes - * loaded, ret will be non-zero on error. - */ - switch (comp) { - case IH_COMP_NONE: - ret = 0; - if (load == image_start) - break; - if (image_len <= unc_len) - memmove_wd(load_buf, image_buf, image_len, CHUNKSZ); - else - ret = -ENOSPC; - break; - case IH_COMP_GZIP: - if (!tools_build() && CONFIG_IS_ENABLED(GZIP)) - ret = gunzip(load_buf, unc_len, image_buf, &image_len); - break; - case IH_COMP_BZIP2: - if (!tools_build() && CONFIG_IS_ENABLED(BZIP2)) { - uint size = unc_len; - - /* - * If we've got less than 4 MB of malloc() space, - * use slower decompression algorithm which requires - * at most 2300 KB of memory. - */ - ret = BZ2_bzBuffToBuffDecompress(load_buf, &size, - image_buf, image_len, CONSERVE_MEMORY, 0); - image_len = size; - } - break; - case IH_COMP_LZMA: - if (!tools_build() && CONFIG_IS_ENABLED(LZMA)) { - SizeT lzma_len = unc_len; - - ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, - image_buf, image_len); - image_len = lzma_len; - } - break; - case IH_COMP_LZO: - if (!tools_build() && CONFIG_IS_ENABLED(LZO)) { - size_t size = unc_len; - - ret = lzop_decompress(image_buf, image_len, load_buf, &size); - image_len = size; - } - break; - case IH_COMP_LZ4: - if (!tools_build() && CONFIG_IS_ENABLED(LZ4)) { - size_t size = unc_len; - - ret = ulz4fn(image_buf, image_len, load_buf, &size); - image_len = size; - } - break; - case IH_COMP_ZSTD: - if (!tools_build() && CONFIG_IS_ENABLED(ZSTD)) { - struct abuf in, out; - - abuf_init_set(&in, image_buf, image_len); - abuf_init_set(&in, load_buf, unc_len); - ret = zstd_decompress(&in, &out); - if (ret >= 0) { - image_len = ret; - ret = 0; - } - } - break; - } - if (ret == -ENOSYS) { - printf("Unimplemented compression type %d\n", comp); - return ret; - } - if (ret) - return ret; - - *load_end = load + image_len; - - return 0; -} - -const table_entry_t *get_table_entry(const table_entry_t *table, int id) -{ - for (; table->id >= 0; ++table) { - if (table->id == id) - return table; - } - return NULL; -} - -static const char *unknown_msg(enum ih_category category) -{ - static const char unknown_str[] = "Unknown "; - static char msg[30]; - - strcpy(msg, unknown_str); - strncat(msg, table_info[category].desc, - sizeof(msg) - sizeof(unknown_str)); - - return msg; -} - -/** - * genimg_get_cat_name - translate entry id to long name - * @category: category to look up (enum ih_category) - * @id: entry id to be translated - * - * This will scan the translation table trying to find the entry that matches - * the given id. - * - * @return long entry name if translation succeeds; error string on failure - */ -const char *genimg_get_cat_name(enum ih_category category, uint id) -{ - const table_entry_t *entry; - - entry = get_table_entry(table_info[category].table, id); - if (!entry) - return unknown_msg(category); - return manual_reloc(entry->lname); -} - -/** - * genimg_get_cat_short_name - translate entry id to short name - * @category: category to look up (enum ih_category) - * @id: entry id to be translated - * - * This will scan the translation table trying to find the entry that matches - * the given id. - * - * @return short entry name if translation succeeds; error string on failure - */ -const char *genimg_get_cat_short_name(enum ih_category category, uint id) -{ - const table_entry_t *entry; - - entry = get_table_entry(table_info[category].table, id); - if (!entry) - return unknown_msg(category); - return manual_reloc(entry->sname); -} - -int genimg_get_cat_count(enum ih_category category) -{ - return table_info[category].count; -} - -const char *genimg_get_cat_desc(enum ih_category category) -{ - return table_info[category].desc; -} - -/** - * genimg_cat_has_id - check whether category has entry id - * @category: category to look up (enum ih_category) - * @id: entry id to be checked - * - * This will scan the translation table trying to find the entry that matches - * the given id. - * - * @return true if category has entry id; false if not - */ -bool genimg_cat_has_id(enum ih_category category, uint id) -{ - if (get_table_entry(table_info[category].table, id)) - return true; - - return false; -} - -/** - * get_table_entry_name - translate entry id to long name - * @table: pointer to a translation table for entries of a specific type - * @msg: message to be returned when translation fails - * @id: entry id to be translated - * - * get_table_entry_name() will go over translation table trying to find - * entry that matches given id. If matching entry is found, its long - * name is returned to the caller. - * - * returns: - * long entry name if translation succeeds - * msg otherwise - */ -char *get_table_entry_name(const table_entry_t *table, char *msg, int id) -{ - table = get_table_entry(table, id); - if (!table) - return msg; - return manual_reloc(table->lname); -} - -const char *genimg_get_os_name(uint8_t os) -{ - return (get_table_entry_name(uimage_os, "Unknown OS", os)); -} - -const char *genimg_get_arch_name(uint8_t arch) -{ - return (get_table_entry_name(uimage_arch, "Unknown Architecture", - arch)); -} - -const char *genimg_get_type_name(uint8_t type) -{ - return (get_table_entry_name(uimage_type, "Unknown Image", type)); -} - -const char *genimg_get_comp_name(uint8_t comp) -{ - return (get_table_entry_name(uimage_comp, "Unknown Compression", - comp)); -} - -static const char *genimg_get_short_name(const table_entry_t *table, int val) -{ - table = get_table_entry(table, val); - if (!table) - return "unknown"; - return manual_reloc(table->sname); -} - -const char *genimg_get_type_short_name(uint8_t type) -{ - return genimg_get_short_name(uimage_type, type); -} - -const char *genimg_get_comp_short_name(uint8_t comp) -{ - return genimg_get_short_name(uimage_comp, comp); -} - -const char *genimg_get_os_short_name(uint8_t os) -{ - return genimg_get_short_name(uimage_os, os); -} - -const char *genimg_get_arch_short_name(uint8_t arch) -{ - return genimg_get_short_name(uimage_arch, arch); -} - -/** - * get_table_entry_id - translate short entry name to id - * @table: pointer to a translation table for entries of a specific type - * @table_name: to be used in case of error - * @name: entry short name to be translated - * - * get_table_entry_id() will go over translation table trying to find - * entry that matches given short name. If matching entry is found, - * its id returned to the caller. - * - * returns: - * entry id if translation succeeds - * -1 otherwise - */ -int get_table_entry_id(const table_entry_t *table, - const char *table_name, const char *name) -{ - const table_entry_t *t; - - for (t = table; t->id >= 0; ++t) { - if (t->sname && !strcasecmp(manual_reloc(t->sname), name)) - return t->id; - } - debug("Invalid %s Type: %s\n", table_name, name); - - return -1; -} - -int genimg_get_os_id(const char *name) -{ - return (get_table_entry_id(uimage_os, "OS", name)); -} - -int genimg_get_arch_id(const char *name) -{ - return (get_table_entry_id(uimage_arch, "CPU", name)); -} - -int genimg_get_type_id(const char *name) -{ - return (get_table_entry_id(uimage_type, "Image", name)); -} - -int genimg_get_comp_id(const char *name) -{ - return (get_table_entry_id(uimage_comp, "Compression", name)); -} |