diff options
Diffstat (limited to 'roms/u-boot/common/spl')
25 files changed, 5998 insertions, 0 deletions
diff --git a/roms/u-boot/common/spl/Kconfig b/roms/u-boot/common/spl/Kconfig new file mode 100644 index 000000000..fa80524cf --- /dev/null +++ b/roms/u-boot/common/spl/Kconfig @@ -0,0 +1,1639 @@ +menu "SPL / TPL" + +config SUPPORT_SPL + bool + +config SUPPORT_TPL + bool + +config SPL_DFU_NO_RESET + bool + +config SPL + bool + depends on SUPPORT_SPL + prompt "Enable SPL" + help + If you want to build SPL as well as the normal image, say Y. + +config SPL_FRAMEWORK + bool "Support SPL based upon the common SPL framework" + depends on SPL + default y + help + Enable the SPL framework under common/spl/. This framework + supports MMC, NAND and YMODEM and other methods loading of U-Boot + and the Linux Kernel. If unsure, say Y. + +config SPL_FRAMEWORK_BOARD_INIT_F + bool "Define a generic function board_init_f" + depends on SPL_FRAMEWORK + help + Define a generic function board_init_f that: + - initialize the spl (spl_early_init) + - initialize the serial (preloader_console_init) + Unless you want to provide your own board_init_f, you should say Y. + +config SPL_SIZE_LIMIT + hex "Maximum size of SPL image" + depends on SPL + default 0x11000 if ARCH_MX6 && !MX6_OCRAM_256KB + default 0x31000 if ARCH_MX6 && MX6_OCRAM_256KB + default 0x0 + help + Specifies the maximum length of the U-Boot SPL image. + If this value is zero, it is ignored. + +config SPL_SIZE_LIMIT_SUBTRACT_GD + bool "SPL image size check: provide space for global data" + depends on SPL_SIZE_LIMIT > 0 + help + If enabled, aligned size of global data is reserved in + SPL_SIZE_LIMIT check to ensure such an image does not overflow SRAM + if SPL_SIZE_LIMIT describes the size of SRAM available for SPL when + pre-reloc global data is put into this SRAM, too. + +config SPL_SIZE_LIMIT_SUBTRACT_MALLOC + bool "SPL image size check: provide space for malloc() pool before relocation" + depends on SPL_SIZE_LIMIT > 0 + help + If enabled, SPL_SYS_MALLOC_F_LEN is reserved in SPL_SIZE_LIMIT check + to ensure such an image does not overflow SRAM if SPL_SIZE_LIMIT + describes the size of SRAM available for SPL when pre-reloc malloc + pool is put into this SRAM, too. + +config SPL_SIZE_LIMIT_PROVIDE_STACK + hex "SPL image size check: provide stack space before relocation" + depends on SPL_SIZE_LIMIT > 0 + default 0 + help + If set, this size is reserved in SPL_SIZE_LIMIT check to ensure such + an image does not overflow SRAM if SPL_SIZE_LIMIT describes the size + of SRAM available for SPL when the stack required before reolcation + uses this SRAM, too. + +config SPL_SYS_STACK_F_CHECK_BYTE + hex + default 0xaa + help + Constant used to check the stack + +config SPL_SYS_REPORT_STACK_F_USAGE + depends on SPL_SIZE_LIMIT_PROVIDE_STACK != 0 + bool "Check and report stack usage in SPL before relocation" + help + If this option is enabled, the initial SPL stack is filled with 0xaa + very early, up to the size configured with + SPL_SIZE_LIMIT_PROVIDE_STACK. + Later when SPL is done using this initial stack and switches to a + stack in DRAM, the actually used size of this initial stack is + reported by examining the memory and searching for the lowest + occurrence of non 0xaa bytes. + This default implementation works for stacks growing down only. + +menu "PowerPC and LayerScape SPL Boot options" + +config SPL_NAND_BOOT + bool "Load SPL from NAND flash" + depends on PPC && (SUPPORT_SPL && !SPL_FRAMEWORK) + +config SPL_MMC_BOOT + bool "Load SPL from SD Card / eMMC" + depends on PPC && (SUPPORT_SPL && !SPL_FRAMEWORK) + +config SPL_SPI_BOOT + bool "Load SPL from SPI flash" + depends on PPC && (SUPPORT_SPL && !SPL_FRAMEWORK) + +config SPL_FSL_PBL + bool "Create SPL in Freescale PBI format" + depends on (PPC || ARCH_LS1021A || ARCH_LS1043A || ARCH_LS1046A) && \ + SUPPORT_SPL + help + Create boot binary having SPL binary in PBI format concatenated with + u-boot binary. + +endmenu + +config HANDOFF + bool "Pass hand-off information from SPL to U-Boot proper" + depends on SPL && BLOBLIST + help + It is useful to be able to pass information from SPL to U-Boot + proper to preserve state that is known in SPL and is needed in U-Boot. + Enable this to locate the handoff information in U-Boot proper, early + in boot. It is available in gd->handoff. The state state is set up + in SPL (or TPL if that is being used). + +if SPL + +config SPL_HANDOFF + bool "Pass hand-off information from SPL to U-Boot proper" + depends on HANDOFF && SPL_BLOBLIST + default y + help + This option enables SPL to write handoff information. This can be + used to pass information like the size of SDRAM from SPL to U-Boot + proper. Also SPL can receive information from TPL in the same place + if that is enabled. + +config SPL_LDSCRIPT + string "Linker script for the SPL stage" + default "arch/\$(ARCH)/cpu/u-boot-spl.lds" + help + The SPL stage will usually require a different linker-script + (as it runs from a different memory region) than the regular + U-Boot stage. Set this to the path of the linker-script to + be used for SPL. + +config SPL_TEXT_BASE + hex "SPL Text Base" + default ISW_ENTRY_ADDR if AM43XX || AM33XX || OMAP54XX || ARCH_KEYSTONE + default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I + default 0x20060 if SUN50I_GEN_H6 + default 0x00060 if ARCH_SUNXI + default 0xfffc0000 if ARCH_ZYNQMP + default 0x0 + help + The address in memory that SPL will be running from. + +config SPL_BOARD_INIT + bool "Call board-specific initialization in SPL" + help + If this option is enabled, U-Boot will call the function + spl_board_init() from board_init_r(). This function should be + provided by the board. + +config SPL_BOOTROM_SUPPORT + bool "Support returning to the BOOTROM" + help + Some platforms (e.g. the Rockchip RK3368) provide support in their + ROM for loading the next boot-stage after performing basic setup + from the SPL stage. + + Enable this option, to return to the BOOTROM through the + BOOT_DEVICE_BOOTROM (or fall-through to the next boot device in the + boot device list, if not implemented for a given board) + +config SPL_BOOTCOUNT_LIMIT + bool "Support bootcount in SPL" + depends on SPL_ENV_SUPPORT && !TPL_BOOTCOUNT_LIMIT + help + On some boards, which use 'falcon' mode, it is necessary to check + and increment the number of boot attempts. Such boards do not + use proper U-Boot for normal boot flow and hence needs those + adjustments to be done in the SPL. + +config SPL_RAW_IMAGE_SUPPORT + bool "Support SPL loading and booting of RAW images" + default n if (ARCH_MX6 && (SPL_MMC_SUPPORT || SPL_SATA_SUPPORT)) + default y if !TI_SECURE_DEVICE + help + SPL will support loading and booting a RAW image when this option + is y. If this is not set, SPL will move on to other available + boot media to find a suitable image. + +config SPL_LEGACY_IMAGE_SUPPORT + bool "Support SPL loading and booting of Legacy images" + default y if !TI_SECURE_DEVICE && !SPL_LOAD_FIT + help + SPL will support loading and booting Legacy images when this option + is y. If this is not set, SPL will move on to other available + boot media to find a suitable image. + +config SPL_LEGACY_IMAGE_CRC_CHECK + bool "Check CRC of Legacy images" + depends on SPL_LEGACY_IMAGE_SUPPORT + select SPL_CRC32_SUPPORT + help + Enable this to check the CRC of Legacy images. While this increases + reliability, it affects both code size and boot duration. + If disabled, Legacy images are booted if the image magic and size + are correct, without further integrity checks. + +config SPL_SYS_MALLOC_SIMPLE + bool + prompt "Only use malloc_simple functions in the SPL" + help + Say Y here to only use the *_simple malloc functions from + malloc_simple.c, rather then using the versions from dlmalloc.c; + this will make the SPL binary smaller at the cost of more heap + usage as the *_simple malloc functions do not re-use free-ed mem. + +config TPL_SYS_MALLOC_SIMPLE + bool + prompt "Only use malloc_simple functions in the TPL" + depends on TPL + help + Say Y here to only use the *_simple malloc functions from + malloc_simple.c, rather then using the versions from dlmalloc.c; + this will make the TPL binary smaller at the cost of more heap + usage as the *_simple malloc functions do not re-use free-ed mem. + +config SPL_STACK_R + bool "Enable SDRAM location for SPL stack" + help + SPL starts off execution in SRAM and thus typically has only a small + stack available. Since SPL sets up DRAM while in its board_init_f() + function, it is possible for the stack to move there before + board_init_r() is reached. This option enables a special SDRAM + location for the SPL stack. U-Boot SPL switches to this after + board_init_f() completes, and before board_init_r() starts. + +config SPL_STACK_R_ADDR + depends on SPL_STACK_R + hex "SDRAM location for SPL stack" + default 0x82000000 if ARCH_OMAP2PLUS + help + Specify the address in SDRAM for the SPL stack. This will be set up + before board_init_r() is called. + +config SPL_STACK_R_MALLOC_SIMPLE_LEN + depends on SPL_STACK_R && SPL_SYS_MALLOC_SIMPLE + hex "Size of malloc_simple heap after switching to DRAM SPL stack" + default 0x100000 + help + Specify the amount of the stack to use as memory pool for + malloc_simple after switching the stack to DRAM. This may be set + to give board_init_r() a larger heap then the initial heap in + SRAM which is limited to SYS_MALLOC_F_LEN bytes. + +config SPL_SEPARATE_BSS + bool "BSS section is in a different memory region from text" + help + Some platforms need a large BSS region in SPL and can provide this + because RAM is already set up. In this case BSS can be moved to RAM. + This option should then be enabled so that the correct device tree + location is used. Normally we put the device tree at the end of BSS + but with this option enabled, it goes at _image_binary_end. + +config SPL_READ_ONLY + bool + depends on SPL_OF_PLATDATA + # Bind cannot be supported because the udevice structs are in read-only + # memory so we cannot update the linked lists. + select SPL_OF_PLATDATA_NO_BIND + select SPL_OF_PLATDATA_RT + help + Some platforms (e.g. x86 Apollo Lake) load SPL into a read-only + section of memory. This means that of-platdata must make a copy (in + writeable memory) of anything it wants to modify, such as + device-private data. + +config SPL_BANNER_PRINT + bool "Enable output of the SPL banner 'U-Boot SPL ...'" + default y + help + If this option is enabled, SPL will print the banner with version + info. Disabling this option could be useful to reduce SPL boot time + (e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud). + +config TPL_BANNER_PRINT + bool "Enable output of the TPL banner 'U-Boot TPL ...'" + depends on TPL + default y + help + If this option is enabled, TPL will print the banner with version + info. Disabling this option could be useful to reduce TPL boot time + (e.g. approx. 6 ms faster, when output on i.MX6 with 115200 baud). + +config SPL_EARLY_BSS + depends on ARM && !ARM64 + bool "Allows initializing BSS early before entering board_init_f" + help + On some platform we have sufficient memory available early on to + allow setting up and using a basic BSS prior to entering + board_init_f. Activating this option will also de-activate the + clearing of BSS during the SPL relocation process, thus allowing + to carry state from board_init_f to board_init_r by way of BSS. + +config SPL_DISPLAY_PRINT + bool "Display a board-specific message in SPL" + help + If this option is enabled, U-Boot will call the function + spl_display_print() immediately after displaying the SPL console + banner ("U-Boot SPL ..."). This function should be provided by + the board. + +config SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR + bool "MMC raw mode: by sector" + default y if ARCH_SUNXI || ARCH_DAVINCI || ARCH_UNIPHIER || \ + ARCH_MX6 || ARCH_MX7 || \ + ARCH_ROCKCHIP || ARCH_MVEBU || ARCH_SOCFPGA || \ + ARCH_AT91 || ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || \ + OMAP44XX || OMAP54XX || AM33XX || AM43XX || \ + TARGET_SIFIVE_UNLEASHED || TARGET_SIFIVE_UNMATCHED + help + Use sector number for specifying U-Boot location on MMC/SD in + raw mode. + +config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR + hex "Address on the MMC to load U-Boot from" + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR + default 0x40 if ARCH_SUNXI + default 0x75 if ARCH_DAVINCI + default 0x8a if ARCH_MX6 || ARCH_MX7 + default 0x100 if ARCH_UNIPHIER + default 0x140 if ARCH_MVEBU + default 0x200 if ARCH_SOCFPGA || ARCH_AT91 + default 0x300 if ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || OMAP44XX || \ + OMAP54XX || AM33XX || AM43XX || ARCH_K3 + default 0x4000 if ARCH_ROCKCHIP + default 0x822 if TARGET_SIFIVE_UNLEASHED || TARGET_SIFIVE_UNMATCHED + help + Address on the MMC to load U-Boot from, when the MMC is being used + in raw mode. Units: MMC sectors (1 sector = 512 bytes). + +config SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET + hex "U-Boot main hardware partition image offset" + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR + default 0x10 if ARCH_SUNXI + default 0x0 + help + On some platforms SPL location depends on hardware partition. The ROM + code skips the MBR sector when loading SPL from main hardware data + partition. This adds offset to the main U-Boot image. Set this symbol + to the number of skipped sectors. + + If unsure, leave the default. + +config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION + bool "MMC Raw mode: by partition" + help + Use a partition for loading U-Boot when using MMC/SD in raw mode. + +config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION + hex "Partition to use to load U-Boot from" + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION + default 1 + help + Partition on the MMC to load U-Boot from when the MMC is being + used in raw mode + +config SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE + bool "MMC raw mode: by partition type" + depends on DOS_PARTITION && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION + help + Use partition type for specifying U-Boot partition on MMC/SD in + raw mode. U-Boot will be loaded from the first partition of this + type to be found. + +config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_TYPE + hex "Partition Type on the MMC to load U-Boot from" + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE + help + Partition Type on the MMC to load U-Boot from, when the MMC is being + used in raw mode. + +config SUPPORT_EMMC_BOOT_OVERRIDE_PART_CONFIG + bool "Override eMMC EXT_CSC_PART_CONFIG by user defined partition" + depends on SUPPORT_EMMC_BOOT + help + eMMC boot partition is normally configured by the bits of the EXT_CSD + register (EXT_CSC_PART_CONFIG), BOOT_PARTITION_ENABLE field. In some + cases it might be required in SPL to load the image from different + partition than the partition selected by EXT_CSC_PART_CONFIG register. + Enable this option if you intend to use an eMMC boot partition other + then selected via EXT_CSC_PART_CONFIG register and specify the custom + partition number by the CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION + option. + +config SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION + int "Number of the eMMC boot partition to use" + depends on SUPPORT_EMMC_BOOT_OVERRIDE_PART_CONFIG + default 1 + help + eMMC boot partition number to use when the eMMC in raw mode and + the eMMC EXT_CSC_PART_CONFIG selection should be overridden in SPL + by user defined partition number. + +config SPL_CRC32_SUPPORT + bool "Support CRC32" + default y if SPL_LEGACY_IMAGE_SUPPORT + help + Enable this to support CRC32 in uImages or FIT images within SPL. + This is a 32-bit checksum value that can be used to verify images. + For FIT images, this is the least secure type of checksum, suitable + for detected accidental image corruption. For secure applications you + should consider SHA1 or SHA256. + +config SPL_MD5_SUPPORT + bool "Support MD5" + depends on SPL_FIT + help + Enable this to support MD5 in FIT images within SPL. An MD5 + checksum is a 128-bit hash value used to check that the image + contents have not been corrupted. Note that MD5 is not considered + secure as it is possible (with a brute-force attack) to adjust the + image while still retaining the same MD5 hash value. For secure + applications where images may be changed maliciously, you should + consider SHA256 or SHA384. + +config SPL_SHA1_SUPPORT + bool "Support SHA1" + depends on SPL_FIT + select SHA1 + help + Enable this to support SHA1 in FIT images within SPL. A SHA1 + checksum is a 160-bit (20-byte) hash value used to check that the + image contents have not been corrupted or maliciously altered. + While SHA1 is fairly secure it is coming to the end of its life + due to the expanding computing power available to brute-force + attacks. For more security, consider SHA256 or SHA384. + +config SPL_SHA256_SUPPORT + bool "Support SHA256" + depends on SPL_FIT + select SHA256 + help + Enable this to support SHA256 in FIT images within SPL. A SHA256 + checksum is a 256-bit (32-byte) hash value used to check that the + image contents have not been corrupted. + +config SPL_SHA384_SUPPORT + bool "Support SHA384" + depends on SPL_FIT + select SHA384 + select SHA512_ALGO + help + Enable this to support SHA384 in FIT images within SPL. A SHA384 + checksum is a 384-bit (48-byte) hash value used to check that the + image contents have not been corrupted. Use this for the highest + security. + +config SPL_SHA512_SUPPORT + bool "Support SHA512" + depends on SPL_FIT + select SHA512 + select SHA512_ALGO + help + Enable this to support SHA512 in FIT images within SPL. A SHA512 + checksum is a 512-bit (64-byte) hash value used to check that the + image contents have not been corrupted. + +config SPL_FIT_IMAGE_TINY + bool "Remove functionality from SPL FIT loading to reduce size" + depends on SPL_FIT + default y if MACH_SUN50I || MACH_SUN50I_H5 || SUN50I_GEN_H6 + default y if ARCH_IMX8M + help + Enable this to reduce the size of the FIT image loading code + in SPL, if space for the SPL binary is very tight. + + This skips the recording of each loaded payload + (i.e. loadable) into the FDT (modifying the loaded FDT to + ensure this information is available to the next image + invoked). + +config SPL_CACHE_SUPPORT + bool "Support CACHE drivers" + help + Enable CACHE drivers in SPL. These drivers can keep data so that + future requests for that data can be served faster. Enable this option + to build the drivers in drivers/cache as part of an SPL build. + +config SPL_CPU + bool "Support CPU drivers" + help + Enable this to support CPU drivers in SPL. These drivers can set + up CPUs and provide information about them such as the model and + name. This can be useful in SPL since setting up the CPUs earlier + may improve boot performance. Enable this option to build the + drivers in drivers/cpu as part of an SPL build. + +config SPL_CRYPTO_SUPPORT + bool "Support crypto drivers" + help + Enable crypto drivers in SPL. These drivers can be used to + accelerate secure boot processing in secure applications. Enable + this option to build the drivers in drivers/crypto as part of an + SPL build. + +config SPL_HASH_SUPPORT + bool "Support hashing drivers" + select SHA1 + select SHA256 + help + Enable hashing drivers in SPL. These drivers can be used to + accelerate secure boot processing in secure applications. Enable + this option to build system-specific drivers for hash acceleration + as part of an SPL build. + +config TPL_HASH_SUPPORT + bool "Support hashing drivers in TPL" + depends on TPL + select SHA1 + select SHA256 + help + Enable hashing drivers in SPL. These drivers can be used to + accelerate secure boot processing in secure applications. Enable + this option to build system-specific drivers for hash acceleration + as part of an SPL build. + +config SPL_DMA + bool "Support DMA drivers" + help + Enable DMA (direct-memory-access) drivers in SPL. These drivers + can be used to handle memory-to-peripheral data transfer without + the CPU moving the data. Enable this option to build the drivers + in drivers/dma as part of an SPL build. + +config SPL_DRIVERS_MISC_SUPPORT + bool "Support misc drivers" + help + Enable miscellaneous drivers in SPL. These drivers perform various + tasks that don't fall nicely into other categories, Enable this + option to build the drivers in drivers/misc as part of an SPL + build, for those that support building in SPL (not all drivers do). + +config SPL_ENV_SUPPORT + bool "Support an environment" + help + Enable environment support in SPL. The U-Boot environment provides + a number of settings (essentially name/value pairs) which can + control many aspects of U-Boot's operation. Normally this is not + needed in SPL as it has a much simpler task with less + configuration. But some boards use this to support 'Falcon' boot + on EXT2 and FAT, where SPL boots directly into Linux without + starting U-Boot first. Enabling this option will make env_get() + and env_set() available in SPL. + +config SPL_SAVEENV + bool "Support save environment" + depends on SPL_ENV_SUPPORT + select SPL_MMC_WRITE if ENV_IS_IN_MMC + help + Enable save environment support in SPL after setenv. By default + the saveenv option is not provided in SPL, but some boards need + this support in 'Falcon' boot, where SPL need to boot from + different images based on environment variable set by OS. For + example OS may set "reboot_image" environment variable to + "recovery" inorder to boot recovery image by SPL. The SPL read + "reboot_image" and act accordingly and change the reboot_image + to default mode using setenv and save the environment. + +config SPL_ETH_SUPPORT + bool "Support Ethernet" + depends on SPL_ENV_SUPPORT + help + Enable access to the network subsystem and associated Ethernet + drivers in SPL. This permits SPL to load U-Boot over an Ethernet + link rather than from an on-board peripheral. Environment support + is required since the network stack uses a number of environment + variables. See also SPL_NET_SUPPORT. + +config SPL_FS_EXT4 + bool "Support EXT filesystems" + help + Enable support for EXT2/3/4 filesystems with SPL. This permits + U-Boot (or Linux in Falcon mode) to be loaded from an EXT + filesystem from within SPL. Support for the underlying block + device (e.g. MMC or USB) must be enabled separately. + +config SPL_FS_SQUASHFS + bool "Support SquashFS filesystems" + select FS_SQUASHFS + help + Enable support for SquashFS filesystems with SPL. This permits + U-Boot (or Linux in Falcon mode) to be loaded from a SquashFS + filesystem from within SPL. Support for the underlying block + device (e.g. MMC or USB) must be enabled separately. + +config SPL_FS_FAT + bool "Support FAT filesystems" + select FS_FAT + help + Enable support for FAT and VFAT filesystems with SPL. This + permits U-Boot (or Linux in Falcon mode) to be loaded from a FAT + filesystem from within SPL. Support for the underlying block + device (e.g. MMC or USB) must be enabled separately. + +config SPL_FAT_WRITE + bool "Support write for FAT filesystems" + help + Enable write support for FAT and VFAT filesystems with SPL. + Support for the underlying block device (e.g. MMC or USB) must be + enabled separately. + +config SPL_FPGA + bool "Support FPGAs" + help + Enable support for FPGAs in SPL. Field-programmable Gate Arrays + provide software-configurable hardware which is typically used to + implement peripherals (such as UARTs, LCD displays, MMC) or + accelerate custom processing functions, such as image processing + or machine learning. Sometimes it is useful to program the FPGA + as early as possible during boot, and this option can enable that + within SPL. + +config SPL_GPIO_SUPPORT + bool "Support GPIO in SPL" + help + Enable support for GPIOs (General-purpose Input/Output) in SPL. + GPIOs allow U-Boot to read the state of an input line (high or + low) and set the state of an output line. This can be used to + drive LEDs, control power to various system parts and read user + input. GPIOs can be useful in SPL to enable a 'sign-of-life' LED, + for example. Enable this option to build the drivers in + drivers/gpio as part of an SPL build. + +config SPL_I2C_SUPPORT + bool "Support I2C" + help + Enable support for the I2C (Inter-Integrated Circuit) bus in SPL. + I2C works with a clock and data line which can be driven by a + one or more masters or slaves. It is a fairly complex bus but is + widely used as it only needs two lines for communication. Speeds of + 400kbps are typical but up to 3.4Mbps is supported by some + hardware. I2C can be useful in SPL to configure power management + ICs (PMICs) before raising the CPU clock speed, for example. + Enable this option to build the drivers in drivers/i2c as part of + an SPL build. + +config SPL_LIBCOMMON_SUPPORT + bool "Support common libraries" + help + Enable support for common U-Boot libraries within SPL. These + libraries include common code to deal with U-Boot images, + environment and USB, for example. This option is enabled on many + boards. Enable this option to build the code in common/ as part of + an SPL build. + +config SPL_LIBDISK_SUPPORT + bool "Support disk partitions" + select PARTITIONS + help + Enable support for disk partitions within SPL. 'Disk' is something + of a misnomer as it includes non-spinning media such as flash (as + used in MMC and USB sticks). Partitions provide a way for a disk + to be split up into separate regions, with a partition table placed + at the start or end which describes the location and size of each + 'partition'. These partitions are typically uses as individual block + devices, typically with an EXT2 or FAT filesystem in each. This + option enables whatever partition support has been enabled in + U-Boot to also be used in SPL. It brings in the code in disk/. + +config SPL_LIBGENERIC_SUPPORT + bool "Support generic libraries" + help + Enable support for generic U-Boot libraries within SPL. These + libraries include generic code to deal with device tree, hashing, + printf(), compression and the like. This option is enabled on many + boards. Enable this option to build the code in lib/ as part of an + SPL build. + +config SPL_DM_MAILBOX + bool "Support Mailbox" + help + Enable support for Mailbox within SPL. This enable the inter + processor communication protocols tobe used within SPL. Enable + this option to build the drivers in drivers/mailbox as part of + SPL build. + +config SPL_MMC_SUPPORT + bool "Support MMC" + depends on MMC + select HAVE_BLOCK_DEVICE + help + Enable support for MMC (Multimedia Card) within SPL. This enables + the MMC protocol implementation and allows any enabled drivers to + be used within SPL. MMC can be used with or without disk partition + support depending on the application (SPL_LIBDISK_SUPPORT). Enable + this option to build the drivers in drivers/mmc as part of an SPL + build. + +config SYS_MMCSD_FS_BOOT_PARTITION + int "MMC Boot Partition" + default 1 + help + Partition on the MMC to load U-Boot from when the MMC is being + used in fs mode + +config SPL_MMC_TINY + bool "Tiny MMC framework in SPL" + depends on SPL_MMC_SUPPORT + default n + help + Enable MMC framework tinification support. This option is useful if + if your SPL is extremely size constrained. Heed the warning, enable + this option if and only if you know exactly what you are doing, if + you are reading this help text, you most likely have no idea :-) + + The MMC framework is reduced to bare minimum to be useful. No malloc + support is needed for the MMC framework operation with this option + enabled. The framework supports exactly one MMC device and exactly + one MMC driver. The MMC driver can be adjusted to avoid any malloc + operations too, which can remove the need for malloc support in SPL + and thus further reduce footprint. + +config SPL_MMC_WRITE + bool "MMC/SD/SDIO card support for write operations in SPL" + depends on SPL_MMC_SUPPORT + default n + help + Enable write access to MMC and SD Cards in SPL + + +config SPL_MPC8XXX_INIT_DDR_SUPPORT + bool "Support MPC8XXX DDR init" + help + Enable support for DDR-SDRAM (double-data-rate synchronous dynamic + random-access memory) on the MPC8XXX family within SPL. This + allows DRAM to be set up before loading U-Boot into that DRAM, + where it can run. + +config SPL_MTD_SUPPORT + bool "Support MTD drivers" + help + Enable support for MTD (Memory Technology Device) within SPL. MTD + provides a block interface over raw NAND and can also be used with + SPI flash. This allows SPL to load U-Boot from supported MTD + devices. See SPL_NAND_SUPPORT and SPL_ONENAND_SUPPORT for how + to enable specific MTD drivers. + +config SPL_MUSB_NEW_SUPPORT + bool "Support new Mentor Graphics USB" + help + Enable support for Mentor Graphics USB in SPL. This is a new + driver used by some boards. Enable this option to build + the drivers in drivers/usb/musb-new as part of an SPL build. The + old drivers are in drivers/usb/musb. + +config SPL_NAND_SUPPORT + bool "Support NAND flash" + help + Enable support for NAND (Negative AND) flash in SPL. NAND flash + can be used to allow SPL to load U-Boot from supported devices. + This enables the drivers in drivers/mtd/nand/raw as part of an SPL + build. + +config SPL_NAND_DRIVERS + bool "Use standard NAND driver" + help + SPL uses normal NAND drivers, not minimal drivers. + +config SPL_NAND_ECC + bool "Include standard software ECC in the SPL" + +config SPL_NAND_SIMPLE + bool "Support simple NAND drivers in SPL" + help + Support for NAND boot using simple NAND drivers that + expose the cmd_ctrl() interface. + +config SPL_NAND_BASE + depends on SPL_NAND_DRIVERS + bool "Use Base NAND Driver" + help + Include nand_base.c in the SPL. + +config SPL_NAND_IDENT + depends on SPL_NAND_BASE + bool "Use chip ID to identify NAND flash" + help + SPL uses the chip ID list to identify the NAND flash. + +config SPL_UBI + bool "Support UBI" + help + Enable support for loading payloads from UBI. See + README.ubispl for more info. + +if SPL_DM +config SPL_CACHE + depends on CACHE + bool "Support cache drivers in SPL" + help + Enable support for cache drivers in SPL. + +config SPL_DM_SPI + bool "Support SPI DM drivers in SPL" + help + Enable support for SPI DM drivers in SPL. + +config SPL_DM_SPI_FLASH + bool "Support SPI DM FLASH drivers in SPL" + help + Enable support for SPI DM flash drivers in SPL. + +endif +if SPL_UBI +config SPL_UBI_LOAD_BY_VOLNAME + bool "Support loading volumes by name" + help + This enables support for loading UBI volumes by name. When this + is set, CONFIG_SPL_UBI_LOAD_MONITOR_VOLNAME can be used to + configure the volume name from which to load U-Boot. + +config SPL_UBI_MAX_VOL_LEBS + int "Maximum number of LEBs per volume" + depends on SPL_UBI + help + The maximum number of logical eraseblocks which a static volume + to load can contain. Used for sizing the scan data structure. + +config SPL_UBI_MAX_PEB_SIZE + int "Maximum PEB size" + depends on SPL_UBI + help + The maximum physical erase block size. + +config SPL_UBI_MAX_PEBS + int "Maximum number of PEBs" + depends on SPL_UBI + help + The maximum physical erase block size. If not overridden by + board code, this value will be used as the actual number of PEBs. + +config SPL_UBI_PEB_OFFSET + int "Offset to first UBI PEB" + depends on SPL_UBI + help + The offset in number of PEBs from the start of flash to the first + PEB part of the UBI image. + +config SPL_UBI_VID_OFFSET + int "Offset to VID header" + depends on SPL_UBI + +config SPL_UBI_LEB_START + int "Offset to LEB in PEB" + depends on SPL_UBI + help + The offset in bytes to the LEB within a PEB. + +config SPL_UBI_INFO_ADDR + hex "Address to place UBI scan info" + depends on SPL_UBI + help + Address for ubispl to place the scan info. Read README.ubispl to + determine the required size + +config SPL_UBI_VOL_IDS + int "Maximum volume id" + depends on SPL_UBI + help + The maximum volume id which can be loaded. Used for sizing the + scan data structure. + +config SPL_UBI_LOAD_MONITOR_ID + int "id of U-Boot volume" + depends on SPL_UBI + help + The UBI volume id from which to load U-Boot + +config SPL_UBI_LOAD_MONITOR_VOLNAME + string "volume name of U-Boot volume" + depends on SPL_UBI_LOAD_BY_VOLNAME + help + The UBI volume name from which to load U-Boot + +config SPL_UBI_LOAD_KERNEL_ID + int "id of kernel volume" + depends on SPL_OS_BOOT && SPL_UBI + help + The UBI volume id from which to load the kernel + +config SPL_UBI_LOAD_ARGS_ID + int "id of kernel args volume" + depends on SPL_OS_BOOT && SPL_UBI + help + The UBI volume id from which to load the device tree + +config UBI_SPL_SILENCE_MSG + bool "silence UBI SPL messages" + default n + help + Disable messages from UBI SPL. This leaves warnings + and errors enabled. + +endif # if SPL_UBI + +config SPL_NET_SUPPORT + bool "Support networking" + help + Enable support for network devices (such as Ethernet) in SPL. + This permits SPL to load U-Boot over a network link rather than + from an on-board peripheral. Environment support is required since + the network stack uses a number of environment variables. See also + SPL_ETH_SUPPORT. + +if SPL_NET_SUPPORT +config SPL_NET_VCI_STRING + string "BOOTP Vendor Class Identifier string sent by SPL" + help + As defined by RFC 2132 the vendor class identifier field can be + sent by the client to identify the vendor type and configuration + of a client. This is often used in practice to allow for the DHCP + server to specify different files to load depending on if the ROM, + SPL or U-Boot itself makes the request +endif # if SPL_NET_SUPPORT + +config SPL_NO_CPU_SUPPORT + bool "Drop CPU code in SPL" + help + This is specific to the ARM926EJ-S CPU. It disables the standard + start.S start-up code, presumably so that a replacement can be + used on that CPU. You should not enable it unless you know what + you are doing. + +config SPL_NOR_SUPPORT + bool "Support NOR flash" + help + Enable support for loading U-Boot from memory-mapped NOR (Negative + OR) flash in SPL. NOR flash is slow to write but fast to read, and + a memory-mapped device makes it very easy to access. Loading from + NOR is typically achieved with just a memcpy(). + +config SPL_XIP_SUPPORT + bool "Support XIP" + depends on SPL + help + Enable support for execute in place of U-Boot or kernel image. There + is no need to copy image from flash to ram if flash supports execute + in place. Its very useful in systems having enough flash but not + enough ram to load the image. + +config SPL_ONENAND_SUPPORT + bool "Support OneNAND flash" + help + Enable support for OneNAND (Negative AND) flash in SPL. OneNAND is + a type of NAND flash and therefore can be used to allow SPL to + load U-Boot from supported devices. This enables the drivers in + drivers/mtd/onenand as part of an SPL build. + +config SPL_OS_BOOT + bool "Activate Falcon Mode" + depends on !TI_SECURE_DEVICE + default n + help + Enable booting directly to an OS from SPL. + for more info read doc/README.falcon + +if SPL_OS_BOOT +config SYS_OS_BASE + hex "addr, where OS is found" + depends on SPL_NOR_SUPPORT + help + Specify the address, where the OS image is found, which + gets booted. + +endif # SPL_OS_BOOT + +config SPL_PAYLOAD + string "SPL payload" + default "tpl/u-boot-with-tpl.bin" if TPL + default "u-boot.bin" + help + Payload for SPL boot. For backward compatibility, default to + u-boot.bin, i.e. RAW image without any header. In case of + TPL, tpl/u-boot-with-tpl.bin. For new boards, suggest to + use u-boot.img. + +config SPL_PCI + bool "Support PCI drivers" + help + Enable support for PCI in SPL. For platforms that need PCI to boot, + or must perform some init using PCI in SPL, this provides the + necessary driver support. This enables the drivers in drivers/pci + as part of an SPL build. + +config SPL_PCH_SUPPORT + bool "Support PCH drivers" + help + Enable support for PCH (Platform Controller Hub) devices in SPL. + These are used to set up GPIOs and the SPI peripheral early in + boot. This enables the drivers in drivers/pch as part of an SPL + build. + +config SPL_POST_MEM_SUPPORT + bool "Support POST drivers" + help + Enable support for POST (Power-on Self Test) in SPL. POST is a + procedure that checks that the hardware (CPU or board) appears to + be functionally correctly. It is a sanity check that can be + performed before booting. This enables the drivers in post/drivers + as part of an SPL build. + +config SPL_DM_RESET + bool "Support reset drivers" + depends on SPL + help + Enable support for reset control in SPL. + That can be useful in SPL to handle IP reset in driver, as in U-Boot, + by using the generic reset API provided by driver model. + This enables the drivers in drivers/reset as part of an SPL build. + +config SPL_POWER_SUPPORT + bool "Support power drivers" + help + Enable support for power control in SPL. This includes support + for PMICs (Power-management Integrated Circuits) and some of the + features provided by PMICs. In particular, voltage regulators can + be used to enable/disable power and vary its voltage. That can be + useful in SPL to turn on boot peripherals and adjust CPU voltage + so that the clock speed can be increased. This enables the drivers + in drivers/power, drivers/power/pmic and drivers/power/regulator + as part of an SPL build. + +config SPL_POWER_DOMAIN + bool "Support power domain drivers" + help + Enable support for power domain control in SPL. Many SoCs allow + power to be applied to or removed from portions of the SoC (power + domains). This may be used to save power. This API provides the + means to control such power management hardware. This enables + the drivers in drivers/power/domain as part of a SPL build. + +config SPL_RAM_SUPPORT + bool "Support booting from RAM" + default y if MICROBLAZE || ARCH_SOCFPGA || ARCH_TEGRA || ARCH_ZYNQ + help + Enable booting of an image in RAM. The image can be preloaded or + it can be loaded by SPL directly into RAM (e.g. using USB). + +config SPL_RAM_DEVICE + bool "Support booting from preloaded image in RAM" + depends on SPL_RAM_SUPPORT + default y if MICROBLAZE || ARCH_SOCFPGA || ARCH_TEGRA || ARCH_ZYNQ + help + Enable booting of an image already loaded in RAM. The image has to + be already in memory when SPL takes over, e.g. loaded by the boot + ROM. + +config SPL_REMOTEPROC + bool "Support REMOTEPROCS" + help + Enable support for REMOTEPROCs in SPL. This permits to load + a remote processor firmware in SPL. + +config SPL_RTC_SUPPORT + bool "Support RTC drivers" + help + Enable RTC (Real-time Clock) support in SPL. This includes support + for reading and setting the time. Some RTC devices also have some + non-volatile (battery-backed) memory which is accessible if + needed. This enables the drivers in drivers/rtc as part of an SPL + build. + +config SPL_SATA_SUPPORT + bool "Support loading from SATA" + help + Enable support for SATA (Serial AT attachment) in SPL. This allows + use of SATA devices such as hard drives and flash drivers for + loading U-Boot. SATA is used in higher-end embedded systems and + can provide higher performance than MMC , at somewhat higher + expense and power consumption. This enables loading from SATA + using a configured device. + +config SPL_SATA_RAW_U_BOOT_USE_SECTOR + bool "SATA raw mode: by sector" + depends on SPL_SATA_SUPPORT + help + Use sector number for specifying U-Boot location on SATA disk in + raw mode. + +config SPL_SATA_RAW_U_BOOT_SECTOR + hex "Sector on the SATA disk to load U-Boot from" + depends on SPL_SATA_RAW_U_BOOT_USE_SECTOR + help + Sector on the SATA disk to load U-Boot from, when the SATA disk is being + used in raw mode. Units: SATA disk sectors (1 sector = 512 bytes). + +config SPL_SERIAL_SUPPORT + bool "Support serial" + select SPL_PRINTF + select SPL_STRTO + help + Enable support for serial in SPL. This allows use of a serial UART + for displaying messages while SPL is running. It also brings in + printf() and panic() functions. This should normally be enabled + unless there are space reasons not to. Even then, consider + enabling SPL_USE_TINY_PRINTF which is a small printf() version. + +config SPL_SPI_SUPPORT + bool "Support SPI drivers" + help + Enable support for using SPI in SPL. This is used for connecting + to SPI flash for loading U-Boot. See SPL_SPI_FLASH_SUPPORT for + more details on that. The SPI driver provides the transport for + data between the SPI flash and the CPU. This option can be used to + enable SPI drivers that are needed for other purposes also, such + as a SPI PMIC. + +config SPL_SPI_FLASH_SUPPORT + bool "Support SPI flash drivers" + depends on SPL_SPI_SUPPORT + help + Enable support for using SPI flash in SPL, and loading U-Boot from + SPI flash. SPI flash (Serial Peripheral Bus flash) is named after + the SPI bus that is used to connect it to a system. It is a simple + but fast bidirectional 4-wire bus (clock, chip select and two data + lines). This enables the drivers in drivers/mtd/spi as part of an + SPL build. This normally requires SPL_SPI_SUPPORT. + +if SPL_SPI_FLASH_SUPPORT + +config SPL_SPI_FLASH_TINY + bool "Enable low footprint SPL SPI Flash support" + depends on !SPI_FLASH_BAR + default y if SPI_FLASH + help + Enable lightweight SPL SPI Flash support that supports just reading + data/images from flash. No support to write/erase flash. Enable + this if you have SPL size limitations and don't need full + fledged SPI flash support. + +config SPL_SPI_FLASH_SFDP_SUPPORT + bool "SFDP table parsing support for SPI NOR flashes" + depends on !SPI_FLASH_BAR && !SPL_SPI_FLASH_TINY + help + Enable support for parsing and auto discovery of parameters for + SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP) + tables as per JESD216 standard in SPL. + +config SPL_SPI_FLASH_MTD + bool "Support for SPI flash MTD drivers in SPL" + help + Enable support for SPI flash MTD drivers in SPL. + +config SPL_SPI_LOAD + bool "Support loading from SPI flash" + help + Enable support for loading next stage, U-Boot or otherwise, from + SPI NOR in U-Boot SPL. + +endif # SPL_SPI_FLASH_SUPPORT + +config SYS_SPI_U_BOOT_OFFS + hex "address of u-boot payload in SPI flash" + default 0x8000 if ARCH_SUNXI + default 0x0 + depends on SPL_SPI_LOAD || SPL_SPI_SUNXI + help + Address within SPI-Flash from where the u-boot payload is fetched + from. + +config SPL_THERMAL + bool "Driver support for thermal devices" + help + Enable support for temperature-sensing devices. Some SoCs have on-chip + temperature sensors to permit warnings, speed throttling or even + automatic power-off when the temperature gets too high or low. Other + devices may be discrete but connected on a suitable bus. + +config SPL_USB_HOST_SUPPORT + bool "Support USB host drivers" + select HAVE_BLOCK_DEVICE + help + Enable access to USB (Universal Serial Bus) host devices so that + SPL can load U-Boot from a connected USB peripheral, such as a USB + flash stick. While USB takes a little longer to start up than most + buses, it is very flexible since many different types of storage + device can be attached. This option enables the drivers in + drivers/usb/host as part of an SPL build. + +config SPL_USB_STORAGE + bool "Support loading from USB" + depends on SPL_USB_HOST_SUPPORT && !(BLK && !DM_USB) + help + Enable support for USB devices in SPL. This allows use of USB + devices such as hard drives and flash drivers for loading U-Boot. + The actual drivers are enabled separately using the normal U-Boot + config options. This enables loading from USB using a configured + device. + +config SPL_USB_GADGET + bool "Suppport USB Gadget drivers" + help + Enable USB Gadget API which allows to enable USB device functions + in SPL. + +if SPL_USB_GADGET + +config SPL_USB_ETHER + bool "Support USB Ethernet drivers" + help + Enable access to the USB network subsystem and associated + drivers in SPL. This permits SPL to load U-Boot over a + USB-connected Ethernet link (such as a USB Ethernet dongle) rather + than from an onboard peripheral. Environment support is required + since the network stack uses a number of environment variables. + See also SPL_NET_SUPPORT and SPL_ETH_SUPPORT. + +config SPL_DFU + bool "Support DFU (Device Firmware Upgrade)" + select SPL_HASH_SUPPORT + select SPL_DFU_NO_RESET + depends on SPL_RAM_SUPPORT + help + This feature enables the DFU (Device Firmware Upgrade) in SPL with + RAM memory device support. The ROM code will load and execute + the SPL built with dfu. The user can load binaries (u-boot/kernel) to + selected device partition from host-pc using dfu-utils. + This feature is useful to flash the binaries to factory or bare-metal + boards using USB interface. + +choice + bool "DFU device selection" + depends on SPL_DFU + +config SPL_DFU_RAM + bool "RAM device" + depends on SPL_DFU && SPL_RAM_SUPPORT + help + select RAM/DDR memory device for loading binary images + (u-boot/kernel) to the selected device partition using + DFU and execute the u-boot/kernel from RAM. + +endchoice + +config SPL_USB_SDP_SUPPORT + bool "Support SDP (Serial Download Protocol)" + depends on SPL_SERIAL_SUPPORT + help + Enable Serial Download Protocol (SDP) device support in SPL. This + allows to download images into memory and execute (jump to) them + using the same protocol as implemented by the i.MX family's boot ROM. + +config SPL_SDP_USB_DEV + int "SDP USB controller index" + default 0 + depends on SPL_USB_SDP_SUPPORT + help + Some boards have USB controller other than 0. Define this option + so it can be used in compiled environment. +endif + +config SPL_WATCHDOG_SUPPORT + bool "Support watchdog drivers" + imply SPL_WDT if !HW_WATCHDOG + help + Enable support for watchdog drivers in SPL. A watchdog is + typically a hardware peripheral which can reset the system when it + detects no activity for a while (such as a software crash). This + enables the drivers in drivers/watchdog as part of an SPL build. + +config SPL_YMODEM_SUPPORT + bool "Support loading using Ymodem" + depends on SPL_SERIAL_SUPPORT + help + While loading from serial is slow it can be a useful backup when + there is no other option. The Ymodem protocol provides a reliable + means of transmitting U-Boot over a serial line for using in SPL, + with a checksum to ensure correctness. + +config SPL_ATF + bool "Support ARM Trusted Firmware" + depends on ARM64 && SPL_FIT + help + ATF(ARM Trusted Firmware) is a component for ARM AArch64 which + is loaded by SPL (which is considered as BL2 in ATF terminology). + More detail at: https://github.com/ARM-software/arm-trusted-firmware + +config SPL_ATF_LOAD_IMAGE_V2 + bool "Use the new LOAD_IMAGE_V2 parameter passing" + depends on SPL_ATF + help + Some platforms use the newer LOAD_IMAGE_V2 parameter passing. + + If you want to load a bl31 image from the SPL and need the new + method, say Y. + +config SPL_ATF_NO_PLATFORM_PARAM + bool "Pass no platform parameter" + depends on SPL_ATF + help + While we expect to call a pointer to a valid FDT (or NULL) + as the platform parameter to an ATF, some ATF versions are + not U-Boot aware and have an insufficiently robust parameter + validation to gracefully reject a FDT being passed. + + If this option is enabled, the spl_atf os-type handler will + always pass NULL for the platform parameter. + + If your ATF is affected, say Y. + +config SPL_AM33XX_ENABLE_RTC32K_OSC + bool "Enable the RTC32K OSC on AM33xx based platforms" + default y if AM33XX + help + Enable access to the AM33xx RTC and select the external 32kHz clock + source. + +config SPL_OPTEE + bool "Support OP-TEE Trusted OS" + depends on ARM + help + OP-TEE is an open source Trusted OS which is loaded by SPL. + More detail at: https://github.com/OP-TEE/optee_os + +config SPL_OPENSBI + bool "Support RISC-V OpenSBI" + depends on RISCV && SPL_RISCV_MMODE && RISCV_SMODE + help + OpenSBI is an open-source implementation of the RISC-V Supervisor Binary + Interface (SBI) specification. U-Boot supports the OpenSBI FW_DYNAMIC + firmware. It is loaded and started by U-Boot SPL. + + More details are available at https://github.com/riscv/opensbi and + https://github.com/riscv/riscv-sbi-doc + +config SPL_OPENSBI_LOAD_ADDR + hex "OpenSBI load address" + depends on SPL_OPENSBI + help + Load address of the OpenSBI binary. + +config TPL + bool + depends on SUPPORT_TPL + prompt "Enable TPL" + help + If you want to build TPL as well as the normal image and SPL, say Y. + +if TPL + +config TPL_SIZE_LIMIT + hex "Maximum size of TPL image" + depends on TPL + default 0x0 + help + Specifies the maximum length of the U-Boot TPL image. + If this value is zero, it is ignored. + +config TPL_FRAMEWORK + bool "Support TPL based upon the common SPL framework" + default y if SPL_FRAMEWORK + help + Enable the SPL framework under common/spl/ for TPL builds. + This framework supports MMC, NAND and YMODEM and other methods + loading of U-Boot's SPL stage. If unsure, say Y. + +config TPL_HANDOFF + bool "Pass hand-off information from TPL to SPL and U-Boot proper" + depends on HANDOFF && TPL_BLOBLIST + default y + help + This option enables TPL to write handoff information. This can be + used to pass information like the size of SDRAM from TPL to U-Boot + proper. The information is also available to SPL if it is useful + there. + +config TPL_BOARD_INIT + bool "Call board-specific initialization in TPL" + help + If this option is enabled, U-Boot will call the function + spl_board_init() from board_init_r(). This function should be + provided by the board. + +config TPL_BOOTCOUNT_LIMIT + bool "Support bootcount in TPL" + depends on TPL_ENV_SUPPORT + help + If this option is enabled, the TPL will support bootcount. + For example, it may be useful to choose the device to boot. + +config TPL_LDSCRIPT + string "Linker script for the TPL stage" + depends on TPL + default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARM64 + default "arch/\$(ARCH)/cpu/u-boot-spl.lds" + help + The TPL stage will usually require a different linker-script + (as it runs from a different memory region) than the regular + U-Boot stage. Set this to the path of the linker-script to + be used for TPL. + + May be left empty to trigger the Makefile infrastructure to + fall back to the linker-script used for the SPL stage. + +config TPL_NEEDS_SEPARATE_TEXT_BASE + bool "TPL needs a separate text-base" + default n + depends on TPL + help + Enable, if the TPL stage should not inherit its text-base + from the SPL stage. When enabled, a base address for the + .text sections of the TPL stage has to be set below. + +config TPL_NEEDS_SEPARATE_STACK + bool "TPL needs a separate initial stack-pointer" + default n + depends on TPL + help + Enable, if the TPL stage should not inherit its initial + stack-pointer from the settings for the SPL stage. + +config TPL_TEXT_BASE + hex "Base address for the .text section of the TPL stage" + depends on TPL_NEEDS_SEPARATE_TEXT_BASE + help + The base address for the .text section of the TPL stage. + +config TPL_MAX_SIZE + int "Maximum size (in bytes) for the TPL stage" + default 0 + depends on TPL + help + The maximum size (in bytes) of the TPL stage. + +config TPL_STACK + hex "Address of the initial stack-pointer for the TPL stage" + depends on TPL_NEEDS_SEPARATE_STACK + help + The address of the initial stack-pointer for the TPL stage. + Usually this will be the (aligned) top-of-stack. + +config TPL_READ_ONLY + bool + depends on TPL_OF_PLATDATA + select TPL_OF_PLATDATA_NO_BIND + select TPL_OF_PLATDATA_RT + help + Some platforms (e.g. x86 Apollo Lake) load SPL into a read-only + section of memory. This means that of-platdata must make a copy (in + writeable memory) of anything it wants to modify, such as + device-private data. + +config TPL_BOOTROM_SUPPORT + bool "Support returning to the BOOTROM (from TPL)" + help + Some platforms (e.g. the Rockchip RK3368) provide support in their + ROM for loading the next boot-stage after performing basic setup + from the TPL stage. + + Enable this option, to return to the BOOTROM through the + BOOT_DEVICE_BOOTROM (or fall-through to the next boot device in the + boot device list, if not implemented for a given board) + +config TPL_DRIVERS_MISC_SUPPORT + bool "Support misc drivers in TPL" + help + Enable miscellaneous drivers in TPL. These drivers perform various + tasks that don't fall nicely into other categories, Enable this + option to build the drivers in drivers/misc as part of an TPL + build, for those that support building in TPL (not all drivers do). + +config TPL_ENV_SUPPORT + bool "Support an environment" + help + Enable environment support in TPL. See SPL_ENV_SUPPORT for details. + +config TPL_GPIO_SUPPORT + bool "Support GPIO in TPL" + help + Enable support for GPIOs (General-purpose Input/Output) in TPL. + GPIOs allow U-Boot to read the state of an input line (high or + low) and set the state of an output line. This can be used to + drive LEDs, control power to various system parts and read user + input. GPIOs can be useful in TPL to enable a 'sign-of-life' LED, + for example. Enable this option to build the drivers in + drivers/gpio as part of an TPL build. + +config TPL_I2C_SUPPORT + bool "Support I2C" + help + Enable support for the I2C bus in TPL. See SPL_I2C_SUPPORT for + details. + +config TPL_LIBCOMMON_SUPPORT + bool "Support common libraries" + help + Enable support for common U-Boot libraries within TPL. See + SPL_LIBCOMMON_SUPPORT for details. + +config TPL_LIBGENERIC_SUPPORT + bool "Support generic libraries" + help + Enable support for generic U-Boot libraries within TPL. See + SPL_LIBGENERIC_SUPPORT for details. + +config TPL_MPC8XXX_INIT_DDR_SUPPORT + bool "Support MPC8XXX DDR init" + help + Enable support for DDR-SDRAM on the MPC8XXX family within TPL. See + SPL_MPC8XXX_INIT_DDR_SUPPORT for details. + +config TPL_MMC_SUPPORT + bool "Support MMC" + depends on MMC + help + Enable support for MMC within TPL. See SPL_MMC_SUPPORT for details. + +config TPL_NAND_SUPPORT + bool "Support NAND flash" + help + Enable support for NAND in TPL. See SPL_NAND_SUPPORT for details. + +config TPL_PCI + bool "Support PCI drivers" + help + Enable support for PCI in TPL. For platforms that need PCI to boot, + or must perform some init using PCI in SPL, this provides the + necessary driver support. This enables the drivers in drivers/pci + as part of a TPL build. + +config TPL_PCH_SUPPORT + bool "Support PCH drivers" + help + Enable support for PCH (Platform Controller Hub) devices in TPL. + These are used to set up GPIOs and the SPI peripheral early in + boot. This enables the drivers in drivers/pch as part of a TPL + build. + +config TPL_RAM_SUPPORT + bool "Support booting from RAM" + help + Enable booting of an image in RAM. The image can be preloaded or + it can be loaded by TPL directly into RAM (e.g. using USB). + +config TPL_RAM_DEVICE + bool "Support booting from preloaded image in RAM" + depends on TPL_RAM_SUPPORT + help + Enable booting of an image already loaded in RAM. The image has to + be already in memory when TPL takes over, e.g. loaded by the boot + ROM. + +config TPL_RTC_SUPPORT + bool "Support RTC drivers" + help + Enable RTC (Real-time Clock) support in TPL. This includes support + for reading and setting the time. Some RTC devices also have some + non-volatile (battery-backed) memory which is accessible if + needed. This enables the drivers in drivers/rtc as part of an TPL + build. + +config TPL_SERIAL_SUPPORT + bool "Support serial" + select TPL_PRINTF + select TPL_STRTO + help + Enable support for serial in TPL. See SPL_SERIAL_SUPPORT for + details. + +config TPL_SPI_FLASH_SUPPORT + bool "Support SPI flash drivers" + help + Enable support for using SPI flash in TPL. See SPL_SPI_FLASH_SUPPORT + for details. + +config TPL_SPI_FLASH_TINY + bool "Enable low footprint TPL SPI Flash support" + depends on TPL_SPI_FLASH_SUPPORT && !SPI_FLASH_BAR + default y if SPI_FLASH + help + Enable lightweight TPL SPI Flash support that supports just reading + data/images from flash. No support to write/erase flash. Enable + this if you have TPL size limitations and don't need full-fledged + SPI flash support. + +config TPL_SPI_LOAD + bool "Support loading from SPI flash" + depends on TPL_SPI_FLASH_SUPPORT + help + Enable support for loading next stage, U-Boot or otherwise, from + SPI NOR in U-Boot TPL. + +config TPL_SPI_SUPPORT + bool "Support SPI drivers" + help + Enable support for using SPI in TPL. See SPL_SPI_SUPPORT for + details. + +config TPL_DM_SPI + bool "Support SPI DM drivers in TPL" + help + Enable support for SPI DM drivers in TPL. + +config TPL_DM_SPI_FLASH + bool "Support SPI DM FLASH drivers in TPL" + help + Enable support for SPI DM flash drivers in TPL. + +config TPL_YMODEM_SUPPORT + bool "Support loading using Ymodem" + depends on TPL_SERIAL_SUPPORT + help + While loading from serial is slow it can be a useful backup when + there is no other option. The Ymodem protocol provides a reliable + means of transmitting U-Boot over a serial line for using in TPL, + with a checksum to ensure correctness. + +endif # TPL + +config SPL_AT91_MCK_BYPASS + bool "Use external clock signal as a source of main clock for AT91 platforms" + depends on ARCH_AT91 + default n + help + Use external 8 to 24 Mhz clock signal as source of main clock instead + of an external crystal oscillator. + This option disables the internal driving on the XOUT pin. + The external source has to provide a stable clock on the XIN pin. + If this option is disabled, the SoC expects a crystal oscillator + that needs driving on both XIN and XOUT lines. + +endif # SPL +endmenu diff --git a/roms/u-boot/common/spl/Makefile b/roms/u-boot/common/spl/Makefile new file mode 100644 index 000000000..c576a7812 --- /dev/null +++ b/roms/u-boot/common/spl/Makefile @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2012 +# Texas Instruments Incorporated - http://www.ti.com/ +# Aneesh V <aneesh@ti.com> +# Based on common/Makefile. +# + +ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_$(SPL_TPL_)FRAMEWORK) += spl.o +obj-$(CONFIG_$(SPL_TPL_)BOOTROM_SUPPORT) += spl_bootrom.o +obj-$(CONFIG_$(SPL_TPL_)LOAD_FIT) += spl_fit.o +obj-$(CONFIG_$(SPL_TPL_)LEGACY_IMAGE_SUPPORT) += spl_legacy.o +obj-$(CONFIG_$(SPL_TPL_)NOR_SUPPORT) += spl_nor.o +obj-$(CONFIG_$(SPL_TPL_)XIP_SUPPORT) += spl_xip.o +obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += spl_ymodem.o +ifndef CONFIG_SPL_UBI +obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += spl_nand.o +obj-$(CONFIG_$(SPL_TPL_)ONENAND_SUPPORT) += spl_onenand.o +endif +obj-$(CONFIG_$(SPL_TPL_)UBI) += spl_ubi.o +obj-$(CONFIG_$(SPL_TPL_)NET_SUPPORT) += spl_net.o +obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += spl_mmc.o +obj-$(CONFIG_$(SPL_TPL_)ATF) += spl_atf.o +obj-$(CONFIG_$(SPL_TPL_)OPTEE) += spl_optee.o +obj-$(CONFIG_$(SPL_TPL_)OPENSBI) += spl_opensbi.o +obj-$(CONFIG_$(SPL_TPL_)USB_STORAGE) += spl_usb.o +obj-$(CONFIG_$(SPL_TPL_)FS_FAT) += spl_fat.o +obj-$(CONFIG_$(SPL_TPL_)FS_EXT4) += spl_ext.o +obj-$(CONFIG_$(SPL_TPL_)SATA_SUPPORT) += spl_sata.o +obj-$(CONFIG_$(SPL_TPL_)DFU) += spl_dfu.o +obj-$(CONFIG_$(SPL_TPL_)SPI_LOAD) += spl_spi.o +obj-$(CONFIG_$(SPL_TPL_)RAM_SUPPORT) += spl_ram.o +obj-$(CONFIG_$(SPL_TPL_)USB_SDP_SUPPORT) += spl_sdp.o +endif diff --git a/roms/u-boot/common/spl/spl.c b/roms/u-boot/common/spl/spl.c new file mode 100644 index 000000000..a0a608fd7 --- /dev/null +++ b/roms/u-boot/common/spl/spl.c @@ -0,0 +1,895 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> + */ + +#include <common.h> +#include <bloblist.h> +#include <binman_sym.h> +#include <bootstage.h> +#include <dm.h> +#include <handoff.h> +#include <hang.h> +#include <init.h> +#include <irq_func.h> +#include <log.h> +#include <mapmem.h> +#include <serial.h> +#include <spl.h> +#include <asm/global_data.h> +#include <asm/u-boot.h> +#include <nand.h> +#include <fat.h> +#include <u-boot/crc.h> +#include <version.h> +#include <image.h> +#include <malloc.h> +#include <mapmem.h> +#include <dm/root.h> +#include <linux/compiler.h> +#include <fdt_support.h> +#include <bootcount.h> +#include <wdt.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_UBOOT_START +#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE +#endif +#ifndef CONFIG_SYS_MONITOR_LEN +/* Unknown U-Boot size, let's assume it will not be more than 200 KB */ +#define CONFIG_SYS_MONITOR_LEN (200 * 1024) +#endif + +u32 *boot_params_ptr = NULL; + +/* See spl.h for information about this */ +binman_sym_declare(ulong, u_boot_any, image_pos); +binman_sym_declare(ulong, u_boot_any, size); + +#ifdef CONFIG_TPL +binman_sym_declare(ulong, spl, image_pos); +binman_sym_declare(ulong, spl, size); +#endif + +/* Define board data structure */ +static struct bd_info bdata __attribute__ ((section(".data"))); + +/* + * Board-specific Platform code can reimplement show_boot_progress () if needed + */ +__weak void show_boot_progress(int val) {} + +#if defined(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF) || \ + defined(CONFIG_SPL_ATF) +/* weak, default platform-specific function to initialize dram banks */ +__weak int dram_init_banksize(void) +{ + return 0; +} +#endif + +/* + * Default function to determine if u-boot or the OS should + * be started. This implementation always returns 1. + * + * Please implement your own board specific funcion to do this. + * + * RETURN + * 0 to not start u-boot + * positive if u-boot should start + */ +#ifdef CONFIG_SPL_OS_BOOT +__weak int spl_start_uboot(void) +{ + puts(SPL_TPL_PROMPT + "Please implement spl_start_uboot() for your board\n"); + puts(SPL_TPL_PROMPT "Direct Linux boot not active!\n"); + return 1; +} + +/* + * Weak default function for arch specific zImage check. Return zero + * and fill start and end address if image is recognized. + */ +int __weak bootz_setup(ulong image, ulong *start, ulong *end) +{ + return 1; +} +#endif + +/* Weak default function for arch/board-specific fixups to the spl_image_info */ +void __weak spl_perform_fixups(struct spl_image_info *spl_image) +{ +} + +void spl_fixup_fdt(void *fdt_blob) +{ +#if defined(CONFIG_SPL_OF_LIBFDT) + int err; + + if (!fdt_blob) + return; + + err = fdt_check_header(fdt_blob); + if (err < 0) { + printf("fdt_root: %s\n", fdt_strerror(err)); + return; + } + + /* fixup the memory dt node */ + err = fdt_shrink_to_minimum(fdt_blob, 0); + if (err == 0) { + printf(SPL_TPL_PROMPT "fdt_shrink_to_minimum err - %d\n", err); + return; + } + + err = arch_fixup_fdt(fdt_blob); + if (err) { + printf(SPL_TPL_PROMPT "arch_fixup_fdt err - %d\n", err); + return; + } +#endif +} + +ulong spl_get_image_pos(void) +{ + return spl_phase() == PHASE_TPL ? + binman_sym(ulong, spl, image_pos) : + binman_sym(ulong, u_boot_any, image_pos); +} + +ulong spl_get_image_size(void) +{ + return spl_phase() == PHASE_TPL ? + binman_sym(ulong, spl, size) : + binman_sym(ulong, u_boot_any, size); +} + +ulong spl_get_image_text_base(void) +{ + return spl_phase() == PHASE_TPL ? CONFIG_SPL_TEXT_BASE : + CONFIG_SYS_TEXT_BASE; +} + +/* + * Weak default function for board specific cleanup/preparation before + * Linux boot. Some boards/platforms might not need it, so just provide + * an empty stub here. + */ +__weak void spl_board_prepare_for_linux(void) +{ + /* Nothing to do! */ +} + +__weak void spl_board_prepare_for_boot(void) +{ + /* Nothing to do! */ +} + +__weak struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +{ + return map_sysmem(CONFIG_SYS_TEXT_BASE + offset, 0); +} + +void spl_set_header_raw_uboot(struct spl_image_info *spl_image) +{ + ulong u_boot_pos = binman_sym(ulong, u_boot_any, image_pos); + + spl_image->size = CONFIG_SYS_MONITOR_LEN; + + /* + * Binman error cases: address of the end of the previous region or the + * start of the image's entry area (usually 0) if there is no previous + * region. + */ + if (u_boot_pos && u_boot_pos != BINMAN_SYM_MISSING) { + /* Binman does not support separated entry addresses */ + spl_image->entry_point = u_boot_pos; + spl_image->load_addr = u_boot_pos; + } else { + spl_image->entry_point = CONFIG_SYS_UBOOT_START; + spl_image->load_addr = CONFIG_SYS_TEXT_BASE; + } + spl_image->os = IH_OS_U_BOOT; + spl_image->name = "U-Boot"; +} + +#ifdef CONFIG_SPL_LOAD_FIT_FULL +/* Parse and load full fitImage in SPL */ +static int spl_load_fit_image(struct spl_image_info *spl_image, + const struct image_header *header) +{ + bootm_headers_t images; + const char *fit_uname_config = NULL; + uintptr_t fdt_hack; + const char *uname; + ulong fw_data = 0, dt_data = 0, img_data = 0; + ulong fw_len = 0, dt_len = 0, img_len = 0; + int idx, conf_noffset; + int ret; + +#ifdef CONFIG_SPL_FIT_SIGNATURE + images.verify = 1; +#endif + ret = fit_image_load(&images, (ulong)header, + NULL, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1, + FIT_LOAD_OPTIONAL, &fw_data, &fw_len); + if (ret >= 0) { + printf("DEPRECATED: 'standalone = ' property."); + printf("Please use either 'firmware =' or 'kernel ='\n"); + } else { + ret = fit_image_load(&images, (ulong)header, NULL, + &fit_uname_config, IH_ARCH_DEFAULT, + IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL, + &fw_data, &fw_len); + } + + if (ret < 0) { + ret = fit_image_load(&images, (ulong)header, NULL, + &fit_uname_config, IH_ARCH_DEFAULT, + IH_TYPE_KERNEL, -1, FIT_LOAD_OPTIONAL, + &fw_data, &fw_len); + } + + if (ret < 0) + return ret; + + spl_image->size = fw_len; + spl_image->entry_point = fw_data; + spl_image->load_addr = fw_data; + if (fit_image_get_os(header, ret, &spl_image->os)) + spl_image->os = IH_OS_INVALID; + spl_image->name = genimg_get_os_name(spl_image->os); + + debug(SPL_TPL_PROMPT "payload image: %32s load addr: 0x%lx size: %d\n", + spl_image->name, spl_image->load_addr, spl_image->size); + +#ifdef CONFIG_SPL_FIT_SIGNATURE + images.verify = 1; +#endif + ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1, + FIT_LOAD_OPTIONAL, &dt_data, &dt_len); + if (ret >= 0) { + spl_image->fdt_addr = (void *)dt_data; + + if (spl_image->os == IH_OS_U_BOOT) { + /* HACK: U-boot expects FDT at a specific address */ + fdt_hack = spl_image->load_addr + spl_image->size; + fdt_hack = (fdt_hack + 3) & ~3; + debug("Relocating FDT to %p\n", spl_image->fdt_addr); + memcpy((void *)fdt_hack, spl_image->fdt_addr, dt_len); + } + } + + conf_noffset = fit_conf_get_node((const void *)header, + fit_uname_config); + if (conf_noffset <= 0) + return 0; + + for (idx = 0; + uname = fdt_stringlist_get((const void *)header, conf_noffset, + FIT_LOADABLE_PROP, idx, + NULL), uname; + idx++) + { +#ifdef CONFIG_SPL_FIT_SIGNATURE + images.verify = 1; +#endif + ret = fit_image_load(&images, (ulong)header, + &uname, &fit_uname_config, + IH_ARCH_DEFAULT, IH_TYPE_LOADABLE, -1, + FIT_LOAD_OPTIONAL_NON_ZERO, + &img_data, &img_len); + if (ret < 0) + return ret; + } + + return 0; +} +#endif + +__weak int spl_parse_legacy_header(struct spl_image_info *spl_image, + const struct image_header *header) +{ + /* LEGACY image not supported */ + debug("Legacy boot image support not enabled, proceeding to other boot methods\n"); + return -EINVAL; +} + +int spl_parse_image_header(struct spl_image_info *spl_image, + const struct image_header *header) +{ +#ifdef CONFIG_SPL_LOAD_FIT_FULL + int ret = spl_load_fit_image(spl_image, header); + + if (!ret) + return ret; +#endif + if (image_get_magic(header) == IH_MAGIC) { + int ret; + + ret = spl_parse_legacy_header(spl_image, header); + if (ret) + return ret; + } else { +#ifdef CONFIG_SPL_PANIC_ON_RAW_IMAGE + /* + * CONFIG_SPL_PANIC_ON_RAW_IMAGE is defined when the + * code which loads images in SPL cannot guarantee that + * absolutely all read errors will be reported. + * An example is the LPC32XX MLC NAND driver, which + * will consider that a completely unreadable NAND block + * is bad, and thus should be skipped silently. + */ + panic("** no mkimage signature but raw image not supported"); +#endif + +#ifdef CONFIG_SPL_OS_BOOT + ulong start, end; + + if (!bootz_setup((ulong)header, &start, &end)) { + spl_image->name = "Linux"; + spl_image->os = IH_OS_LINUX; + spl_image->load_addr = CONFIG_SYS_LOAD_ADDR; + spl_image->entry_point = CONFIG_SYS_LOAD_ADDR; + spl_image->size = end - start; + debug(SPL_TPL_PROMPT + "payload zImage, load addr: 0x%lx size: %d\n", + spl_image->load_addr, spl_image->size); + return 0; + } +#endif + +#ifdef CONFIG_SPL_RAW_IMAGE_SUPPORT + /* Signature not found - assume u-boot.bin */ + debug("mkimage signature not found - ih_magic = %x\n", + header->ih_magic); + spl_set_header_raw_uboot(spl_image); +#else + /* RAW image not supported, proceed to other boot methods. */ + debug("Raw boot image support not enabled, proceeding to other boot methods\n"); + return -EINVAL; +#endif + } + + return 0; +} + +__weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) +{ + typedef void __noreturn (*image_entry_noargs_t)(void); + + image_entry_noargs_t image_entry = + (image_entry_noargs_t)spl_image->entry_point; + + debug("image entry point: 0x%lx\n", spl_image->entry_point); + image_entry(); +} + +#if CONFIG_IS_ENABLED(HANDOFF) +/** + * Set up the SPL hand-off information + * + * This is initially empty (zero) but can be written by + */ +static int setup_spl_handoff(void) +{ + struct spl_handoff *ho; + + ho = bloblist_ensure(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff)); + if (!ho) + return -ENOENT; + + return 0; +} + +__weak int handoff_arch_save(struct spl_handoff *ho) +{ + return 0; +} + +static int write_spl_handoff(void) +{ + struct spl_handoff *ho; + int ret; + + ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff)); + if (!ho) + return -ENOENT; + handoff_save_dram(ho); + ret = handoff_arch_save(ho); + if (ret) + return ret; + debug(SPL_TPL_PROMPT "Wrote SPL handoff\n"); + + return 0; +} +#else +static inline int setup_spl_handoff(void) { return 0; } +static inline int write_spl_handoff(void) { return 0; } + +#endif /* HANDOFF */ + +/** + * get_bootstage_id() - Get the bootstage ID to emit + * + * @start: true if this is for starting SPL, false for ending it + * @return bootstage ID to use + */ +static enum bootstage_id get_bootstage_id(bool start) +{ + enum u_boot_phase phase = spl_phase(); + + if (IS_ENABLED(CONFIG_TPL_BUILD) && phase == PHASE_TPL) + return start ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_END_TPL; + else + return start ? BOOTSTAGE_ID_START_SPL : BOOTSTAGE_ID_END_SPL; +} + +static int spl_common_init(bool setup_malloc) +{ + int ret; + +#if CONFIG_VAL(SYS_MALLOC_F_LEN) + if (setup_malloc) { +#ifdef CONFIG_MALLOC_F_ADDR + gd->malloc_base = CONFIG_MALLOC_F_ADDR; +#endif + gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN); + gd->malloc_ptr = 0; + } +#endif + ret = bootstage_init(u_boot_first_phase()); + if (ret) { + debug("%s: Failed to set up bootstage: ret=%d\n", __func__, + ret); + return ret; + } +#ifdef CONFIG_BOOTSTAGE_STASH + if (!u_boot_first_phase()) { + const void *stash = map_sysmem(CONFIG_BOOTSTAGE_STASH_ADDR, + CONFIG_BOOTSTAGE_STASH_SIZE); + + ret = bootstage_unstash(stash, CONFIG_BOOTSTAGE_STASH_SIZE); + if (ret) + debug("%s: Failed to unstash bootstage: ret=%d\n", + __func__, ret); + } +#endif /* CONFIG_BOOTSTAGE_STASH */ + bootstage_mark_name(get_bootstage_id(true), + spl_phase_name(spl_phase())); +#if CONFIG_IS_ENABLED(LOG) + ret = log_init(); + if (ret) { + debug("%s: Failed to set up logging\n", __func__); + return ret; + } +#endif + if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { + ret = fdtdec_setup(); + if (ret) { + debug("fdtdec_setup() returned error %d\n", ret); + return ret; + } + } + if (CONFIG_IS_ENABLED(DM)) { + bootstage_start(BOOTSTAGE_ID_ACCUM_DM_SPL, + spl_phase() == PHASE_TPL ? "dm tpl" : "dm_spl"); + /* With CONFIG_SPL_OF_PLATDATA, bring in all devices */ + ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA)); + bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_SPL); + if (ret) { + debug("dm_init_and_scan() returned error %d\n", ret); + return ret; + } + } + + return 0; +} + +void spl_set_bd(void) +{ + /* + * NOTE: On some platforms (e.g. x86) bdata may be in flash and not + * writeable. + */ + if (!gd->bd) + gd->bd = &bdata; +} + +int spl_early_init(void) +{ + int ret; + + debug("%s\n", __func__); + + ret = spl_common_init(true); + if (ret) + return ret; + gd->flags |= GD_FLG_SPL_EARLY_INIT; + + return 0; +} + +int spl_init(void) +{ + int ret; + bool setup_malloc = !(IS_ENABLED(CONFIG_SPL_STACK_R) && + IS_ENABLED(CONFIG_SPL_SYS_MALLOC_SIMPLE)); + + debug("%s\n", __func__); + + if (!(gd->flags & GD_FLG_SPL_EARLY_INIT)) { + ret = spl_common_init(setup_malloc); + if (ret) + return ret; + } + gd->flags |= GD_FLG_SPL_INIT; + + return 0; +} + +#ifndef BOOT_DEVICE_NONE +#define BOOT_DEVICE_NONE 0xdeadbeef +#endif + +__weak void board_boot_order(u32 *spl_boot_list) +{ + spl_boot_list[0] = spl_boot_device(); +} + +static struct spl_image_loader *spl_ll_find_loader(uint boot_device) +{ + struct spl_image_loader *drv = + ll_entry_start(struct spl_image_loader, spl_image_loader); + const int n_ents = + ll_entry_count(struct spl_image_loader, spl_image_loader); + struct spl_image_loader *entry; + + for (entry = drv; entry != drv + n_ents; entry++) { + if (boot_device == entry->boot_device) + return entry; + } + + /* Not found */ + return NULL; +} + +static int spl_load_image(struct spl_image_info *spl_image, + struct spl_image_loader *loader) +{ + int ret; + struct spl_boot_device bootdev; + + bootdev.boot_device = loader->boot_device; + bootdev.boot_device_name = NULL; + + ret = loader->load_image(spl_image, &bootdev); +#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK + if (!ret && spl_image->dcrc_length) { + /* check data crc */ + ulong dcrc = crc32_wd(0, (unsigned char *)spl_image->dcrc_data, + spl_image->dcrc_length, CHUNKSZ_CRC32); + if (dcrc != spl_image->dcrc) { + puts("SPL: Image data CRC check failed!\n"); + ret = -EINVAL; + } + } +#endif + return ret; +} + +/** + * boot_from_devices() - Try loading a booting U-Boot from a list of devices + * + * @spl_image: Place to put the image details if successful + * @spl_boot_list: List of boot devices to try + * @count: Number of elements in spl_boot_list + * @return 0 if OK, -ve on error + */ +static int boot_from_devices(struct spl_image_info *spl_image, + u32 spl_boot_list[], int count) +{ + int i; + + for (i = 0; i < count && spl_boot_list[i] != BOOT_DEVICE_NONE; i++) { + struct spl_image_loader *loader; + + loader = spl_ll_find_loader(spl_boot_list[i]); +#if defined(CONFIG_SPL_SERIAL_SUPPORT) \ + && defined(CONFIG_SPL_LIBCOMMON_SUPPORT) \ + && !defined(CONFIG_SILENT_CONSOLE) + if (loader) + printf("Trying to boot from %s\n", loader->name); + else + puts(SPL_TPL_PROMPT "Unsupported Boot Device!\n"); +#endif + if (loader && !spl_load_image(spl_image, loader)) { + spl_image->boot_device = spl_boot_list[i]; + return 0; + } + } + + return -ENODEV; +} + +#if defined(CONFIG_SPL_FRAMEWORK_BOARD_INIT_F) +void board_init_f(ulong dummy) +{ + if (CONFIG_IS_ENABLED(OF_CONTROL)) { + int ret; + + ret = spl_early_init(); + if (ret) { + debug("spl_early_init() failed: %d\n", ret); + hang(); + } + } + + preloader_console_init(); +} +#endif + +void board_init_r(gd_t *dummy1, ulong dummy2) +{ + u32 spl_boot_list[] = { + BOOT_DEVICE_NONE, + BOOT_DEVICE_NONE, + BOOT_DEVICE_NONE, + BOOT_DEVICE_NONE, + BOOT_DEVICE_NONE, + }; + struct spl_image_info spl_image; + int ret; + + debug(">>" SPL_TPL_PROMPT "board_init_r()\n"); + + spl_set_bd(); + +#if defined(CONFIG_SYS_SPL_MALLOC_START) + mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START, + CONFIG_SYS_SPL_MALLOC_SIZE); + gd->flags |= GD_FLG_FULL_MALLOC_INIT; +#endif + if (!(gd->flags & GD_FLG_SPL_INIT)) { + if (spl_init()) + hang(); + } +#if !defined(CONFIG_PPC) && !defined(CONFIG_ARCH_MX6) + /* + * timer_init() does not exist on PPC systems. The timer is initialized + * and enabled (decrementer) in interrupt_init() here. + */ + timer_init(); +#endif + if (CONFIG_IS_ENABLED(BLOBLIST)) { + ret = bloblist_init(); + if (ret) { + debug("%s: Failed to set up bloblist: ret=%d\n", + __func__, ret); + puts(SPL_TPL_PROMPT "Cannot set up bloblist\n"); + hang(); + } + } + if (CONFIG_IS_ENABLED(HANDOFF)) { + int ret; + + ret = setup_spl_handoff(); + if (ret) { + puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n"); + hang(); + } + } + +#if CONFIG_IS_ENABLED(BOARD_INIT) + spl_board_init(); +#endif + +#if defined(CONFIG_SPL_WATCHDOG_SUPPORT) && CONFIG_IS_ENABLED(WDT) + initr_watchdog(); +#endif + + if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF) || + IS_ENABLED(CONFIG_SPL_ATF)) + dram_init_banksize(); + + bootcount_inc(); + + memset(&spl_image, '\0', sizeof(spl_image)); +#ifdef CONFIG_SYS_SPL_ARGS_ADDR + spl_image.arg = (void *)CONFIG_SYS_SPL_ARGS_ADDR; +#endif + spl_image.boot_device = BOOT_DEVICE_NONE; + board_boot_order(spl_boot_list); + + if (boot_from_devices(&spl_image, spl_boot_list, + ARRAY_SIZE(spl_boot_list))) { + puts(SPL_TPL_PROMPT "failed to boot from all boot devices\n"); + hang(); + } + + spl_perform_fixups(&spl_image); + if (CONFIG_IS_ENABLED(HANDOFF)) { + ret = write_spl_handoff(); + if (ret) + printf(SPL_TPL_PROMPT + "SPL hand-off write failed (err=%d)\n", ret); + } + if (CONFIG_IS_ENABLED(BLOBLIST)) { + ret = bloblist_finish(); + if (ret) + printf("Warning: Failed to finish bloblist (ret=%d)\n", + ret); + } + +#ifdef CONFIG_CPU_V7M + spl_image.entry_point |= 0x1; +#endif + switch (spl_image.os) { + case IH_OS_U_BOOT: + debug("Jumping to %s...\n", spl_phase_name(spl_next_phase())); + break; +#if CONFIG_IS_ENABLED(ATF) + case IH_OS_ARM_TRUSTED_FIRMWARE: + debug("Jumping to U-Boot via ARM Trusted Firmware\n"); + spl_fixup_fdt(spl_image.fdt_addr); + spl_invoke_atf(&spl_image); + break; +#endif +#if CONFIG_IS_ENABLED(OPTEE) + case IH_OS_TEE: + debug("Jumping to U-Boot via OP-TEE\n"); + spl_optee_entry(NULL, NULL, spl_image.fdt_addr, + (void *)spl_image.entry_point); + break; +#endif +#if CONFIG_IS_ENABLED(OPENSBI) + case IH_OS_OPENSBI: + debug("Jumping to U-Boot via RISC-V OpenSBI\n"); + spl_invoke_opensbi(&spl_image); + break; +#endif +#ifdef CONFIG_SPL_OS_BOOT + case IH_OS_LINUX: + debug("Jumping to Linux\n"); +#if defined(CONFIG_SYS_SPL_ARGS_ADDR) + spl_fixup_fdt((void *)CONFIG_SYS_SPL_ARGS_ADDR); +#endif + spl_board_prepare_for_linux(); + jump_to_image_linux(&spl_image); +#endif + default: + debug("Unsupported OS image.. Jumping nevertheless..\n"); + } +#if CONFIG_VAL(SYS_MALLOC_F_LEN) && !defined(CONFIG_SYS_SPL_MALLOC_SIZE) + debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr, + gd->malloc_ptr / 1024); +#endif + bootstage_mark_name(get_bootstage_id(false), "end phase"); +#ifdef CONFIG_BOOTSTAGE_STASH + ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, + CONFIG_BOOTSTAGE_STASH_SIZE); + if (ret) + debug("Failed to stash bootstage: err=%d\n", ret); +#endif + + spl_board_prepare_for_boot(); + jump_to_image_no_args(&spl_image); +} + +/* + * This requires UART clocks to be enabled. In order for this to work the + * caller must ensure that the gd pointer is valid. + */ +void preloader_console_init(void) +{ +#ifdef CONFIG_SPL_SERIAL_SUPPORT + gd->baudrate = CONFIG_BAUDRATE; + + serial_init(); /* serial communications setup */ + + gd->have_console = 1; + +#if CONFIG_IS_ENABLED(BANNER_PRINT) + puts("\nU-Boot " SPL_TPL_NAME " " PLAIN_VERSION " (" U_BOOT_DATE " - " + U_BOOT_TIME " " U_BOOT_TZ ")\n"); +#endif +#ifdef CONFIG_SPL_DISPLAY_PRINT + spl_display_print(); +#endif +#endif +} + +/** + * This function is called before the stack is changed from initial stack to + * relocated stack. It tries to dump the stack size used + */ +__weak void spl_relocate_stack_check(void) +{ +#if CONFIG_IS_ENABLED(SYS_REPORT_STACK_F_USAGE) + ulong init_sp = gd->start_addr_sp; + ulong stack_bottom = init_sp - CONFIG_VAL(SIZE_LIMIT_PROVIDE_STACK); + u8 *ptr = (u8 *)stack_bottom; + ulong i; + + for (i = 0; i < CONFIG_VAL(SIZE_LIMIT_PROVIDE_STACK); i++) { + if (*ptr != CONFIG_VAL(SYS_STACK_F_CHECK_BYTE)) + break; + ptr++; + } + printf("SPL initial stack usage: %lu bytes\n", + CONFIG_VAL(SIZE_LIMIT_PROVIDE_STACK) - i); +#endif +} + +/** + * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution + * + * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM + * for the main board_init_r() execution. This is typically because we need + * more stack space for things like the MMC sub-system. + * + * This function calculates the stack position, copies the global_data into + * place, sets the new gd (except for ARM, for which setting GD within a C + * function may not always work) and returns the new stack position. The + * caller is responsible for setting up the sp register and, in the case + * of ARM, setting up gd. + * + * All of this is done using the same layout and alignments as done in + * board_init_f_init_reserve() / board_init_f_alloc_reserve(). + * + * @return new stack location, or 0 to use the same stack + */ +ulong spl_relocate_stack_gd(void) +{ +#ifdef CONFIG_SPL_STACK_R + gd_t *new_gd; + ulong ptr = CONFIG_SPL_STACK_R_ADDR; + + if (CONFIG_IS_ENABLED(SYS_REPORT_STACK_F_USAGE)) + spl_relocate_stack_check(); + +#if defined(CONFIG_SPL_SYS_MALLOC_SIMPLE) && CONFIG_VAL(SYS_MALLOC_F_LEN) + if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) { + debug("SPL malloc() before relocation used 0x%lx bytes (%ld KB)\n", + gd->malloc_ptr, gd->malloc_ptr / 1024); + ptr -= CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN; + gd->malloc_base = ptr; + gd->malloc_limit = CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN; + gd->malloc_ptr = 0; + } +#endif + /* Get stack position: use 8-byte alignment for ABI compliance */ + ptr = CONFIG_SPL_STACK_R_ADDR - roundup(sizeof(gd_t),16); + new_gd = (gd_t *)ptr; + memcpy(new_gd, (void *)gd, sizeof(gd_t)); +#if CONFIG_IS_ENABLED(DM) + dm_fixup_for_gd_move(new_gd); +#endif +#if !defined(CONFIG_ARM) && !defined(CONFIG_RISCV) + gd = new_gd; +#endif + return ptr; +#else + return 0; +#endif +} + +#if defined(CONFIG_BOOTCOUNT_LIMIT) && \ + ((!defined(CONFIG_TPL_BUILD) && !defined(CONFIG_SPL_BOOTCOUNT_LIMIT)) || \ + (defined(CONFIG_TPL_BUILD) && !defined(CONFIG_TPL_BOOTCOUNT_LIMIT))) +void bootcount_store(ulong a) +{ +} + +ulong bootcount_load(void) +{ + return 0; +} +#endif diff --git a/roms/u-boot/common/spl/spl_atf.c b/roms/u-boot/common/spl/spl_atf.c new file mode 100644 index 000000000..e1b68dd56 --- /dev/null +++ b/roms/u-boot/common/spl/spl_atf.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Reference to the ARM TF Project, + * plat/arm/common/arm_bl2_setup.c + * Portions copyright (c) 2013-2016, ARM Limited and Contributors. All rights + * reserved. + * Copyright (C) 2016 Rockchip Electronic Co.,Ltd + * Written by Kever Yang <kever.yang@rock-chips.com> + * Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH + */ + +#include <common.h> +#include <atf_common.h> +#include <cpu_func.h> +#include <errno.h> +#include <image.h> +#include <log.h> +#include <spl.h> +#include <asm/cache.h> + +/* Holds all the structures we need for bl31 parameter passing */ +struct bl2_to_bl31_params_mem { + struct bl31_params bl31_params; + struct atf_image_info bl31_image_info; + struct atf_image_info bl32_image_info; + struct atf_image_info bl33_image_info; + struct entry_point_info bl33_ep_info; + struct entry_point_info bl32_ep_info; + struct entry_point_info bl31_ep_info; +}; + +struct bl2_to_bl31_params_mem_v2 { + struct bl_params bl_params; + struct bl_params_node bl31_params_node; + struct bl_params_node bl32_params_node; + struct bl_params_node bl33_params_node; + struct atf_image_info bl31_image_info; + struct atf_image_info bl32_image_info; + struct atf_image_info bl33_image_info; + struct entry_point_info bl33_ep_info; + struct entry_point_info bl32_ep_info; + struct entry_point_info bl31_ep_info; +}; + +struct bl31_params *bl2_plat_get_bl31_params_default(uintptr_t bl32_entry, + uintptr_t bl33_entry, + uintptr_t fdt_addr) +{ + static struct bl2_to_bl31_params_mem bl31_params_mem; + struct bl31_params *bl2_to_bl31_params; + struct entry_point_info *bl32_ep_info; + struct entry_point_info *bl33_ep_info; + + /* + * Initialise the memory for all the arguments that needs to + * be passed to BL31 + */ + memset(&bl31_params_mem, 0, sizeof(struct bl2_to_bl31_params_mem)); + + /* Assign memory for TF related information */ + bl2_to_bl31_params = &bl31_params_mem.bl31_params; + SET_PARAM_HEAD(bl2_to_bl31_params, ATF_PARAM_BL31, ATF_VERSION_1, 0); + + /* Fill BL31 related information */ + bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, + ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); + + /* Fill BL32 related information */ + bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; + bl32_ep_info = &bl31_params_mem.bl32_ep_info; + SET_PARAM_HEAD(bl32_ep_info, ATF_PARAM_EP, ATF_VERSION_1, + ATF_EP_SECURE); + + /* secure payload is optional, so set pc to 0 if absent */ + bl32_ep_info->args.arg3 = fdt_addr; + bl32_ep_info->pc = bl32_entry ? bl32_entry : 0; + bl32_ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXECPTIONS); + + bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, + ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); + + /* Fill BL33 related information */ + bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; + bl33_ep_info = &bl31_params_mem.bl33_ep_info; + SET_PARAM_HEAD(bl33_ep_info, ATF_PARAM_EP, ATF_VERSION_1, + ATF_EP_NON_SECURE); + + /* BL33 expects to receive the primary CPU MPID (through x0) */ + bl33_ep_info->args.arg0 = 0xffff & read_mpidr(); + bl33_ep_info->pc = bl33_entry; + bl33_ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXECPTIONS); + + bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, + ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); + + return bl2_to_bl31_params; +} + +__weak struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry, + uintptr_t bl33_entry, + uintptr_t fdt_addr) +{ + return bl2_plat_get_bl31_params_default(bl32_entry, bl33_entry, + fdt_addr); +} + +struct bl_params *bl2_plat_get_bl31_params_v2_default(uintptr_t bl32_entry, + uintptr_t bl33_entry, + uintptr_t fdt_addr) +{ + static struct bl2_to_bl31_params_mem_v2 bl31_params_mem; + struct bl_params *bl_params; + struct bl_params_node *bl_params_node; + + /* + * Initialise the memory for all the arguments that needs to + * be passed to BL31 + */ + memset(&bl31_params_mem, 0, sizeof(bl31_params_mem)); + + /* Assign memory for TF related information */ + bl_params = &bl31_params_mem.bl_params; + SET_PARAM_HEAD(bl_params, ATF_PARAM_BL_PARAMS, ATF_VERSION_2, 0); + bl_params->head = &bl31_params_mem.bl31_params_node; + + /* Fill BL31 related information */ + bl_params_node = &bl31_params_mem.bl31_params_node; + bl_params_node->image_id = ATF_BL31_IMAGE_ID; + bl_params_node->image_info = &bl31_params_mem.bl31_image_info; + bl_params_node->ep_info = &bl31_params_mem.bl31_ep_info; + bl_params_node->next_params_info = &bl31_params_mem.bl32_params_node; + SET_PARAM_HEAD(bl_params_node->image_info, ATF_PARAM_IMAGE_BINARY, + ATF_VERSION_2, 0); + + /* Fill BL32 related information */ + bl_params_node = &bl31_params_mem.bl32_params_node; + bl_params_node->image_id = ATF_BL32_IMAGE_ID; + bl_params_node->image_info = &bl31_params_mem.bl32_image_info; + bl_params_node->ep_info = &bl31_params_mem.bl32_ep_info; + bl_params_node->next_params_info = &bl31_params_mem.bl33_params_node; + SET_PARAM_HEAD(bl_params_node->ep_info, ATF_PARAM_EP, + ATF_VERSION_2, ATF_EP_SECURE); + + /* secure payload is optional, so set pc to 0 if absent */ + bl_params_node->ep_info->args.arg3 = fdt_addr; + bl_params_node->ep_info->pc = bl32_entry ? bl32_entry : 0; + bl_params_node->ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXECPTIONS); + SET_PARAM_HEAD(bl_params_node->image_info, ATF_PARAM_IMAGE_BINARY, + ATF_VERSION_2, 0); + + /* Fill BL33 related information */ + bl_params_node = &bl31_params_mem.bl33_params_node; + bl_params_node->image_id = ATF_BL33_IMAGE_ID; + bl_params_node->image_info = &bl31_params_mem.bl33_image_info; + bl_params_node->ep_info = &bl31_params_mem.bl33_ep_info; + bl_params_node->next_params_info = NULL; + SET_PARAM_HEAD(bl_params_node->ep_info, ATF_PARAM_EP, + ATF_VERSION_2, ATF_EP_NON_SECURE); + + /* BL33 expects to receive the primary CPU MPID (through x0) */ + bl_params_node->ep_info->args.arg0 = 0xffff & read_mpidr(); + bl_params_node->ep_info->pc = bl33_entry; + bl_params_node->ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXECPTIONS); + SET_PARAM_HEAD(bl_params_node->image_info, ATF_PARAM_IMAGE_BINARY, + ATF_VERSION_2, 0); + + return bl_params; +} + +__weak struct bl_params *bl2_plat_get_bl31_params_v2(uintptr_t bl32_entry, + uintptr_t bl33_entry, + uintptr_t fdt_addr) +{ + return bl2_plat_get_bl31_params_v2_default(bl32_entry, bl33_entry, + fdt_addr); +} + +static inline void raw_write_daif(unsigned int daif) +{ + __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory"); +} + +typedef void (*atf_entry_t)(struct bl31_params *params, void *plat_params); + +static void bl31_entry(uintptr_t bl31_entry, uintptr_t bl32_entry, + uintptr_t bl33_entry, uintptr_t fdt_addr) +{ + atf_entry_t atf_entry = (atf_entry_t)bl31_entry; + void *bl31_params; + + if (CONFIG_IS_ENABLED(ATF_LOAD_IMAGE_V2)) + bl31_params = bl2_plat_get_bl31_params_v2(bl32_entry, + bl33_entry, + fdt_addr); + else + bl31_params = bl2_plat_get_bl31_params(bl32_entry, bl33_entry, + fdt_addr); + + raw_write_daif(SPSR_EXCEPTION_MASK); + dcache_disable(); + + atf_entry(bl31_params, (void *)fdt_addr); +} + +static int spl_fit_images_find(void *blob, int os) +{ + int parent, node, ndepth = 0; + const void *data; + + if (!blob) + return -FDT_ERR_BADMAGIC; + + parent = fdt_path_offset(blob, "/fit-images"); + if (parent < 0) + return -FDT_ERR_NOTFOUND; + + for (node = fdt_next_node(blob, parent, &ndepth); + (node >= 0) && (ndepth > 0); + node = fdt_next_node(blob, node, &ndepth)) { + if (ndepth != 1) + continue; + + data = fdt_getprop(blob, node, FIT_OS_PROP, NULL); + if (!data) + continue; + + if (genimg_get_os_id(data) == os) + return node; + }; + + return -FDT_ERR_NOTFOUND; +} + +uintptr_t spl_fit_images_get_entry(void *blob, int node) +{ + ulong val; + int ret; + + ret = fit_image_get_entry(blob, node, &val); + if (ret) + ret = fit_image_get_load(blob, node, &val); + + debug("%s: entry point 0x%lx\n", __func__, val); + return val; +} + +void spl_invoke_atf(struct spl_image_info *spl_image) +{ + uintptr_t bl32_entry = 0; + uintptr_t bl33_entry = CONFIG_SYS_TEXT_BASE; + void *blob = spl_image->fdt_addr; + uintptr_t platform_param = (uintptr_t)blob; + int node; + + /* + * Find the OP-TEE binary (in /fit-images) load address or + * entry point (if different) and pass it as the BL3-2 entry + * point, this is optional. + */ + node = spl_fit_images_find(blob, IH_OS_TEE); + if (node >= 0) + bl32_entry = spl_fit_images_get_entry(blob, node); + + /* + * Find the U-Boot binary (in /fit-images) load addreess or + * entry point (if different) and pass it as the BL3-3 entry + * point. + * This will need to be extended to support Falcon mode. + */ + + node = spl_fit_images_find(blob, IH_OS_U_BOOT); + if (node >= 0) + bl33_entry = spl_fit_images_get_entry(blob, node); + + /* + * If ATF_NO_PLATFORM_PARAM is set, we override the platform + * parameter and always pass 0. This is a workaround for + * older ATF versions that have insufficiently robust (or + * overzealous) argument validation. + */ + if (CONFIG_IS_ENABLED(ATF_NO_PLATFORM_PARAM)) + platform_param = 0; + + /* + * We don't provide a BL3-2 entry yet, but this will be possible + * using similar logic. + */ + bl31_entry(spl_image->entry_point, bl32_entry, + bl33_entry, platform_param); +} diff --git a/roms/u-boot/common/spl/spl_bootrom.c b/roms/u-boot/common/spl/spl_bootrom.c new file mode 100644 index 000000000..0eefd39a5 --- /dev/null +++ b/roms/u-boot/common/spl/spl_bootrom.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Theobroma Systems Design und Consulting GmH + */ + +#include <common.h> +#include <spl.h> + +__weak int board_return_to_bootrom(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + return 0; +} + +static int spl_return_to_bootrom(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + /* + * If the board implements a way to return to its ROM (with + * the expectation that the next stage of will be booted by + * the ROM), it will implement board_return_to_bootrom() and + * should not return from it. + */ + return board_return_to_bootrom(spl_image, bootdev); +} + +SPL_LOAD_IMAGE_METHOD("BOOTROM", 0, BOOT_DEVICE_BOOTROM, spl_return_to_bootrom); diff --git a/roms/u-boot/common/spl/spl_dfu.c b/roms/u-boot/common/spl/spl_dfu.c new file mode 100644 index 000000000..5728d43ad --- /dev/null +++ b/roms/u-boot/common/spl/spl_dfu.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2016 + * Texas Instruments, <www.ti.com> + * + * Ravi B <ravibabu@ti.com> + */ +#include <common.h> +#include <env.h> +#include <spl.h> +#include <linux/compiler.h> +#include <errno.h> +#include <watchdog.h> +#include <console.h> +#include <g_dnl.h> +#include <usb.h> +#include <dfu.h> + +static int run_dfu(int usb_index, char *interface, char *devstring) +{ + int ret; + + ret = dfu_init_env_entities(interface, devstring); + if (ret) { + dfu_free_entities(); + goto exit; + } + + run_usb_dnl_gadget(usb_index, "usb_dnl_dfu"); +exit: + dfu_free_entities(); + return ret; +} + +int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr) +{ + char *str_env; + int ret; + + /* set default environment */ + env_set_default(NULL, 0); + str_env = env_get(dfu_alt_info); + if (!str_env) { + pr_err("\"%s\" env variable not defined!\n", dfu_alt_info); + return -EINVAL; + } + + ret = env_set("dfu_alt_info", str_env); + if (ret) { + pr_err("unable to set env variable \"dfu_alt_info\"!\n"); + return -EINVAL; + } + + /* invoke dfu command */ + return run_dfu(usbctrl, interface, devstr); +} diff --git a/roms/u-boot/common/spl/spl_ext.c b/roms/u-boot/common/spl/spl_ext.c new file mode 100644 index 000000000..d73f06276 --- /dev/null +++ b/roms/u-boot/common/spl/spl_ext.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <common.h> +#include <env.h> +#include <part.h> +#include <spl.h> +#include <asm/u-boot.h> +#include <ext4fs.h> +#include <errno.h> +#include <image.h> + +int spl_load_image_ext(struct spl_image_info *spl_image, + struct blk_desc *block_dev, int partition, + const char *filename) +{ + s32 err; + struct image_header *header; + loff_t filelen, actlen; + struct disk_partition part_info = {}; + + header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + + if (part_get_info(block_dev, partition, &part_info)) { + printf("spl: no partition table found\n"); + return -1; + } + + ext4fs_set_blk_dev(block_dev, &part_info); + + err = ext4fs_mount(0); + if (!err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("%s: ext4fs mount err - %d\n", __func__, err); +#endif + return -1; + } + + err = ext4fs_open(filename, &filelen); + if (err < 0) { + puts("spl: ext4fs_open failed\n"); + goto end; + } + err = ext4fs_read((char *)header, 0, sizeof(struct image_header), &actlen); + if (err < 0) { + puts("spl: ext4fs_read failed\n"); + goto end; + } + + err = spl_parse_image_header(spl_image, header); + if (err < 0) { + puts("spl: ext: failed to parse image header\n"); + goto end; + } + + err = ext4fs_read((char *)spl_image->load_addr, 0, filelen, &actlen); + +end: +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + if (err < 0) + printf("%s: error reading image %s, err - %d\n", + __func__, filename, err); +#endif + + return err < 0; +} + +#ifdef CONFIG_SPL_OS_BOOT +int spl_load_image_ext_os(struct spl_image_info *spl_image, + struct blk_desc *block_dev, int partition) +{ + int err; + __maybe_unused loff_t filelen, actlen; + struct disk_partition part_info = {}; + __maybe_unused char *file; + + if (part_get_info(block_dev, partition, &part_info)) { + printf("spl: no partition table found\n"); + return -1; + } + + ext4fs_set_blk_dev(block_dev, &part_info); + + err = ext4fs_mount(0); + if (!err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("%s: ext4fs mount err - %d\n", __func__, err); +#endif + return -1; + } +#if defined(CONFIG_SPL_ENV_SUPPORT) + file = env_get("falcon_args_file"); + if (file) { + err = ext4fs_open(file, &filelen); + if (err < 0) { + puts("spl: ext4fs_open failed\n"); + goto defaults; + } + err = ext4fs_read((void *)CONFIG_SYS_SPL_ARGS_ADDR, 0, filelen, &actlen); + if (err < 0) { + printf("spl: error reading image %s, err - %d, falling back to default\n", + file, err); + goto defaults; + } + file = env_get("falcon_image_file"); + if (file) { + err = spl_load_image_ext(spl_image, block_dev, + partition, file); + if (err != 0) { + puts("spl: falling back to default\n"); + goto defaults; + } + + return 0; + } else { + puts("spl: falcon_image_file not set in environment, falling back to default\n"); + } + } else { + puts("spl: falcon_args_file not set in environment, falling back to default\n"); + } + +defaults: +#endif + + err = ext4fs_open(CONFIG_SPL_FS_LOAD_ARGS_NAME, &filelen); + if (err < 0) + puts("spl: ext4fs_open failed\n"); + + err = ext4fs_read((void *)CONFIG_SYS_SPL_ARGS_ADDR, 0, filelen, &actlen); + if (err < 0) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("%s: error reading image %s, err - %d\n", + __func__, CONFIG_SPL_FS_LOAD_ARGS_NAME, err); +#endif + return -1; + } + + return spl_load_image_ext(spl_image, block_dev, partition, + CONFIG_SPL_FS_LOAD_KERNEL_NAME); +} +#else +int spl_load_image_ext_os(struct spl_image_info *spl_image, + struct blk_desc *block_dev, int partition) +{ + return -ENOSYS; +} +#endif diff --git a/roms/u-boot/common/spl/spl_fat.c b/roms/u-boot/common/spl/spl_fat.c new file mode 100644 index 000000000..c2eb09736 --- /dev/null +++ b/roms/u-boot/common/spl/spl_fat.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2014 + * Texas Instruments, <www.ti.com> + * + * Dan Murphy <dmurphy@ti.com> + * + * FAT Image Functions copied from spl_mmc.c + */ + +#include <common.h> +#include <env.h> +#include <log.h> +#include <spl.h> +#include <asm/u-boot.h> +#include <fat.h> +#include <errno.h> +#include <image.h> +#include <linux/libfdt.h> + +static int fat_registered; + +static int spl_register_fat_device(struct blk_desc *block_dev, int partition) +{ + int err = 0; + + if (fat_registered) + return err; + + err = fat_register_device(block_dev, partition); + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("%s: fat register err - %d\n", __func__, err); +#endif + return err; + } + + fat_registered = 1; + + return err; +} + +static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset, + ulong size, void *buf) +{ + loff_t actread; + int ret; + char *filename = (char *)load->filename; + + ret = fat_read_file(filename, buf, file_offset, size, &actread); + if (ret) + return ret; + + return actread; +} + +int spl_load_image_fat(struct spl_image_info *spl_image, + struct blk_desc *block_dev, int partition, + const char *filename) +{ + int err; + struct image_header *header; + + err = spl_register_fat_device(block_dev, partition); + if (err) + goto end; + + header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + + err = file_fat_read(filename, header, sizeof(struct image_header)); + if (err <= 0) + goto end; + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && + image_get_magic(header) == FDT_MAGIC) { + err = file_fat_read(filename, (void *)CONFIG_SYS_LOAD_ADDR, 0); + if (err <= 0) + goto end; + err = spl_parse_image_header(spl_image, + (struct image_header *)CONFIG_SYS_LOAD_ADDR); + if (err == -EAGAIN) + return err; + if (err == 0) + err = 1; + } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; + + debug("Found FIT\n"); + load.read = spl_fit_read; + load.bl_len = 1; + load.filename = (void *)filename; + load.priv = NULL; + + return spl_load_simple_fit(spl_image, &load, 0, header); + } else { + err = spl_parse_image_header(spl_image, header); + if (err) + goto end; + + err = file_fat_read(filename, + (u8 *)(uintptr_t)spl_image->load_addr, 0); + } + +end: +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + if (err <= 0) + printf("%s: error reading image %s, err - %d\n", + __func__, filename, err); +#endif + + return (err <= 0); +} + +#ifdef CONFIG_SPL_OS_BOOT +int spl_load_image_fat_os(struct spl_image_info *spl_image, + struct blk_desc *block_dev, int partition) +{ + int err; + __maybe_unused char *file; + + err = spl_register_fat_device(block_dev, partition); + if (err) + return err; + +#if defined(CONFIG_SPL_ENV_SUPPORT) && defined(CONFIG_SPL_OS_BOOT) + file = env_get("falcon_args_file"); + if (file) { + err = file_fat_read(file, (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0); + if (err <= 0) { + printf("spl: error reading image %s, err - %d, falling back to default\n", + file, err); + goto defaults; + } + file = env_get("falcon_image_file"); + if (file) { + err = spl_load_image_fat(spl_image, block_dev, + partition, file); + if (err != 0) { + puts("spl: falling back to default\n"); + goto defaults; + } + + return 0; + } else + puts("spl: falcon_image_file not set in environment, falling back to default\n"); + } else + puts("spl: falcon_args_file not set in environment, falling back to default\n"); + +defaults: +#endif + + err = file_fat_read(CONFIG_SPL_FS_LOAD_ARGS_NAME, + (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0); + if (err <= 0) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("%s: error reading image %s, err - %d\n", + __func__, CONFIG_SPL_FS_LOAD_ARGS_NAME, err); +#endif + return -1; + } + + return spl_load_image_fat(spl_image, block_dev, partition, + CONFIG_SPL_FS_LOAD_KERNEL_NAME); +} +#else +int spl_load_image_fat_os(struct spl_image_info *spl_image, + struct blk_desc *block_dev, int partition) +{ + return -ENOSYS; +} +#endif diff --git a/roms/u-boot/common/spl/spl_fit.c b/roms/u-boot/common/spl/spl_fit.c new file mode 100644 index 000000000..caddf5119 --- /dev/null +++ b/roms/u-boot/common/spl/spl_fit.c @@ -0,0 +1,810 @@ +// 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 <fpga.h> +#include <gzip.h> +#include <image.h> +#include <log.h> +#include <malloc.h> +#include <mapmem.h> +#include <spl.h> +#include <sysinfo.h> +#include <asm/cache.h> +#include <asm/global_data.h> +#include <linux/libfdt.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ +#define CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ (64 * 1024) +#endif + +#ifndef CONFIG_SYS_BOOTM_LEN +#define CONFIG_SYS_BOOTM_LEN (64 << 20) +#endif + +struct spl_fit_info { + const void *fit; /* Pointer to a valid FIT blob */ + size_t ext_data_offset; /* Offset to FIT external data (end of FIT) */ + int images_node; /* FDT offset to "/images" node */ + int conf_node; /* FDT offset to selected configuration node */ +}; + +__weak void board_spl_fit_post_load(const void *fit) +{ +} + +__weak ulong board_spl_fit_size_align(ulong size) +{ + return size; +} + +static int find_node_from_desc(const void *fit, int node, const char *str) +{ + int child; + + if (node < 0) + return -EINVAL; + + /* iterate the FIT nodes and find a matching description */ + for (child = fdt_first_subnode(fit, node); child >= 0; + child = fdt_next_subnode(fit, child)) { + int len; + const char *desc = fdt_getprop(fit, child, "description", &len); + + if (!desc) + continue; + + if (!strcmp(desc, str)) + return child; + } + + return -ENOENT; +} + +/** + * spl_fit_get_image_name(): By using the matching configuration subnode, + * retrieve the name of an image, specified by a property name and an index + * into that. + * @fit: Pointer to the FDT blob. + * @images: Offset of the /images subnode. + * @type: Name of the property within the configuration subnode. + * @index: Index into the list of strings in this property. + * @outname: Name of the image + * + * Return: 0 on success, or a negative error number + */ +static int spl_fit_get_image_name(const struct spl_fit_info *ctx, + const char *type, int index, + const char **outname) +{ + struct udevice *sysinfo; + const char *name, *str; + __maybe_unused int node; + int len, i; + bool found = true; + + name = fdt_getprop(ctx->fit, ctx->conf_node, type, &len); + if (!name) { + debug("cannot find property '%s': %d\n", type, len); + return -EINVAL; + } + + str = name; + for (i = 0; i < index; i++) { + str = strchr(str, '\0') + 1; + if (!str || (str - name >= len)) { + found = false; + break; + } + } + + if (!found && CONFIG_IS_ENABLED(SYSINFO) && !sysinfo_get(&sysinfo)) { + int rc; + /* + * no string in the property for this index. Check if the + * sysinfo-level code can supply one. + */ + rc = sysinfo_detect(sysinfo); + if (rc) + return rc; + + rc = sysinfo_get_fit_loadable(sysinfo, index - i - 1, type, + &str); + if (rc && rc != -ENOENT) + return rc; + + if (!rc) { + /* + * The sysinfo provided a name for a loadable. + * Try to match it against the description properties + * first. If no matching node is found, use it as a + * node name. + */ + int node; + int images = fdt_path_offset(ctx->fit, FIT_IMAGES_PATH); + + node = find_node_from_desc(ctx->fit, images, str); + if (node > 0) + str = fdt_get_name(ctx->fit, node, NULL); + + found = true; + } + } + + if (!found) { + debug("no string for index %d\n", index); + return -E2BIG; + } + + *outname = str; + return 0; +} + +/** + * spl_fit_get_image_node(): By using the matching configuration subnode, + * retrieve the name of an image, specified by a property name and an index + * into that. + * @fit: Pointer to the FDT blob. + * @images: Offset of the /images subnode. + * @type: Name of the property within the configuration subnode. + * @index: Index into the list of strings in this property. + * + * Return: the node offset of the respective image node or a negative + * error number. + */ +static int spl_fit_get_image_node(const struct spl_fit_info *ctx, + const char *type, int index) +{ + const char *str; + int err; + int node; + + err = spl_fit_get_image_name(ctx, type, index, &str); + if (err) + return err; + + debug("%s: '%s'\n", type, str); + + node = fdt_subnode_offset(ctx->fit, ctx->images_node, str); + if (node < 0) { + pr_err("cannot find image node '%s': %d\n", str, node); + return -EINVAL; + } + + return node; +} + +static int get_aligned_image_offset(struct spl_load_info *info, int offset) +{ + /* + * If it is a FS read, get the first address before offset which is + * aligned to ARCH_DMA_MINALIGN. If it is raw read return the + * block number to which offset belongs. + */ + if (info->filename) + return offset & ~(ARCH_DMA_MINALIGN - 1); + + return offset / info->bl_len; +} + +static int get_aligned_image_overhead(struct spl_load_info *info, int offset) +{ + /* + * If it is a FS read, get the difference between the offset and + * the first address before offset which is aligned to + * ARCH_DMA_MINALIGN. If it is raw read return the offset within the + * block. + */ + if (info->filename) + return offset & (ARCH_DMA_MINALIGN - 1); + + return offset % info->bl_len; +} + +static int get_aligned_image_size(struct spl_load_info *info, int data_size, + int offset) +{ + data_size = data_size + get_aligned_image_overhead(info, offset); + + if (info->filename) + return data_size; + + return (data_size + info->bl_len - 1) / info->bl_len; +} + +/** + * spl_load_fit_image(): load the image described in a certain FIT node + * @info: points to information about the device to load data from + * @sector: the start sector of the FIT image on the device + * @ctx: points to the FIT context structure + * @node: offset of the DT node describing the image to load (relative + * to @fit) + * @image_info: will be filled with information about the loaded image + * If the FIT node does not contain a "load" (address) property, + * the image gets loaded to the address pointed to by the + * load_addr member in this struct, if load_addr is not 0 + * + * Return: 0 on success or a negative error number. + */ +static int spl_load_fit_image(struct spl_load_info *info, ulong sector, + const struct spl_fit_info *ctx, int node, + struct spl_image_info *image_info) +{ + int offset; + size_t length; + int len; + ulong size; + ulong load_addr; + void *load_ptr; + void *src; + ulong overhead; + int nr_sectors; + uint8_t image_comp = -1, type = -1; + const void *data; + const void *fit = ctx->fit; + bool external_data = false; + + if (IS_ENABLED(CONFIG_SPL_FPGA) || + (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP))) { + if (fit_image_get_type(fit, node, &type)) + puts("Cannot get image type.\n"); + else + debug("%s ", genimg_get_type_name(type)); + } + + if (IS_ENABLED(CONFIG_SPL_GZIP)) { + fit_image_get_comp(fit, node, &image_comp); + debug("%s ", genimg_get_comp_name(image_comp)); + } + + if (fit_image_get_load(fit, node, &load_addr)) { + if (!image_info->load_addr) { + printf("Can't load %s: No load address and no buffer\n", + fit_get_name(fit, node, NULL)); + return -ENOBUFS; + } + load_addr = image_info->load_addr; + } + + if (!fit_image_get_data_position(fit, node, &offset)) { + external_data = true; + } else if (!fit_image_get_data_offset(fit, node, &offset)) { + offset += ctx->ext_data_offset; + external_data = true; + } + + if (external_data) { + void *src_ptr; + + /* External data */ + if (fit_image_get_data_size(fit, node, &len)) + return -ENOENT; + + src_ptr = map_sysmem(ALIGN(load_addr, ARCH_DMA_MINALIGN), len); + length = len; + + overhead = get_aligned_image_overhead(info, offset); + nr_sectors = get_aligned_image_size(info, length, offset); + + if (info->read(info, + sector + get_aligned_image_offset(info, offset), + nr_sectors, src_ptr) != nr_sectors) + return -EIO; + + debug("External data: dst=%p, offset=%x, size=%lx\n", + src_ptr, offset, (unsigned long)length); + src = src_ptr + overhead; + } else { + /* Embedded data */ + if (fit_image_get_data(fit, node, &data, &length)) { + puts("Cannot get image data/size\n"); + return -ENOENT; + } + debug("Embedded data: dst=%lx, size=%lx\n", load_addr, + (unsigned long)length); + src = (void *)data; /* cast away const */ + } + + if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) { + printf("## Checking hash(es) for Image %s ... ", + fit_get_name(fit, node, NULL)); + if (!fit_image_verify_with_data(fit, node, src, length)) + return -EPERM; + puts("OK\n"); + } + + if (CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS)) + board_fit_image_post_process(&src, &length); + + load_ptr = map_sysmem(load_addr, length); + if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) { + size = length; + if (gunzip(load_ptr, CONFIG_SYS_BOOTM_LEN, src, &size)) { + puts("Uncompressing error\n"); + return -EIO; + } + length = size; + } else { + memcpy(load_ptr, src, length); + } + + if (image_info) { + ulong entry_point; + + image_info->load_addr = load_addr; + image_info->size = length; + + if (!fit_image_get_entry(fit, node, &entry_point)) + image_info->entry_point = entry_point; + else + image_info->entry_point = FDT_ERROR; + } + + return 0; +} + +static bool os_takes_devicetree(uint8_t os) +{ + switch (os) { + case IH_OS_U_BOOT: + return true; + case IH_OS_LINUX: + return IS_ENABLED(CONFIG_SPL_OS_BOOT); + default: + return false; + } +} + +static int spl_fit_append_fdt(struct spl_image_info *spl_image, + struct spl_load_info *info, ulong sector, + const struct spl_fit_info *ctx) +{ + struct spl_image_info image_info; + int node, ret = 0, index = 0; + + /* + * Use the address following the image as target address for the + * device tree. + */ + image_info.load_addr = spl_image->load_addr + spl_image->size; + + /* Figure out which device tree the board wants to use */ + node = spl_fit_get_image_node(ctx, FIT_FDT_PROP, index++); + if (node < 0) { + debug("%s: cannot find FDT node\n", __func__); + + /* + * U-Boot did not find a device tree inside the FIT image. Use + * the U-Boot device tree instead. + */ + if (gd->fdt_blob) + memcpy((void *)image_info.load_addr, gd->fdt_blob, + fdt_totalsize(gd->fdt_blob)); + else + return node; + } else { + ret = spl_load_fit_image(info, sector, ctx, node, + &image_info); + if (ret < 0) + return ret; + } + + /* Make the load-address of the FDT available for the SPL framework */ + spl_image->fdt_addr = map_sysmem(image_info.load_addr, 0); + if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY)) + return 0; + + if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) { + void *tmpbuffer = NULL; + + for (; ; index++) { + node = spl_fit_get_image_node(ctx, FIT_FDT_PROP, index); + if (node == -E2BIG) { + debug("%s: No additional FDT node\n", __func__); + break; + } else if (node < 0) { + debug("%s: unable to find FDT node %d\n", + __func__, index); + continue; + } + + if (!tmpbuffer) { + /* + * allocate memory to store the DT overlay + * before it is applied. It may not be used + * depending on how the overlay is stored, so + * don't fail yet if the allocation failed. + */ + tmpbuffer = malloc(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ); + if (!tmpbuffer) + debug("%s: unable to allocate space for overlays\n", + __func__); + } + image_info.load_addr = (ulong)tmpbuffer; + ret = spl_load_fit_image(info, sector, ctx, + node, &image_info); + if (ret < 0) + break; + + /* Make room in FDT for changes from the overlay */ + ret = fdt_increase_size(spl_image->fdt_addr, + image_info.size); + if (ret < 0) + break; + + ret = fdt_overlay_apply_verbose(spl_image->fdt_addr, + (void *)image_info.load_addr); + if (ret) { + pr_err("failed to apply DT overlay %s\n", + fit_get_name(ctx->fit, node, NULL)); + break; + } + + debug("%s: DT overlay %s applied\n", __func__, + fit_get_name(ctx->fit, node, NULL)); + } + free(tmpbuffer); + if (ret) + return ret; + } + /* Try to make space, so we can inject details on the loadables */ + ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192); + if (ret < 0) + return ret; + + return ret; +} + +static int spl_fit_record_loadable(const struct spl_fit_info *ctx, int index, + void *blob, struct spl_image_info *image) +{ + int ret = 0; + const char *name; + int node; + + if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY)) + return 0; + + ret = spl_fit_get_image_name(ctx, "loadables", index, &name); + if (ret < 0) + return ret; + + node = spl_fit_get_image_node(ctx, "loadables", index); + + ret = fdt_record_loadable(blob, index, name, image->load_addr, + image->size, image->entry_point, + fdt_getprop(ctx->fit, node, "type", NULL), + fdt_getprop(ctx->fit, node, "os", NULL)); + return ret; +} + +static int spl_fit_image_is_fpga(const void *fit, int node) +{ + const char *type; + + if (!IS_ENABLED(CONFIG_SPL_FPGA)) + return 0; + + type = fdt_getprop(fit, node, FIT_TYPE_PROP, NULL); + if (!type) + return 0; + + return !strcmp(type, "fpga"); +} + +static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os) +{ + if (!CONFIG_IS_ENABLED(FIT_IMAGE_TINY) || CONFIG_IS_ENABLED(OS_BOOT)) + return fit_image_get_os(fit, noffset, os); + + const char *name = fdt_getprop(fit, noffset, FIT_OS_PROP, NULL); + if (!name) + return -ENOENT; + + /* + * We don't care what the type of the image actually is, + * only whether or not it is U-Boot. This saves some + * space by omitting the large table of OS types. + */ + if (!strcmp(name, "u-boot")) + *os = IH_OS_U_BOOT; + else + *os = IH_OS_INVALID; + + return 0; +} + +/* + * The purpose of the FIT load buffer is to provide a memory location that is + * independent of the load address of any FIT component. + */ +static void *spl_get_fit_load_buffer(size_t size) +{ + void *buf; + + buf = malloc(size); + if (!buf) { + pr_err("Could not get FIT buffer of %lu bytes\n", (ulong)size); + pr_err("\tcheck CONFIG_SYS_SPL_MALLOC_SIZE\n"); + buf = spl_get_load_buffer(0, size); + } + return buf; +} + +/* + * Weak default function to allow customizing SPL fit loading for load-only + * use cases by allowing to skip the parsing/processing of the FIT contents + * (so that this can be done separately in a more customized fashion) + */ +__weak bool spl_load_simple_fit_skip_processing(void) +{ + return false; +} + +static void warn_deprecated(const char *msg) +{ + printf("DEPRECATED: %s\n", msg); + printf("\tSee doc/uImage.FIT/source_file_format.txt\n"); +} + +static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node, + struct spl_image_info *fpga_image) +{ + const char *compatible; + int ret; + + debug("FPGA bitstream at: %x, size: %x\n", + (u32)fpga_image->load_addr, fpga_image->size); + + compatible = fdt_getprop(ctx->fit, node, "compatible", NULL); + if (!compatible) + warn_deprecated("'fpga' image without 'compatible' property"); + else if (strcmp(compatible, "u-boot,fpga-legacy")) + printf("Ignoring compatible = %s property\n", compatible); + + ret = fpga_load(0, (void *)fpga_image->load_addr, fpga_image->size, + BIT_FULL); + if (ret) { + printf("%s: Cannot load the image to the FPGA\n", __func__); + return ret; + } + + puts("FPGA image loaded from FIT\n"); + + return 0; +} + +static int spl_fit_load_fpga(struct spl_fit_info *ctx, + struct spl_load_info *info, ulong sector) +{ + int node, ret; + + struct spl_image_info fpga_image = { + .load_addr = 0, + }; + + node = spl_fit_get_image_node(ctx, "fpga", 0); + if (node < 0) + return node; + + warn_deprecated("'fpga' property in config node. Use 'loadables'"); + + /* Load the image and set up the fpga_image structure */ + ret = spl_load_fit_image(info, sector, ctx, node, &fpga_image); + if (ret) { + printf("%s: Cannot load the FPGA: %i\n", __func__, ret); + return ret; + } + + return spl_fit_upload_fpga(ctx, node, &fpga_image); +} + +static int spl_simple_fit_read(struct spl_fit_info *ctx, + struct spl_load_info *info, ulong sector, + const void *fit_header) +{ + unsigned long count, size; + int sectors; + void *buf; + + /* + * For FIT with external data, figure out where the external images + * start. This is the base for the data-offset properties in each + * image. + */ + size = ALIGN(fdt_totalsize(fit_header), 4); + size = board_spl_fit_size_align(size); + ctx->ext_data_offset = ALIGN(size, 4); + + /* + * So far we only have one block of data from the FIT. Read the entire + * thing, including that first block. + * + * For FIT with data embedded, data is loaded as part of FIT image. + * For FIT with external data, data is not loaded in this step. + */ + sectors = get_aligned_image_size(info, size, 0); + buf = spl_get_fit_load_buffer(sectors * info->bl_len); + + count = info->read(info, sector, sectors, buf); + ctx->fit = buf; + debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu, size=0x%lx\n", + sector, sectors, buf, count, size); + + return (count == 0) ? -EIO : 0; +} + +static int spl_simple_fit_parse(struct spl_fit_info *ctx) +{ + /* Find the correct subnode under "/configurations" */ + ctx->conf_node = fit_find_config_node(ctx->fit); + if (ctx->conf_node < 0) + return -EINVAL; + + if (IS_ENABLED(CONFIG_SPL_FIT_SIGNATURE)) { + printf("## Checking hash(es) for config %s ... ", + fit_get_name(ctx->fit, ctx->conf_node, NULL)); + if (fit_config_verify(ctx->fit, ctx->conf_node)) + return -EPERM; + puts("OK\n"); + } + + /* find the node holding the images information */ + ctx->images_node = fdt_path_offset(ctx->fit, FIT_IMAGES_PATH); + if (ctx->images_node < 0) { + debug("%s: Cannot find /images node: %d\n", __func__, + ctx->images_node); + return -EINVAL; + } + + return 0; +} + +int spl_load_simple_fit(struct spl_image_info *spl_image, + struct spl_load_info *info, ulong sector, void *fit) +{ + struct spl_image_info image_info; + struct spl_fit_info ctx; + int node = -1; + int ret; + int index = 0; + int firmware_node; + + ret = spl_simple_fit_read(&ctx, info, sector, fit); + if (ret < 0) + return ret; + + /* skip further processing if requested to enable load-only use cases */ + if (spl_load_simple_fit_skip_processing()) + return 0; + + ret = spl_simple_fit_parse(&ctx); + if (ret < 0) + return ret; + + if (IS_ENABLED(CONFIG_SPL_FPGA)) + spl_fit_load_fpga(&ctx, info, sector); + + /* + * Find the U-Boot image using the following search order: + * - start at 'firmware' (e.g. an ARM Trusted Firmware) + * - fall back 'kernel' (e.g. a Falcon-mode OS boot + * - fall back to using the first 'loadables' entry + */ + if (node < 0) + node = spl_fit_get_image_node(&ctx, FIT_FIRMWARE_PROP, 0); + + if (node < 0 && IS_ENABLED(CONFIG_SPL_OS_BOOT)) + node = spl_fit_get_image_node(&ctx, FIT_KERNEL_PROP, 0); + + if (node < 0) { + debug("could not find firmware image, trying loadables...\n"); + node = spl_fit_get_image_node(&ctx, "loadables", 0); + /* + * If we pick the U-Boot image from "loadables", start at + * the second image when later loading additional images. + */ + index = 1; + } + if (node < 0) { + debug("%s: Cannot find u-boot image node: %d\n", + __func__, node); + return -1; + } + + /* Load the image and set up the spl_image structure */ + ret = spl_load_fit_image(info, sector, &ctx, node, spl_image); + if (ret) + return ret; + + /* + * For backward compatibility, we treat the first node that is + * as a U-Boot image, if no OS-type has been declared. + */ + if (!spl_fit_image_get_os(ctx.fit, node, &spl_image->os)) + debug("Image OS is %s\n", genimg_get_os_name(spl_image->os)); + else if (!IS_ENABLED(CONFIG_SPL_OS_BOOT)) + spl_image->os = IH_OS_U_BOOT; + + /* + * Booting a next-stage U-Boot may require us to append the FDT. + * We allow this to fail, as the U-Boot image might embed its FDT. + */ + if (os_takes_devicetree(spl_image->os)) { + ret = spl_fit_append_fdt(spl_image, info, sector, &ctx); + if (ret < 0 && spl_image->os != IH_OS_U_BOOT) + return ret; + } + + firmware_node = node; + /* Now check if there are more images for us to load */ + for (; ; index++) { + uint8_t os_type = IH_OS_INVALID; + + node = spl_fit_get_image_node(&ctx, "loadables", index); + if (node < 0) + break; + + /* + * if the firmware is also a loadable, skip it because + * it already has been loaded. This is typically the case with + * u-boot.img generated by mkimage. + */ + if (firmware_node == node) + continue; + + image_info.load_addr = 0; + ret = spl_load_fit_image(info, sector, &ctx, node, &image_info); + if (ret < 0) { + printf("%s: can't load image loadables index %d (ret = %d)\n", + __func__, index, ret); + return ret; + } + + if (spl_fit_image_is_fpga(ctx.fit, node)) + spl_fit_upload_fpga(&ctx, node, &image_info); + + if (!spl_fit_image_get_os(ctx.fit, node, &os_type)) + debug("Loadable is %s\n", genimg_get_os_name(os_type)); + + if (os_takes_devicetree(os_type)) { + spl_fit_append_fdt(&image_info, info, sector, &ctx); + spl_image->fdt_addr = image_info.fdt_addr; + } + + /* + * If the "firmware" image did not provide an entry point, + * use the first valid entry point from the loadables. + */ + if (spl_image->entry_point == FDT_ERROR && + image_info.entry_point != FDT_ERROR) + spl_image->entry_point = image_info.entry_point; + + /* Record our loadables into the FDT */ + if (spl_image->fdt_addr) + spl_fit_record_loadable(&ctx, index, + spl_image->fdt_addr, + &image_info); + } + + /* + * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's + * Makefile will set it to 0 and it will end up as the entry point + * here. What it actually means is: use the load address. + */ + if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0) + spl_image->entry_point = spl_image->load_addr; + + spl_image->flags |= SPL_FIT_FOUND; + + if (IS_ENABLED(CONFIG_IMX_HAB)) + board_spl_fit_post_load(ctx.fit); + + return 0; +} diff --git a/roms/u-boot/common/spl/spl_legacy.c b/roms/u-boot/common/spl/spl_legacy.c new file mode 100644 index 000000000..82d032680 --- /dev/null +++ b/roms/u-boot/common/spl/spl_legacy.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Stefan Roese <sr@denx.de> + */ + +#include <common.h> +#include <image.h> +#include <log.h> +#include <malloc.h> +#include <spl.h> + +#include <lzma/LzmaTypes.h> +#include <lzma/LzmaDec.h> +#include <lzma/LzmaTools.h> + +#define LZMA_LEN (1 << 20) + +int spl_parse_legacy_header(struct spl_image_info *spl_image, + const struct image_header *header) +{ + u32 header_size = sizeof(struct image_header); + + /* check uImage header CRC */ + if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK) && + !image_check_hcrc(header)) { + puts("SPL: Image header CRC check failed!\n"); + return -EINVAL; + } + + if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) { + /* + * On some system (e.g. powerpc), the load-address and + * entry-point is located at address 0. We can't load + * to 0-0x40. So skip header in this case. + */ + spl_image->load_addr = image_get_load(header); + spl_image->entry_point = image_get_ep(header); + spl_image->size = image_get_data_size(header); + } else { + spl_image->entry_point = image_get_ep(header); + /* Load including the header */ + spl_image->load_addr = image_get_load(header) - + header_size; + spl_image->size = image_get_data_size(header) + + header_size; + } + +#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK + /* store uImage data length and CRC to check later */ + spl_image->dcrc_data = image_get_load(header); + spl_image->dcrc_length = image_get_data_size(header); + spl_image->dcrc = image_get_dcrc(header); +#endif + + spl_image->os = image_get_os(header); + spl_image->name = image_get_name(header); + debug(SPL_TPL_PROMPT + "payload image: %32s load addr: 0x%lx size: %d\n", + spl_image->name, spl_image->load_addr, spl_image->size); + + return 0; +} + +/* + * This function is added explicitly to avoid code size increase, when + * no compression method is enabled. The compiler will optimize the + * following switch/case statement in spl_load_legacy_img() away due to + * Dead Code Elimination. + */ +static inline int spl_image_get_comp(const struct image_header *hdr) +{ + if (IS_ENABLED(CONFIG_SPL_LZMA)) + return image_get_comp(hdr); + + return IH_COMP_NONE; +} + +int spl_load_legacy_img(struct spl_image_info *spl_image, + struct spl_load_info *load, ulong header) +{ + __maybe_unused SizeT lzma_len; + __maybe_unused void *src; + struct image_header hdr; + ulong dataptr; + int ret; + + /* Read header into local struct */ + load->read(load, header, sizeof(hdr), &hdr); + + ret = spl_parse_image_header(spl_image, &hdr); + if (ret) + return ret; + + dataptr = header + sizeof(hdr); + + /* Read image */ + switch (spl_image_get_comp(&hdr)) { + case IH_COMP_NONE: + load->read(load, dataptr, spl_image->size, + (void *)(unsigned long)spl_image->load_addr); + break; + + case IH_COMP_LZMA: + lzma_len = LZMA_LEN; + + debug("LZMA: Decompressing %08lx to %08lx\n", + dataptr, spl_image->load_addr); + src = malloc(spl_image->size); + if (!src) { + printf("Unable to allocate %d bytes for LZMA\n", + spl_image->size); + return -ENOMEM; + } + + load->read(load, dataptr, spl_image->size, src); + ret = lzmaBuffToBuffDecompress((void *)spl_image->load_addr, + &lzma_len, src, spl_image->size); + if (ret) { + printf("LZMA decompression error: %d\n", ret); + return ret; + } + + spl_image->size = lzma_len; + break; + + default: + debug("Compression method %s is not supported\n", + genimg_get_comp_short_name(image_get_comp(&hdr))); + return -EINVAL; + } + + return 0; +} diff --git a/roms/u-boot/common/spl/spl_mmc.c b/roms/u-boot/common/spl/spl_mmc.c new file mode 100644 index 000000000..add2785b4 --- /dev/null +++ b/roms/u-boot/common/spl/spl_mmc.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> + */ +#include <common.h> +#include <dm.h> +#include <log.h> +#include <part.h> +#include <spl.h> +#include <linux/compiler.h> +#include <errno.h> +#include <asm/u-boot.h> +#include <errno.h> +#include <mmc.h> +#include <image.h> + +static int mmc_load_legacy(struct spl_image_info *spl_image, struct mmc *mmc, + ulong sector, struct image_header *header) +{ + u32 image_size_sectors; + unsigned long count; + int ret; + + ret = spl_parse_image_header(spl_image, header); + if (ret) + return ret; + + /* convert size to sectors - round up */ + image_size_sectors = (spl_image->size + mmc->read_bl_len - 1) / + mmc->read_bl_len; + + /* Read the header too to avoid extra memcpy */ + count = blk_dread(mmc_get_blk_desc(mmc), sector, image_size_sectors, + (void *)(ulong)spl_image->load_addr); + debug("read %x sectors to %lx\n", image_size_sectors, + spl_image->load_addr); + if (count != image_size_sectors) + return -EIO; + + return 0; +} + +static ulong h_spl_load_read(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + struct mmc *mmc = load->dev; + + return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf); +} + +static __maybe_unused unsigned long spl_mmc_raw_uboot_offset(int part) +{ +#if IS_ENABLED(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR) + if (part == 0) + return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET; +#endif + + return 0; +} + +static __maybe_unused +int mmc_load_image_raw_sector(struct spl_image_info *spl_image, + struct mmc *mmc, unsigned long sector) +{ + unsigned long count; + struct image_header *header; + struct blk_desc *bd = mmc_get_blk_desc(mmc); + int ret = 0; + + header = spl_get_load_buffer(-sizeof(*header), bd->blksz); + + /* read image header to find the image size & load address */ + count = blk_dread(bd, sector, 1, header); + debug("hdr read sector %lx, count=%lu\n", sector, count); + if (count == 0) { + ret = -EIO; + goto end; + } + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; + + debug("Found FIT\n"); + load.dev = mmc; + load.priv = NULL; + load.filename = NULL; + load.bl_len = mmc->read_bl_len; + load.read = h_spl_load_read; + ret = spl_load_simple_fit(spl_image, &load, sector, header); + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + struct spl_load_info load; + + load.dev = mmc; + load.priv = NULL; + load.filename = NULL; + load.bl_len = mmc->read_bl_len; + load.read = h_spl_load_read; + + ret = spl_load_imx_container(spl_image, &load, sector); + } else { + ret = mmc_load_legacy(spl_image, mmc, sector, header); + } + +end: + if (ret) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + puts("mmc_load_image_raw_sector: mmc block read error\n"); +#endif + return -1; + } + + return 0; +} + +static int spl_mmc_get_device_index(u32 boot_device) +{ + switch (boot_device) { + case BOOT_DEVICE_MMC1: + return 0; + case BOOT_DEVICE_MMC2: + case BOOT_DEVICE_MMC2_2: + return 1; + } + +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: unsupported mmc boot device.\n"); +#endif + + return -ENODEV; +} + +static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device) +{ + int err, mmc_dev; + + mmc_dev = spl_mmc_get_device_index(boot_device); + if (mmc_dev < 0) + return mmc_dev; + +#if CONFIG_IS_ENABLED(DM_MMC) + err = mmc_init_device(mmc_dev); +#else + err = mmc_initialize(NULL); +#endif /* DM_MMC */ + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: could not initialize mmc. error: %d\n", err); +#endif + return err; + } + *mmcp = find_mmc_device(mmc_dev); + err = *mmcp ? 0 : -ENODEV; + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: could not find mmc device %d. error: %d\n", + mmc_dev, err); +#endif + return err; + } + + return 0; +} + +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION +static int mmc_load_image_raw_partition(struct spl_image_info *spl_image, + struct mmc *mmc, int partition, + unsigned long sector) +{ + struct disk_partition info; + int err; + +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE + int type_part; + /* Only support MBR so DOS_ENTRY_NUMBERS */ + for (type_part = 1; type_part <= DOS_ENTRY_NUMBERS; type_part++) { + err = part_get_info(mmc_get_blk_desc(mmc), type_part, &info); + if (err) + continue; + if (info.sys_ind == + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_TYPE) { + partition = type_part; + break; + } + } +#endif + + err = part_get_info(mmc_get_blk_desc(mmc), partition, &info); + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + puts("spl: partition error\n"); +#endif + return -1; + } + +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR + return mmc_load_image_raw_sector(spl_image, mmc, info.start + sector); +#else + return mmc_load_image_raw_sector(spl_image, mmc, info.start); +#endif +} +#endif + +#ifdef CONFIG_SPL_OS_BOOT +static int mmc_load_image_raw_os(struct spl_image_info *spl_image, + struct mmc *mmc) +{ + int ret; + +#if defined(CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR) + unsigned long count; + + count = blk_dread(mmc_get_blk_desc(mmc), + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, + (void *) CONFIG_SYS_SPL_ARGS_ADDR); + if (count != CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + puts("mmc_load_image_raw_os: mmc block read error\n"); +#endif + return -1; + } +#endif /* CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR */ + + ret = mmc_load_image_raw_sector(spl_image, mmc, + CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); + if (ret) + return ret; + + if (spl_image->os != IH_OS_LINUX) { + puts("Expected Linux image is not found. Trying to start U-boot\n"); + return -ENOENT; + } + + return 0; +} +#else +int spl_start_uboot(void) +{ + return 1; +} +static int mmc_load_image_raw_os(struct spl_image_info *spl_image, + struct mmc *mmc) +{ + return -ENOSYS; +} +#endif + +#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION +static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc, + const char *filename) +{ + int err = -ENOSYS; + +#ifdef CONFIG_SPL_FS_FAT + if (!spl_start_uboot()) { + err = spl_load_image_fat_os(spl_image, mmc_get_blk_desc(mmc), + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); + if (!err) + return err; + } +#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME + err = spl_load_image_fat(spl_image, mmc_get_blk_desc(mmc), + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + filename); + if (!err) + return err; +#endif +#endif +#ifdef CONFIG_SPL_FS_EXT4 + if (!spl_start_uboot()) { + err = spl_load_image_ext_os(spl_image, mmc_get_blk_desc(mmc), + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); + if (!err) + return err; + } +#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME + err = spl_load_image_ext(spl_image, mmc_get_blk_desc(mmc), + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + filename); + if (!err) + return err; +#endif +#endif + +#if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4) + err = -ENOENT; +#endif + + return err; +} +#else +static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc, + const char *filename) +{ + return -ENOSYS; +} +#endif + +u32 __weak spl_mmc_boot_mode(const u32 boot_device) +{ +#if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4) + return MMCSD_MODE_FS; +#elif defined(CONFIG_SUPPORT_EMMC_BOOT) + return MMCSD_MODE_EMMCBOOT; +#else + return MMCSD_MODE_RAW; +#endif +} + +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION +int __weak spl_mmc_boot_partition(const u32 boot_device) +{ + return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION; +} +#endif + +unsigned long __weak spl_mmc_get_uboot_raw_sector(struct mmc *mmc, + unsigned long raw_sect) +{ + return raw_sect; +} + +int spl_mmc_load(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev, + const char *filename, + int raw_part, + unsigned long raw_sect) +{ + static struct mmc *mmc; + u32 boot_mode; + int err = 0; + __maybe_unused int part = 0; + + /* Perform peripheral init only once */ + if (!mmc) { + err = spl_mmc_find_device(&mmc, bootdev->boot_device); + if (err) + return err; + + err = mmc_init(mmc); + if (err) { + mmc = NULL; +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: mmc init failed with error: %d\n", err); +#endif + return err; + } + } + + boot_mode = spl_mmc_boot_mode(bootdev->boot_device); + err = -EINVAL; + switch (boot_mode) { + case MMCSD_MODE_EMMCBOOT: +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION + part = CONFIG_SYS_MMCSD_RAW_MODE_EMMC_BOOT_PARTITION; +#else + /* + * We need to check what the partition is configured to. + * 1 and 2 match up to boot0 / boot1 and 7 is user data + * which is the first physical partition (0). + */ + part = (mmc->part_config >> 3) & PART_ACCESS_MASK; + + if (part == 7) + part = 0; +#endif + + if (CONFIG_IS_ENABLED(MMC_TINY)) + err = mmc_switch_part(mmc, part); + else + err = blk_dselect_hwpart(mmc_get_blk_desc(mmc), part); + + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + puts("spl: mmc partition switch failed\n"); +#endif + return err; + } + /* Fall through */ + case MMCSD_MODE_RAW: + debug("spl: mmc boot mode: raw\n"); + + if (!spl_start_uboot()) { + err = mmc_load_image_raw_os(spl_image, mmc); + if (!err) + return err; + } + + raw_sect = spl_mmc_get_uboot_raw_sector(mmc, raw_sect); + +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION + err = mmc_load_image_raw_partition(spl_image, mmc, raw_part, + raw_sect); + if (!err) + return err; +#endif +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR + err = mmc_load_image_raw_sector(spl_image, mmc, + raw_sect + spl_mmc_raw_uboot_offset(part)); + if (!err) + return err; +#endif + /* If RAW mode fails, try FS mode. */ + case MMCSD_MODE_FS: + debug("spl: mmc boot mode: fs\n"); + + err = spl_mmc_do_fs_boot(spl_image, mmc, filename); + if (!err) + return err; + + break; +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + default: + puts("spl: mmc: wrong boot mode\n"); +#endif + } + + return err; +} + +int spl_mmc_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + return spl_mmc_load(spl_image, bootdev, +#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, +#else + NULL, +#endif +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION + spl_mmc_boot_partition(bootdev->boot_device), +#else + 0, +#endif +#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); +#else + 0); +#endif +} + +SPL_LOAD_IMAGE_METHOD("MMC1", 0, BOOT_DEVICE_MMC1, spl_mmc_load_image); +SPL_LOAD_IMAGE_METHOD("MMC2", 0, BOOT_DEVICE_MMC2, spl_mmc_load_image); +SPL_LOAD_IMAGE_METHOD("MMC2_2", 0, BOOT_DEVICE_MMC2_2, spl_mmc_load_image); diff --git a/roms/u-boot/common/spl/spl_nand.c b/roms/u-boot/common/spl/spl_nand.c new file mode 100644 index 000000000..59f4a84a3 --- /dev/null +++ b/roms/u-boot/common/spl/spl_nand.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de> + */ +#include <common.h> +#include <config.h> +#include <fdt_support.h> +#include <image.h> +#include <log.h> +#include <spl.h> +#include <asm/io.h> +#include <nand.h> +#include <linux/libfdt_env.h> +#include <fdt.h> + +uint32_t __weak spl_nand_get_uboot_raw_page(void) +{ + return CONFIG_SYS_NAND_U_BOOT_OFFS; +} + +#if defined(CONFIG_SPL_NAND_RAW_ONLY) +static int spl_nand_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + nand_init(); + + printf("Loading U-Boot from 0x%08x (size 0x%08x) to 0x%08x\n", + CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE, + CONFIG_SYS_NAND_U_BOOT_DST); + + nand_spl_load_image(spl_nand_get_uboot_raw_page(), + CONFIG_SYS_NAND_U_BOOT_SIZE, + (void *)CONFIG_SYS_NAND_U_BOOT_DST); + spl_set_header_raw_uboot(spl_image); + nand_deselect(); + + return 0; +} +#else + +static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs, + ulong size, void *dst) +{ + int err; +#ifdef CONFIG_SYS_NAND_BLOCK_SIZE + ulong sector; + + sector = *(int *)load->priv; + offs = sector + nand_spl_adjust_offset(sector, offs - sector); +#else + offs *= load->bl_len; + size *= load->bl_len; +#endif + err = nand_spl_load_image(offs, size, dst); + if (err) + return 0; + + return size / load->bl_len; +} + +struct mtd_info * __weak nand_get_mtd(void) +{ + return NULL; +} + +static int spl_nand_load_element(struct spl_image_info *spl_image, + int offset, struct image_header *header) +{ + struct mtd_info *mtd = nand_get_mtd(); + int bl_len = mtd ? mtd->writesize : 1; + int err; + + err = nand_spl_load_image(offset, sizeof(*header), (void *)header); + if (err) + return err; + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; + + debug("Found FIT\n"); + load.dev = NULL; + load.priv = &offset; + load.filename = NULL; + load.bl_len = bl_len; + load.read = spl_nand_fit_read; + return spl_load_simple_fit(spl_image, &load, offset / bl_len, header); + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + struct spl_load_info load; + + load.dev = NULL; + load.priv = NULL; + load.filename = NULL; + load.bl_len = bl_len; + load.read = spl_nand_fit_read; + return spl_load_imx_container(spl_image, &load, offset / bl_len); + } else { + err = spl_parse_image_header(spl_image, header); + if (err) + return err; + return nand_spl_load_image(offset, spl_image->size, + (void *)(ulong)spl_image->load_addr); + } +} + +static int spl_nand_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + int err; + struct image_header *header; + int *src __attribute__((unused)); + int *dst __attribute__((unused)); + +#ifdef CONFIG_SPL_NAND_SOFTECC + debug("spl: nand - using sw ecc\n"); +#else + debug("spl: nand - using hw ecc\n"); +#endif + nand_init(); + + header = spl_get_load_buffer(0, sizeof(*header)); + +#ifdef CONFIG_SPL_OS_BOOT + if (!spl_start_uboot()) { + /* + * load parameter image + * load to temp position since nand_spl_load_image reads + * a whole block which is typically larger than + * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite + * following sections like BSS + */ + nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS, + CONFIG_CMD_SPL_WRITE_SIZE, + (void *)CONFIG_SYS_TEXT_BASE); + /* copy to destintion */ + for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR, + src = (int *)CONFIG_SYS_TEXT_BASE; + src < (int *)(CONFIG_SYS_TEXT_BASE + + CONFIG_CMD_SPL_WRITE_SIZE); + src++, dst++) { + writel(readl(src), dst); + } + + /* load linux */ + nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS, + sizeof(*header), (void *)header); + err = spl_parse_image_header(spl_image, header); + if (err) + return err; + if (header->ih_os == IH_OS_LINUX) { + /* happy - was a linux */ + err = nand_spl_load_image( + CONFIG_SYS_NAND_SPL_KERNEL_OFFS, + spl_image->size, + (void *)spl_image->load_addr); + nand_deselect(); + return err; + } else { + puts("The Expected Linux image was not " + "found. Please check your NAND " + "configuration.\n"); + puts("Trying to start u-boot now...\n"); + } + } +#endif +#ifdef CONFIG_NAND_ENV_DST + spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET, header); +#ifdef CONFIG_ENV_OFFSET_REDUND + spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET_REDUND, header); +#endif +#endif + /* Load u-boot */ + err = spl_nand_load_element(spl_image, spl_nand_get_uboot_raw_page(), + header); +#ifdef CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND +#if CONFIG_SYS_NAND_U_BOOT_OFFS != CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND + if (err) + err = spl_nand_load_element(spl_image, + CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND, + header); +#endif +#endif + nand_deselect(); + return err; +} +#endif +/* Use priorty 1 so that Ubi can override this */ +SPL_LOAD_IMAGE_METHOD("NAND", 1, BOOT_DEVICE_NAND, spl_nand_load_image); diff --git a/roms/u-boot/common/spl/spl_net.c b/roms/u-boot/common/spl/spl_net.c new file mode 100644 index 000000000..e140a6306 --- /dev/null +++ b/roms/u-boot/common/spl/spl_net.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2012 + * Ilya Yanok <ilya.yanok@gmail.com> + */ +#include <common.h> +#include <env.h> +#include <errno.h> +#include <image.h> +#include <log.h> +#include <spl.h> +#include <net.h> +#include <linux/libfdt.h> + +#if defined(CONFIG_SPL_ETH_SUPPORT) || defined(CONFIG_SPL_USB_ETHER) +static ulong spl_net_load_read(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + debug("%s: sector %lx, count %lx, buf %lx\n", + __func__, sector, count, (ulong)buf); + memcpy(buf, (void *)(image_load_addr + sector), count); + return count; +} + +static int spl_net_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + struct image_header *header = (struct image_header *)image_load_addr; + int rv; + + env_init(); + env_relocate(); + env_set("autoload", "yes"); + rv = eth_initialize(); + if (rv == 0) { + printf("No Ethernet devices found\n"); + return -ENODEV; + } + if (bootdev->boot_device_name) + env_set("ethact", bootdev->boot_device_name); + rv = net_loop(BOOTP); + if (rv < 0) { + printf("Problem booting with BOOTP\n"); + return rv; + } + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; + + debug("Found FIT\n"); + load.bl_len = 1; + load.read = spl_net_load_read; + rv = spl_load_simple_fit(spl_image, &load, 0, header); + } else { + debug("Legacy image\n"); + + rv = spl_parse_image_header(spl_image, header); + if (rv) + return rv; + + memcpy((void *)spl_image->load_addr, header, spl_image->size); + } + + return rv; +} +#endif + +#ifdef CONFIG_SPL_ETH_SUPPORT +int spl_net_load_image_cpgmac(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ +#ifdef CONFIG_SPL_ETH_DEVICE + bootdev->boot_device_name = CONFIG_SPL_ETH_DEVICE; +#endif + + return spl_net_load_image(spl_image, bootdev); +} +SPL_LOAD_IMAGE_METHOD("eth device", 0, BOOT_DEVICE_CPGMAC, + spl_net_load_image_cpgmac); +#endif + +#ifdef CONFIG_SPL_USB_ETHER +int spl_net_load_image_usb(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + bootdev->boot_device_name = "usb_ether"; +#if CONFIG_IS_ENABLED(DM_USB_GADGET) + usb_ether_init(); +#endif + return spl_net_load_image(spl_image, bootdev); +} +SPL_LOAD_IMAGE_METHOD("USB eth", 0, BOOT_DEVICE_USBETH, spl_net_load_image_usb); +#endif diff --git a/roms/u-boot/common/spl/spl_nor.c b/roms/u-boot/common/spl/spl_nor.c new file mode 100644 index 000000000..5270401db --- /dev/null +++ b/roms/u-boot/common/spl/spl_nor.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012 Stefan Roese <sr@denx.de> + */ + +#include <common.h> +#include <image.h> +#include <log.h> +#include <spl.h> + +static ulong spl_nor_load_read(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + debug("%s: sector %lx, count %lx, buf %p\n", + __func__, sector, count, buf); + memcpy(buf, (void *)sector, count); + + return count; +} + +unsigned long __weak spl_nor_get_uboot_base(void) +{ + return CONFIG_SYS_UBOOT_BASE; +} + +static int spl_nor_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + __maybe_unused const struct image_header *header; + __maybe_unused struct spl_load_info load; + + /* + * Loading of the payload to SDRAM is done with skipping of + * the mkimage header in this SPL NOR driver + */ + spl_image->flags |= SPL_COPY_PAYLOAD_ONLY; + +#ifdef CONFIG_SPL_OS_BOOT + if (!spl_start_uboot()) { + /* + * Load Linux from its location in NOR flash to its defined + * location in SDRAM + */ + header = (const struct image_header *)CONFIG_SYS_OS_BASE; +#ifdef CONFIG_SPL_LOAD_FIT + if (image_get_magic(header) == FDT_MAGIC) { + int ret; + + debug("Found FIT\n"); + load.bl_len = 1; + load.read = spl_nor_load_read; + + ret = spl_load_simple_fit(spl_image, &load, + CONFIG_SYS_OS_BASE, + (void *)header); + +#if defined CONFIG_SYS_SPL_ARGS_ADDR && defined CONFIG_CMD_SPL_NOR_OFS + memcpy((void *)CONFIG_SYS_SPL_ARGS_ADDR, + (void *)CONFIG_CMD_SPL_NOR_OFS, + CONFIG_CMD_SPL_WRITE_SIZE); +#endif + return ret; + } +#endif + if (image_get_os(header) == IH_OS_LINUX) { + /* happy - was a Linux */ + int ret; + + ret = spl_parse_image_header(spl_image, header); + if (ret) + return ret; + + memcpy((void *)spl_image->load_addr, + (void *)(CONFIG_SYS_OS_BASE + + sizeof(struct image_header)), + spl_image->size); +#ifdef CONFIG_SYS_FDT_BASE + spl_image->arg = (void *)CONFIG_SYS_FDT_BASE; +#endif + + return 0; + } else { + puts("The Expected Linux image was not found.\n" + "Please check your NOR configuration.\n" + "Trying to start u-boot now...\n"); + } + } +#endif + + /* + * Load real U-Boot from its location in NOR flash to its + * defined location in SDRAM + */ +#ifdef CONFIG_SPL_LOAD_FIT + header = (const struct image_header *)spl_nor_get_uboot_base(); + if (image_get_magic(header) == FDT_MAGIC) { + debug("Found FIT format U-Boot\n"); + load.bl_len = 1; + load.read = spl_nor_load_read; + return spl_load_simple_fit(spl_image, &load, + spl_nor_get_uboot_base(), + (void *)header); + } +#endif + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + load.bl_len = 1; + load.read = spl_nor_load_read; + return spl_load_imx_container(spl_image, &load, + spl_nor_get_uboot_base()); + } + + /* Legacy image handling */ + if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_SUPPORT)) { + load.bl_len = 1; + load.read = spl_nor_load_read; + return spl_load_legacy_img(spl_image, &load, + spl_nor_get_uboot_base()); + } + + return 0; +} +SPL_LOAD_IMAGE_METHOD("NOR", 0, BOOT_DEVICE_NOR, spl_nor_load_image); diff --git a/roms/u-boot/common/spl/spl_onenand.c b/roms/u-boot/common/spl/spl_onenand.c new file mode 100644 index 000000000..93cbf47e8 --- /dev/null +++ b/roms/u-boot/common/spl/spl_onenand.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013 + * ISEE 2007 SL - Enric Balletbo i Serra <eballetbo@iseebcn.com> + * + * Based on common/spl/spl_nand.c + * Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de> + */ +#include <common.h> +#include <config.h> +#include <image.h> +#include <log.h> +#include <spl.h> +#include <asm/io.h> +#include <onenand_uboot.h> + +static int spl_onenand_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + struct image_header *header; + int ret; + + debug("spl: onenand\n"); + + header = spl_get_load_buffer(0, CONFIG_SYS_ONENAND_PAGE_SIZE); + /* Load u-boot */ + onenand_spl_load_image(CONFIG_SYS_ONENAND_U_BOOT_OFFS, + CONFIG_SYS_ONENAND_PAGE_SIZE, (void *)header); + ret = spl_parse_image_header(spl_image, header); + if (ret) + return ret; + onenand_spl_load_image(CONFIG_SYS_ONENAND_U_BOOT_OFFS, + spl_image->size, (void *)spl_image->load_addr); + + return 0; +} +/* Use priorty 1 so that Ubi can override this */ +SPL_LOAD_IMAGE_METHOD("OneNAND", 1, BOOT_DEVICE_ONENAND, + spl_onenand_load_image); diff --git a/roms/u-boot/common/spl/spl_opensbi.c b/roms/u-boot/common/spl/spl_opensbi.c new file mode 100644 index 000000000..1c0abf855 --- /dev/null +++ b/roms/u-boot/common/spl/spl_opensbi.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Fraunhofer AISEC, + * Lukas Auer <lukas.auer@aisec.fraunhofer.de> + * + * Based on common/spl/spl_atf.c + */ +#include <common.h> +#include <cpu_func.h> +#include <errno.h> +#include <hang.h> +#include <image.h> +#include <spl.h> +#include <asm/global_data.h> +#include <asm/smp.h> +#include <opensbi.h> +#include <linux/libfdt.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct fw_dynamic_info opensbi_info; + +static int spl_opensbi_find_uboot_node(void *blob, int *uboot_node) +{ + int fit_images_node, node; + const char *fit_os; + + fit_images_node = fdt_path_offset(blob, "/fit-images"); + if (fit_images_node < 0) + return -ENODEV; + + fdt_for_each_subnode(node, blob, fit_images_node) { + fit_os = fdt_getprop(blob, node, FIT_OS_PROP, NULL); + if (!fit_os) + continue; + + if (genimg_get_os_id(fit_os) == IH_OS_U_BOOT) { + *uboot_node = node; + return 0; + } + } + + return -ENODEV; +} + +void spl_invoke_opensbi(struct spl_image_info *spl_image) +{ + int ret, uboot_node; + ulong uboot_entry; + void (*opensbi_entry)(ulong hartid, ulong dtb, ulong info); + + if (!spl_image->fdt_addr) { + pr_err("No device tree specified in SPL image\n"); + hang(); + } + + /* Find U-Boot image in /fit-images */ + ret = spl_opensbi_find_uboot_node(spl_image->fdt_addr, &uboot_node); + if (ret) { + pr_err("Can't find U-Boot node, %d\n", ret); + hang(); + } + + /* Get U-Boot entry point */ + ret = fit_image_get_entry(spl_image->fdt_addr, uboot_node, &uboot_entry); + if (ret) + ret = fit_image_get_load(spl_image->fdt_addr, uboot_node, &uboot_entry); + + /* Prepare obensbi_info object */ + opensbi_info.magic = FW_DYNAMIC_INFO_MAGIC_VALUE; + opensbi_info.version = FW_DYNAMIC_INFO_VERSION; + opensbi_info.next_addr = uboot_entry; + opensbi_info.next_mode = FW_DYNAMIC_INFO_NEXT_MODE_S; + opensbi_info.options = SBI_SCRATCH_NO_BOOT_PRINTS; + opensbi_info.boot_hart = gd->arch.boot_hart; + + opensbi_entry = (void (*)(ulong, ulong, ulong))spl_image->entry_point; + invalidate_icache_all(); + +#ifdef CONFIG_SPL_SMP + /* + * Start OpenSBI on all secondary harts and wait for acknowledgment. + * + * OpenSBI first relocates itself to its link address. This is done by + * the main hart. To make sure no hart is still running U-Boot SPL + * during relocation, we wait for all secondary harts to acknowledge + * the call-function request before entering OpenSBI on the main hart. + * Otherwise, code corruption can occur if the link address ranges of + * U-Boot SPL and OpenSBI overlap. + */ + ret = smp_call_function((ulong)spl_image->entry_point, + (ulong)spl_image->fdt_addr, + (ulong)&opensbi_info, 1); + if (ret) + hang(); +#endif + opensbi_entry(gd->arch.boot_hart, (ulong)spl_image->fdt_addr, + (ulong)&opensbi_info); +} diff --git a/roms/u-boot/common/spl/spl_optee.S b/roms/u-boot/common/spl/spl_optee.S new file mode 100644 index 000000000..8bd1949dd --- /dev/null +++ b/roms/u-boot/common/spl/spl_optee.S @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2017 Rockchip Electronic Co.,Ltd + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +ENTRY(spl_optee_entry) + ldr lr, =CONFIG_SYS_TEXT_BASE + mov pc, r3 +ENDPROC(spl_optee_entry) diff --git a/roms/u-boot/common/spl/spl_ram.c b/roms/u-boot/common/spl/spl_ram.c new file mode 100644 index 000000000..df1d5b43d --- /dev/null +++ b/roms/u-boot/common/spl/spl_ram.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2016 + * Xilinx, Inc. + * + * (C) Copyright 2016 + * Toradex AG + * + * Michal Simek <michal.simek@xilinx.com> + * Stefan Agner <stefan.agner@toradex.com> + */ +#include <common.h> +#include <binman_sym.h> +#include <image.h> +#include <log.h> +#include <mapmem.h> +#include <spl.h> +#include <linux/libfdt.h> + +#ifndef CONFIG_SPL_LOAD_FIT_ADDRESS +# define CONFIG_SPL_LOAD_FIT_ADDRESS 0 +#endif + +static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + debug("%s: sector %lx, count %lx, buf %lx\n", + __func__, sector, count, (ulong)buf); + memcpy(buf, (void *)(CONFIG_SPL_LOAD_FIT_ADDRESS + sector), count); + return count; +} + +static int spl_ram_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + struct image_header *header; + + header = (struct image_header *)CONFIG_SPL_LOAD_FIT_ADDRESS; + +#if CONFIG_IS_ENABLED(DFU) + if (bootdev->boot_device == BOOT_DEVICE_DFU) + spl_dfu_cmd(0, "dfu_alt_info_ram", "ram", "0"); +#endif + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; + + debug("Found FIT\n"); + load.bl_len = 1; + load.read = spl_ram_load_read; + spl_load_simple_fit(spl_image, &load, 0, header); + } else { + ulong u_boot_pos = binman_sym(ulong, u_boot_any, image_pos); + + debug("Legacy image\n"); + /* + * Get the header. It will point to an address defined by + * handoff which will tell where the image located inside + * the flash. + */ + debug("u_boot_pos = %lx\n", u_boot_pos); + if (u_boot_pos == BINMAN_SYM_MISSING) { + /* + * No binman support or no information. For now, fix it + * to the address pointed to by U-Boot. + */ + u_boot_pos = (ulong)spl_get_load_buffer(-sizeof(*header), + sizeof(*header)); + } + header = (struct image_header *)map_sysmem(u_boot_pos, 0); + + spl_parse_image_header(spl_image, header); + } + + return 0; +} +#if CONFIG_IS_ENABLED(RAM_DEVICE) +SPL_LOAD_IMAGE_METHOD("RAM", 0, BOOT_DEVICE_RAM, spl_ram_load_image); +#endif +#if CONFIG_IS_ENABLED(DFU) +SPL_LOAD_IMAGE_METHOD("DFU", 0, BOOT_DEVICE_DFU, spl_ram_load_image); +#endif + + diff --git a/roms/u-boot/common/spl/spl_sata.c b/roms/u-boot/common/spl/spl_sata.c new file mode 100644 index 000000000..e108af057 --- /dev/null +++ b/roms/u-boot/common/spl/spl_sata.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * Dan Murphy <dmurphy@ti.com> + * + * Derived work from spl_usb.c + */ + +#include <common.h> +#include <spl.h> +#include <asm/u-boot.h> +#include <sata.h> +#include <scsi.h> +#include <errno.h> +#include <fat.h> +#include <image.h> + +#ifndef CONFIG_SYS_SATA_FAT_BOOT_PARTITION +#define CONFIG_SYS_SATA_FAT_BOOT_PARTITION 1 +#endif + +#ifndef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME +#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img" +#endif + +#ifndef CONFIG_SPL_SATA_RAW_U_BOOT_SECTOR +/* Dummy value to make the compiler happy */ +#define CONFIG_SPL_SATA_RAW_U_BOOT_SECTOR 0x100 +#endif + +static int spl_sata_load_image_raw(struct spl_image_info *spl_image, + struct blk_desc *stor_dev, unsigned long sector) +{ + struct image_header *header; + unsigned long count; + u32 image_size_sectors; + int ret; + + header = spl_get_load_buffer(-sizeof(*header), stor_dev->blksz); + count = blk_dread(stor_dev, sector, 1, header); + if (count == 0) + return -EIO; + + ret = spl_parse_image_header(spl_image, header); + if (ret) + return ret; + + image_size_sectors = DIV_ROUND_UP(spl_image->size, stor_dev->blksz); + count = blk_dread(stor_dev, sector, image_size_sectors, + (void *)spl_image->load_addr); + if (count != image_size_sectors) + return -EIO; + + return 0; +} + +static int spl_sata_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + int err = 0; + struct blk_desc *stor_dev; + +#if !defined(CONFIG_DM_SCSI) && !defined(CONFIG_AHCI) + err = init_sata(CONFIG_SPL_SATA_BOOT_DEVICE); +#endif + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: sata init failed: err - %d\n", err); +#endif + return err; + } else { + /* try to recognize storage devices immediately */ + scsi_scan(false); + stor_dev = blk_get_devnum_by_type(IF_TYPE_SCSI, 0); + if (!stor_dev) + return -ENODEV; + } + +#ifdef CONFIG_SPL_OS_BOOT + if (spl_start_uboot() || + spl_load_image_fat_os(spl_image, stor_dev, + CONFIG_SYS_SATA_FAT_BOOT_PARTITION)) +#endif + { + err = -ENOSYS; + + if (IS_ENABLED(CONFIG_SPL_FS_FAT)) { + err = spl_load_image_fat(spl_image, stor_dev, + CONFIG_SYS_SATA_FAT_BOOT_PARTITION, + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); + } else if (IS_ENABLED(CONFIG_SPL_SATA_RAW_U_BOOT_USE_SECTOR)) { + err = spl_sata_load_image_raw(spl_image, stor_dev, + CONFIG_SPL_SATA_RAW_U_BOOT_SECTOR); + } + } + if (err) { + puts("Error loading sata device\n"); + return err; + } + + return 0; +} +SPL_LOAD_IMAGE_METHOD("SATA", 0, BOOT_DEVICE_SATA, spl_sata_load_image); diff --git a/roms/u-boot/common/spl/spl_sdp.c b/roms/u-boot/common/spl/spl_sdp.c new file mode 100644 index 000000000..ae9c09883 --- /dev/null +++ b/roms/u-boot/common/spl/spl_sdp.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2016 Toradex + * Author: Stefan Agner <stefan.agner@toradex.com> + */ + +#include <common.h> +#include <log.h> +#include <spl.h> +#include <usb.h> +#include <g_dnl.h> +#include <sdp.h> + +static int spl_sdp_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + int ret; + const int controller_index = CONFIG_SPL_SDP_USB_DEV; + + usb_gadget_initialize(controller_index); + + board_usb_init(0, USB_INIT_DEVICE); + + g_dnl_clear_detach(); + ret = g_dnl_register("usb_dnl_sdp"); + if (ret) { + pr_err("SDP dnl register failed: %d\n", ret); + return ret; + } + + ret = sdp_init(controller_index); + if (ret) { + pr_err("SDP init failed: %d\n", ret); + return -ENODEV; + } + + /* + * This command either loads a legacy image, jumps and never returns, + * or it loads a FIT image and returns it to be handled by the SPL + * code. + */ + ret = spl_sdp_handle(controller_index, spl_image); + debug("SDP ended\n"); + + usb_gadget_release(controller_index); + return ret; +} +SPL_LOAD_IMAGE_METHOD("USB SDP", 0, BOOT_DEVICE_BOARD, spl_sdp_load_image); diff --git a/roms/u-boot/common/spl/spl_spi.c b/roms/u-boot/common/spl/spl_spi.c new file mode 100644 index 000000000..6a4e03328 --- /dev/null +++ b/roms/u-boot/common/spl/spl_spi.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 OMICRON electronics GmbH + * + * based on drivers/mtd/nand/raw/nand_spl_load.c + * + * Copyright (C) 2011 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + */ + +#include <common.h> +#include <image.h> +#include <log.h> +#include <spi.h> +#include <spi_flash.h> +#include <errno.h> +#include <spl.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_SPL_OS_BOOT +/* + * Load the kernel, check for a valid header we can parse, and if found load + * the kernel and then device tree. + */ +static int spi_load_image_os(struct spl_image_info *spl_image, + struct spi_flash *flash, + struct image_header *header) +{ + int err; + + /* Read for a header, parse or error out. */ + spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS, sizeof(*header), + (void *)header); + + if (image_get_magic(header) != IH_MAGIC) + return -1; + + err = spl_parse_image_header(spl_image, header); + if (err) + return err; + + spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS, + spl_image->size, (void *)spl_image->load_addr); + + /* Read device tree. */ + spi_flash_read(flash, CONFIG_SYS_SPI_ARGS_OFFS, + CONFIG_SYS_SPI_ARGS_SIZE, + (void *)CONFIG_SYS_SPL_ARGS_ADDR); + + return 0; +} +#endif + +static ulong spl_spi_fit_read(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + struct spi_flash *flash = load->dev; + ulong ret; + + ret = spi_flash_read(flash, sector, count, buf); + if (!ret) + return count; + else + return 0; +} + +unsigned int __weak spl_spi_get_uboot_offs(struct spi_flash *flash) +{ + return CONFIG_SYS_SPI_U_BOOT_OFFS; +} + +/* + * The main entry for SPI booting. It's necessary that SDRAM is already + * configured and available since this code loads the main U-Boot image + * from SPI into SDRAM and starts it from there. + */ +static int spl_spi_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + int err = 0; + unsigned int payload_offs; + struct spi_flash *flash; + struct image_header *header; + + /* + * Load U-Boot image from SPI flash into RAM + * In DM mode: defaults speed and mode will be + * taken from DT when available + */ + + flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, + CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE); + if (!flash) { + puts("SPI probe failed.\n"); + return -ENODEV; + } + + payload_offs = spl_spi_get_uboot_offs(flash); + + header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + payload_offs = fdtdec_get_config_int(gd->fdt_blob, + "u-boot,spl-payload-offset", + payload_offs); +#endif + +#ifdef CONFIG_SPL_OS_BOOT + if (spl_start_uboot() || spi_load_image_os(spl_image, flash, header)) +#endif + { + /* Load u-boot, mkimage header is 64 bytes. */ + err = spi_flash_read(flash, payload_offs, sizeof(*header), + (void *)header); + if (err) { + debug("%s: Failed to read from SPI flash (err=%d)\n", + __func__, err); + return err; + } + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && + image_get_magic(header) == FDT_MAGIC) { + err = spi_flash_read(flash, payload_offs, + roundup(fdt_totalsize(header), 4), + (void *)CONFIG_SYS_LOAD_ADDR); + if (err) + return err; + err = spl_parse_image_header(spl_image, + (struct image_header *)CONFIG_SYS_LOAD_ADDR); + } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; + + debug("Found FIT\n"); + load.dev = flash; + load.priv = NULL; + load.filename = NULL; + load.bl_len = 1; + load.read = spl_spi_fit_read; + err = spl_load_simple_fit(spl_image, &load, + payload_offs, + header); + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + struct spl_load_info load; + + load.dev = flash; + load.priv = NULL; + load.filename = NULL; + load.bl_len = 1; + load.read = spl_spi_fit_read; + + err = spl_load_imx_container(spl_image, &load, + payload_offs); + } else { + err = spl_parse_image_header(spl_image, header); + if (err) + return err; + err = spi_flash_read(flash, payload_offs, + spl_image->size, + (void *)spl_image->load_addr); + } + } + + return err; +} +/* Use priorty 1 so that boards can override this */ +SPL_LOAD_IMAGE_METHOD("SPI", 1, BOOT_DEVICE_SPI, spl_spi_load_image); diff --git a/roms/u-boot/common/spl/spl_ubi.c b/roms/u-boot/common/spl/spl_ubi.c new file mode 100644 index 000000000..de6a63bd2 --- /dev/null +++ b/roms/u-boot/common/spl/spl_ubi.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2016 + * Ladislav Michl <ladis@linux-mips.org> + */ + +#include <common.h> +#include <config.h> +#include <image.h> +#include <nand.h> +#include <onenand_uboot.h> +#include <ubispl.h> +#include <spl.h> + +int spl_ubi_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + struct image_header *header; + struct ubispl_info info; + struct ubispl_load volumes[2]; + int ret = 1; + + switch (bootdev->boot_device) { +#ifdef CONFIG_SPL_NAND_SUPPORT + case BOOT_DEVICE_NAND: + nand_init(); + info.read = nand_spl_read_block; + info.peb_size = CONFIG_SYS_NAND_BLOCK_SIZE; + break; +#endif +#ifdef CONFIG_SPL_ONENAND_SUPPORT + case BOOT_DEVICE_ONENAND: + info.read = onenand_spl_read_block; + info.peb_size = CONFIG_SYS_ONENAND_BLOCK_SIZE; + break; +#endif + default: + goto out; + } + info.ubi = (struct ubi_scan_info *)CONFIG_SPL_UBI_INFO_ADDR; + info.fastmap = IS_ENABLED(CONFIG_MTD_UBI_FASTMAP); + + info.peb_offset = CONFIG_SPL_UBI_PEB_OFFSET; + info.vid_offset = CONFIG_SPL_UBI_VID_OFFSET; + info.leb_start = CONFIG_SPL_UBI_LEB_START; + info.peb_count = CONFIG_SPL_UBI_MAX_PEBS - info.peb_offset; + +#ifdef CONFIG_SPL_OS_BOOT + if (!spl_start_uboot()) { + volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_KERNEL_ID; + volumes[0].load_addr = (void *)CONFIG_SYS_LOAD_ADDR; + volumes[1].vol_id = CONFIG_SPL_UBI_LOAD_ARGS_ID; + volumes[1].load_addr = (void *)CONFIG_SYS_SPL_ARGS_ADDR; + + ret = ubispl_load_volumes(&info, volumes, 2); + if (!ret) { + header = (struct image_header *)volumes[0].load_addr; + spl_parse_image_header(spl_image, header); + puts("Linux loaded.\n"); + goto out; + } + puts("Loading Linux failed, falling back to U-Boot.\n"); + } +#endif + header = spl_get_load_buffer(-sizeof(*header), sizeof(header)); +#ifdef CONFIG_SPL_UBI_LOAD_BY_VOLNAME + volumes[0].vol_id = -1; + strncpy(volumes[0].name, + CONFIG_SPL_UBI_LOAD_MONITOR_VOLNAME, + UBI_VOL_NAME_MAX + 1); +#else + volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_MONITOR_ID; +#endif + volumes[0].load_addr = (void *)header; + + ret = ubispl_load_volumes(&info, volumes, 1); + if (!ret) + spl_parse_image_header(spl_image, header); +out: +#ifdef CONFIG_SPL_NAND_SUPPORT + if (bootdev->boot_device == BOOT_DEVICE_NAND) + nand_deselect(); +#endif + return ret; +} +/* Use priorty 0 so that Ubi will override NAND and ONENAND methods */ +SPL_LOAD_IMAGE_METHOD("NAND", 0, BOOT_DEVICE_NAND, spl_ubi_load_image); +SPL_LOAD_IMAGE_METHOD("OneNAND", 0, BOOT_DEVICE_ONENAND, spl_ubi_load_image); diff --git a/roms/u-boot/common/spl/spl_usb.c b/roms/u-boot/common/spl/spl_usb.c new file mode 100644 index 000000000..3648de349 --- /dev/null +++ b/roms/u-boot/common/spl/spl_usb.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2014 + * Texas Instruments, <www.ti.com> + * + * Dan Murphy <dmurphy@ti.com> + * + * Derived work from spl_mmc.c + */ + +#include <common.h> +#include <log.h> +#include <spl.h> +#include <asm/u-boot.h> +#include <errno.h> +#include <usb.h> +#include <fat.h> + +static int usb_stor_curr_dev = -1; /* current device */ + +int spl_usb_load(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev, int partition, + const char *filename) +{ + int err = 0; + struct blk_desc *stor_dev; + static bool usb_init_pending = true; + + if (usb_init_pending) { + usb_stop(); + err = usb_init(); + usb_init_pending = false; + } + + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("%s: usb init failed: err - %d\n", __func__, err); +#endif + return err; + } + + /* try to recognize storage devices immediately */ + usb_stor_curr_dev = usb_stor_scan(1); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, usb_stor_curr_dev); + if (!stor_dev) + return -ENODEV; + + debug("boot mode - FAT\n"); + +#ifdef CONFIG_SPL_OS_BOOT + if (spl_start_uboot() || + spl_load_image_fat_os(spl_image, stor_dev, partition)) +#endif + { + err = spl_load_image_fat(spl_image, stor_dev, partition, filename); + } + + if (err) { + puts("Error loading from USB device\n"); + return err; + } + + return 0; +} + +static int spl_usb_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + return spl_usb_load(spl_image, bootdev, + CONFIG_SYS_USB_FAT_BOOT_PARTITION, + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); +} +SPL_LOAD_IMAGE_METHOD("USB", 0, BOOT_DEVICE_USB, spl_usb_load_image); diff --git a/roms/u-boot/common/spl/spl_xip.c b/roms/u-boot/common/spl/spl_xip.c new file mode 100644 index 000000000..8ce0a09ef --- /dev/null +++ b/roms/u-boot/common/spl/spl_xip.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. + */ + +#include <common.h> +#include <image.h> +#include <log.h> +#include <spl.h> + +static int spl_xip(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ +#ifdef CONFIG_SPL_OS_BOOT + if (!spl_start_uboot()) { + spl_image->arg = (void *)CONFIG_SYS_FDT_BASE; + spl_image->name = "Linux"; + spl_image->os = IH_OS_LINUX; + spl_image->load_addr = CONFIG_SYS_LOAD_ADDR; + spl_image->entry_point = CONFIG_SYS_LOAD_ADDR; + debug("spl: payload xipImage, load addr: 0x%lx\n", + spl_image->load_addr); + return 0; + } +#endif + return(spl_parse_image_header(spl_image, (const struct image_header *) + CONFIG_SYS_UBOOT_BASE)); +} +SPL_LOAD_IMAGE_METHOD("XIP", 0, BOOT_DEVICE_XIP, spl_xip); diff --git a/roms/u-boot/common/spl/spl_ymodem.c b/roms/u-boot/common/spl/spl_ymodem.c new file mode 100644 index 000000000..e979f780a --- /dev/null +++ b/roms/u-boot/common/spl/spl_ymodem.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2011 + * Texas Instruments, <www.ti.com> + * + * Matt Porter <mporter@ti.com> + */ +#include <common.h> +#include <gzip.h> +#include <image.h> +#include <log.h> +#include <spl.h> +#include <xyzModem.h> +#include <asm/u-boot.h> +#include <linux/libfdt.h> + +#define BUF_SIZE 1024 + +/* + * Information required to load image using ymodem. + * + * @image_read: Now of bytes read from the image. + * @buf: pointer to the previous read block. + */ +struct ymodem_fit_info { + int image_read; + char *buf; +}; + +static int getcymodem(void) { + if (tstc()) + return (getchar()); + return -1; +} + +static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset, + ulong size, void *addr) +{ + int res, err, buf_offset; + struct ymodem_fit_info *info = load->priv; + char *buf = info->buf; + + while (info->image_read < offset) { + res = xyzModem_stream_read(buf, BUF_SIZE, &err); + if (res <= 0) + break; + + info->image_read += res; + } + + if (info->image_read > offset) { + res = info->image_read - offset; + if (info->image_read % BUF_SIZE) + buf_offset = (info->image_read % BUF_SIZE); + else + buf_offset = BUF_SIZE; + memcpy(addr, &buf[buf_offset - res], res); + addr = addr + res; + } + + while (info->image_read < offset + size) { + res = xyzModem_stream_read(buf, BUF_SIZE, &err); + if (res <= 0) + break; + + memcpy(addr, buf, res); + info->image_read += res; + addr += res; + } + + return size; +} + +int spl_ymodem_load_image(struct spl_image_info *spl_image, + struct spl_boot_device *bootdev) +{ + ulong size = 0; + int err; + int res; + int ret; + connection_info_t info; + char buf[BUF_SIZE]; + struct image_header *ih = NULL; + ulong addr = 0; + + info.mode = xyzModem_ymodem; + ret = xyzModem_stream_open(&info, &err); + if (ret) { + printf("spl: ymodem err - %s\n", xyzModem_error(err)); + return ret; + } + + res = xyzModem_stream_read(buf, BUF_SIZE, &err); + if (res <= 0) + goto end_stream; + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && + image_get_magic((struct image_header *)buf) == FDT_MAGIC) { + addr = CONFIG_SYS_LOAD_ADDR; + ih = (struct image_header *)addr; + + memcpy((void *)addr, buf, res); + size += res; + addr += res; + + while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) { + memcpy((void *)addr, buf, res); + size += res; + addr += res; + } + + ret = spl_parse_image_header(spl_image, ih); + if (ret) + return ret; + } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic((struct image_header *)buf) == FDT_MAGIC) { + struct spl_load_info load; + struct ymodem_fit_info info; + + debug("Found FIT\n"); + load.dev = NULL; + load.priv = (void *)&info; + load.filename = NULL; + load.bl_len = 1; + info.buf = buf; + info.image_read = BUF_SIZE; + load.read = ymodem_read_fit; + ret = spl_load_simple_fit(spl_image, &load, 0, (void *)buf); + size = info.image_read; + + while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) + size += res; + } else { + ih = (struct image_header *)buf; + ret = spl_parse_image_header(spl_image, ih); + if (ret) + goto end_stream; +#ifdef CONFIG_SPL_GZIP + if (ih->ih_comp == IH_COMP_GZIP) + addr = CONFIG_SYS_LOAD_ADDR; + else +#endif + addr = spl_image->load_addr; + memcpy((void *)addr, buf, res); + ih = (struct image_header *)addr; + size += res; + addr += res; + + while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) { + memcpy((void *)addr, buf, res); + size += res; + addr += res; + } + } + +end_stream: + xyzModem_stream_close(&err); + xyzModem_stream_terminate(false, &getcymodem); + + printf("Loaded %lu bytes\n", size); + +#ifdef CONFIG_SPL_GZIP + if (!(IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic((struct image_header *)buf) == FDT_MAGIC) && + (ih->ih_comp == IH_COMP_GZIP)) { + if (gunzip((void *)(spl_image->load_addr + sizeof(*ih)), + CONFIG_SYS_BOOTM_LEN, + (void *)(CONFIG_SYS_LOAD_ADDR + sizeof(*ih)), + &size)) { + puts("Uncompressing error\n"); + return -EIO; + } + } +#endif + + return ret; +} +SPL_LOAD_IMAGE_METHOD("UART", 0, BOOT_DEVICE_UART, spl_ymodem_load_image); |