From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kever Yang Date: Fri, 06 Jan 2017 15:09:03 +0800 Subject: [U-Boot] [RFC PATCH 3/3] spl: add support to booting with ATF In-Reply-To: <4bbea67f-5fd8-74ff-859f-d22b96a3a127@xilinx.com> References: <1483007152-675-1-git-send-email-kever.yang@rock-chips.com> <1483007152-675-4-git-send-email-kever.yang@rock-chips.com> <4bbea67f-5fd8-74ff-859f-d22b96a3a127@xilinx.com> Message-ID: <586F428F.60202@rock-chips.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Michal, Thanks for your comments. On 01/02/2017 11:05 PM, Michal Simek wrote: > On 29.12.2016 11:25, Kever Yang wrote: >> ATF(ARM Trust Firmware) is used by ARM arch64 SoCs, find more infomation >> about ATF at: >> >> SPL is consider as BL2 in ATF, it needs to load other part of ATF binary > SPL replaces BL2 in ATF OK, will follow your comment in next patch. > >> like BL31, BL32, SCP-BL30, and BL33(U-Boot). And needs to prepare the >> parameter for BL31 which including entry and image information for all >> other images. Then the SPL handle PC to BL31 with the parameter, the >> BL31 will do the rest of work and at last get into U-Boot(BL33). > But the main question for this is how do load that images and in which > format. It means I would think that you will introduce fit format which > contain BL33(U-Boot), BL32(secure os) and BL31(ATF) and SPL will be able > to load all of them. Yes, I use FIT format to contain BL33 and BL32 and SPL load all of them. > > If you look at zynqmp I did a small trick where I consider case that > with ATF it is OS boot where kernel is ATF and dtb is full u-boot to get > it boot. This is a good idea, and it look fine for support ATF in SPL in local source code, but it will be better if we have an official support for ATF, right? > > If you adopt fit format then I expect SPL will be able to remember which > part is where and based on that fill structure for ATF. > Then SPL_ATF_TEXT_BASE address is not needed because it will be read > from fit format. Yes, you are right, SPL_ATF_TEXT_BASE is not a must, we gen get it from fit. > > > >> Signed-off-by: Kever Yang >> --- >> >> common/spl/Kconfig | 14 +++ >> common/spl/Makefile | 1 + >> common/spl/spl.c | 4 + >> common/spl/spl_atf.c | 91 ++++++++++++++++ >> include/atf_common.h | 295 +++++++++++++++++++++++++++++++++++++++++++++++++++ >> include/spl.h | 1 + >> 6 files changed, 406 insertions(+) >> create mode 100644 common/spl/spl_atf.c >> create mode 100644 include/atf_common.h >> >> diff --git a/common/spl/Kconfig b/common/spl/Kconfig >> index cba51f5..1bb4360 100644 >> --- a/common/spl/Kconfig >> +++ b/common/spl/Kconfig >> @@ -577,6 +577,20 @@ config SPL_YMODEM_SUPPORT >> means of transmitting U-Boot over a serial line for using in SPL, >> with a checksum to ensure correctness. >> >> +config SPL_ATF_SUPPORT >> + bool "Support ARM trust firmware" >> + depends on SPL >> + help >> + ATF(ARM Trust Firmware) is component for ARM arch64 which need to >> + load by SPL(consider as BL2 in ATF). >> + More detail at: https://github.com/ARM-software/arm-trusted-firmware >> + >> +config SPL_ATF_TEXT_BASE >> + depends on SPL_ATF_SUPPORT >> + hex "ATF TEXT BASE addr" >> + help >> + This is the base address in memory for ATF text and entry point. >> + >> config TPL_ENV_SUPPORT >> bool "Support an environment" >> depends on TPL >> diff --git a/common/spl/Makefile b/common/spl/Makefile >> index ed02635..620ae90 100644 >> --- a/common/spl/Makefile >> +++ b/common/spl/Makefile >> @@ -20,6 +20,7 @@ endif >> obj-$(CONFIG_SPL_UBI) += spl_ubi.o >> obj-$(CONFIG_SPL_NET_SUPPORT) += spl_net.o >> obj-$(CONFIG_SPL_MMC_SUPPORT) += spl_mmc.o >> +obj-$(CONFIG_SPL_ATF_SUPPORT) += spl_atf.o >> obj-$(CONFIG_SPL_USB_SUPPORT) += spl_usb.o >> obj-$(CONFIG_SPL_FAT_SUPPORT) += spl_fat.o >> obj-$(CONFIG_SPL_EXT_SUPPORT) += spl_ext.o >> diff --git a/common/spl/spl.c b/common/spl/spl.c >> index 1729034..7daf7bd 100644 >> --- a/common/spl/spl.c >> +++ b/common/spl/spl.c >> @@ -390,6 +390,10 @@ void board_init_r(gd_t *dummy1, ulong dummy2) >> gd->malloc_ptr / 1024); >> #endif >> >> +#ifdef CONFIG_SPL_ATF_SUPPORT >> + bl31_entry(); >> +#endif >> + >> debug("loaded - jumping to U-Boot..."); >> spl_board_prepare_for_boot(); >> jump_to_image_no_args(&spl_image); >> diff --git a/common/spl/spl_atf.c b/common/spl/spl_atf.c >> new file mode 100644 >> index 0000000..cf23b7a >> --- /dev/null >> +++ b/common/spl/spl_atf.c >> @@ -0,0 +1,91 @@ >> +/* >> + * Copyright (C) 2016 Rockchip Electronic Co.,Ltd >> + * Written by Kever Yang >> + * >> + * origin from arm-trust-firmware >> + * plat/arm/common/arm_bl2_setup.c >> + * SPDX-License-Identifier: GPL-2.0+ > this is not based on gpl file that's why license should be different. Sorry, I do not get what your mean, I'm not good at license policy, ARM ATF use its own license, what should I do for license when I use code from ATF? > > >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> + >> +static struct bl2_to_bl31_params_mem_t bl31_params_mem; >> +static struct bl31_params_t *bl2_to_bl31_params; >> + >> +/******************************************************************************* >> + * This function assigns a pointer to the memory that the platform has kept >> + * aside to pass platform specific and trusted firmware related information >> + * to BL31. This memory is allocated by allocating memory to >> + * bl2_to_bl31_params_mem_t structure which is a superset of all the >> + * structure whose information is passed to BL31 >> + * NOTE: This function should be called only once and should be done >> + * before generating params to BL31 >> + ******************************************************************************/ >> +struct bl31_params_t *bl2_plat_get_bl31_params(void) >> +{ >> + struct entry_point_info_t *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_t)); >> + >> + /* Assign memory for TF related information */ >> + bl2_to_bl31_params = &bl31_params_mem.bl31_params; >> + SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0); >> + >> + /* Fill BL31 related information */ >> + SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY, >> + VERSION_1, 0); >> + >> + /* Fill BL32 related information if it exists */ >> +#ifdef BL32_BASE >> + bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; >> + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP, >> + VERSION_1, 0); >> + bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; >> + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY, >> + VERSION_1, 0); >> +#endif /* BL32_BASE */ > Is this used? Not use for me now, but it may useful later, because we need to fill info about bl32 if there is. > >> + >> + /* 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, PARAM_EP, VERSION_1, 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 = CONFIG_SYS_TEXT_BASE; >> + 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, PARAM_IMAGE_BINARY, >> + VERSION_1, 0); >> + >> + > double lines. Will fix in next patch, confuse why checkpatch did not find this. > >> + return bl2_to_bl31_params; >> +} >> + >> +void raw_write_daif(uint32_t daif) >> +{ >> + __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory"); >> +} >> + >> +void bl31_entry(void) >> +{ >> + struct bl31_params_t *bl31_params; >> + void (*entry)(struct bl31_params_t *params, void *plat_params) = NULL; >> + >> + bl31_params = bl2_plat_get_bl31_params(); >> + entry = (void *)CONFIG_SPL_ATF_TEXT_BASE; >> + >> + raw_write_daif(SPSR_EXCEPTION_MASK); >> + dcache_disable(); >> + >> + entry(bl31_params, NULL); >> +} >> diff --git a/include/atf_common.h b/include/atf_common.h >> new file mode 100644 >> index 0000000..8351302 >> --- /dev/null >> +++ b/include/atf_common.h >> @@ -0,0 +1,295 @@ >> +/* >> + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. >> + * >> + * Redistribution and use in source and binary forms, with or without >> + * modification, are permitted provided that the following conditions are met: >> + * >> + * Redistributions of source code must retain the above copyright notice, this >> + * list of conditions and the following disclaimer. >> + * >> + * Redistributions in binary form must reproduce the above copyright notice, >> + * this list of conditions and the following disclaimer in the documentation >> + * and/or other materials provided with the distribution. >> + * >> + * Neither the name of ARM nor the names of its contributors may be used >> + * to endorse or promote products derived from this software without specific >> + * prior written permission. >> + * >> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" >> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE >> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE >> + * POSSIBILITY OF SUCH DAMAGE. > This should be probably in SPDX format. Like previous reply, I don't know how to deal with this license, do you mean I can use SPDX license without any information about the origin License? Thanks, - Kever > > >> + */ >> + >> +#ifndef __BL_COMMON_H__ >> +#define __BL_COMMON_H__ >> + >> +#define SECURE 0x0 >> +#define NON_SECURE 0x1 >> +#define sec_state_is_valid(s) (((s) == SECURE) || ((s) == NON_SECURE)) >> + >> +#define UP 1 >> +#define DOWN 0 >> + >> +/******************************************************************************* >> + * Constants to identify the location of a memory region in a given memory >> + * layout. >> +******************************************************************************/ >> +#define TOP 0x1 >> +#define BOTTOM !TOP >> + >> +/******************************************************************************* >> + * Constants that allow assembler code to access members of and the >> + * 'entry_point_info' structure at their correct offsets. >> + ******************************************************************************/ >> +#define ENTRY_POINT_INFO_PC_OFFSET 0x08 >> +#define ENTRY_POINT_INFO_ARGS_OFFSET 0x18 >> + >> +/* The following are used to set/get image attributes. */ >> +#define PARAM_EP_SECURITY_MASK (0x1) >> + >> +#define GET_SECURITY_STATE(x) (x & PARAM_EP_SECURITY_MASK) >> +#define SET_SECURITY_STATE(x, security) \ >> + ((x) = ((x) & ~PARAM_EP_SECURITY_MASK) | (security)) >> + >> + >> +/* >> + * The following are used for image state attributes. >> + * Image can only be in one of the following state. >> + */ >> +#define IMAGE_STATE_RESET 0 >> +#define IMAGE_STATE_COPIED 1 >> +#define IMAGE_STATE_COPYING 2 >> +#define IMAGE_STATE_AUTHENTICATED 3 >> +#define IMAGE_STATE_EXECUTED 4 >> +#define IMAGE_STATE_INTERRUPTED 5 >> + >> +#define EP_SECURE 0x0 >> +#define EP_NON_SECURE 0x1 >> + >> +#define EP_EE_MASK 0x2 >> +#define EP_EE_LITTLE 0x0 >> +#define EP_EE_BIG 0x2 >> +#define EP_GET_EE(x) (x & EP_EE_MASK) >> +#define EP_SET_EE(x, ee) ((x) = ((x) & ~EP_EE_MASK) | (ee)) >> + >> +#define EP_ST_MASK 0x4 >> +#define EP_ST_DISABLE 0x0 >> +#define EP_ST_ENABLE 0x4 >> +#define EP_GET_ST(x) (x & EP_ST_MASK) >> +#define EP_SET_ST(x, ee) ((x) = ((x) & ~EP_ST_MASK) | (ee)) >> + >> +#define EP_EXE_MASK 0x8 >> +#define NON_EXECUTABLE 0x0 >> +#define EXECUTABLE 0x8 >> +#define EP_GET_EXE(x) (x & EP_EXE_MASK) >> +#define EP_SET_EXE(x, ee) ((x) = ((x) & ~EP_EXE_MASK) | (ee)) >> + >> +#define PARAM_EP 0x01 >> +#define PARAM_IMAGE_BINARY 0x02 >> +#define PARAM_BL31 0x03 >> + >> +#define VERSION_1 0x01 >> + >> +#define INVALID_IMAGE_ID (0xFFFFFFFF) >> + >> +#define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \ >> + (_p)->h.type = (uint8_t)(_type); \ >> + (_p)->h.version = (uint8_t)(_ver); \ >> + (_p)->h.size = (uint16_t)sizeof(*_p); \ >> + (_p)->h.attr = (uint32_t)(_attr) ; \ >> + } while (0) >> + >> +/* Following is used for populating structure members statically. */ >> +#define SET_STATIC_PARAM_HEAD(_p, _type, _ver, _p_type, _attr) \ >> + ._p.h.type = (uint8_t)(_type), \ >> + ._p.h.version = (uint8_t)(_ver), \ >> + ._p.h.size = (uint16_t)sizeof(_p_type), \ >> + ._p.h.attr = (uint32_t)(_attr) >> + >> +#define MODE_RW_SHIFT 0x4 >> +#define MODE_RW_MASK 0x1 >> +#define MODE_RW_64 0x0 >> +#define MODE_RW_32 0x1 >> + >> +#define MODE_EL_SHIFT 0x2 >> +#define MODE_EL_MASK 0x3 >> +#define MODE_EL3 0x3 >> +#define MODE_EL2 0x2 >> +#define MODE_EL1 0x1 >> +#define MODE_EL0 0x0 >> + >> +#define MODE_SP_SHIFT 0x0 >> +#define MODE_SP_MASK 0x1 >> +#define MODE_SP_EL0 0x0 >> +#define MODE_SP_ELX 0x1 >> + >> +#define SPSR_DAIF_SHIFT 6 >> +#define SPSR_DAIF_MASK 0x0f >> + >> +#define DAIF_FIQ_BIT (1<<0) >> +#define DAIF_IRQ_BIT (1<<0) >> +#define DAIF_ABT_BIT (1<<0) >> +#define DAIF_DBG_BIT (1<<0) >> +#define DISABLE_ALL_EXECPTIONS \ >> + (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) >> + >> +#define SPSR_64(el, sp, daif) \ >> + (MODE_RW_64 << MODE_RW_SHIFT | \ >> + ((el) & MODE_EL_MASK) << MODE_EL_SHIFT | \ >> + ((sp) & MODE_SP_MASK) << MODE_SP_SHIFT | \ >> + ((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT) >> + >> +/******************************************************************************* >> + * Constants to indicate type of exception to the common exception handler. >> + ******************************************************************************/ >> +#define SYNC_EXCEPTION_SP_EL0 0x0 >> +#define IRQ_SP_EL0 0x1 >> +#define FIQ_SP_EL0 0x2 >> +#define SERROR_SP_EL0 0x3 >> +#define SYNC_EXCEPTION_SP_ELX 0x4 >> +#define IRQ_SP_ELX 0x5 >> +#define FIQ_SP_ELX 0x6 >> +#define SERROR_SP_ELX 0x7 >> +#define SYNC_EXCEPTION_AARCH64 0x8 >> +#define IRQ_AARCH64 0x9 >> +#define FIQ_AARCH64 0xa >> +#define SERROR_AARCH64 0xb >> +#define SYNC_EXCEPTION_AARCH32 0xc >> +#define IRQ_AARCH32 0xd >> +#define FIQ_AARCH32 0xe >> +#define SERROR_AARCH32 0xf >> + >> +#define SPSR_USE_L 0 >> +#define SPSR_USE_H 1 >> +#define SPSR_L_H_MASK 1 >> +#define SPSR_M_SHIFT 4 >> +#define SPSR_ERET_32 (1 << SPSR_M_SHIFT) >> +#define SPSR_ERET_64 (0 << SPSR_M_SHIFT) >> +#define SPSR_FIQ (1 << 6) >> +#define SPSR_IRQ (1 << 7) >> +#define SPSR_SERROR (1 << 8) >> +#define SPSR_DEBUG (1 << 9) >> +#define SPSR_EXCEPTION_MASK (SPSR_FIQ | SPSR_IRQ | SPSR_SERROR | SPSR_DEBUG) >> + >> +#ifndef __ASSEMBLY__ >> + >> +/******************************************************************************* >> + * Structure used for telling the next BL how much of a particular type of >> + * memory is available for its use and how much is already used. >> + ******************************************************************************/ >> +struct aapcs64_params_t { >> + unsigned long arg0; >> + unsigned long arg1; >> + unsigned long arg2; >> + unsigned long arg3; >> + unsigned long arg4; >> + unsigned long arg5; >> + unsigned long arg6; >> + unsigned long arg7; >> +}; >> + >> +/*************************************************************************** >> + * This structure provides version information and the size of the >> + * structure, attributes for the structure it represents >> + ***************************************************************************/ >> +struct param_header_t { >> + uint8_t type; /* type of the structure */ >> + uint8_t version; /* version of this structure */ >> + uint16_t size; /* size of this structure in bytes */ >> + uint32_t attr; /* attributes: unused bits SBZ */ >> +}; >> + >> +/***************************************************************************** >> + * This structure represents the superset of information needed while >> + * switching exception levels. The only two mechanisms to do so are >> + * ERET & SMC. Security state is indicated using bit zero of header >> + * attribute >> + * NOTE: BL1 expects entrypoint followed by spsr at an offset from the start >> + * of this structure defined by the macro `ENTRY_POINT_INFO_PC_OFFSET` while >> + * processing SMC to jump to BL31. >> + *****************************************************************************/ >> +struct entry_point_info_t { >> + struct param_header_t h; >> + uintptr_t pc; >> + uint32_t spsr; >> + struct aapcs64_params_t args; >> +}; >> + >> +/***************************************************************************** >> + * Image info binary provides information from the image loader that >> + * can be used by the firmware to manage available trusted RAM. >> + * More advanced firmware image formats can provide additional >> + * information that enables optimization or greater flexibility in the >> + * common firmware code >> + *****************************************************************************/ >> +struct atf_image_info_t { >> + struct param_header_t h; >> + uintptr_t image_base; /* physical address of base of image */ >> + uint32_t image_size; /* bytes read from image file */ >> +}; >> + >> +/***************************************************************************** >> + * The image descriptor struct definition. >> + *****************************************************************************/ >> +struct image_desc_t { >> + /* Contains unique image id for the image. */ >> + unsigned int image_id; >> + /* >> + * This member contains Image state information. >> + * Refer IMAGE_STATE_XXX defined above. >> + */ >> + unsigned int state; >> + uint32_t copied_size; /* image size copied in blocks */ >> + struct atf_image_info_t atf_image_info; >> + struct entry_point_info_t ep_info; >> +}; >> + >> +/******************************************************************************* >> + * This structure represents the superset of information that can be passed to >> + * BL31 e.g. while passing control to it from BL2. The BL32 parameters will be >> + * populated only if BL2 detects its presence. A pointer to a structure of this >> + * type should be passed in X0 to BL31's cold boot entrypoint. >> + * >> + * Use of this structure and the X0 parameter is not mandatory: the BL31 >> + * platform code can use other mechanisms to provide the necessary information >> + * about BL32 and BL33 to the common and SPD code. >> + * >> + * BL31 image information is mandatory if this structure is used. If either of >> + * the optional BL32 and BL33 image information is not provided, this is >> + * indicated by the respective image_info pointers being zero. >> + ******************************************************************************/ >> +struct bl31_params_t { >> + struct param_header_t h; >> + struct atf_image_info_t *bl31_image_info; >> + struct entry_point_info_t *bl32_ep_info; >> + struct atf_image_info_t *bl32_image_info; >> + struct entry_point_info_t *bl33_ep_info; >> + struct atf_image_info_t *bl33_image_info; >> +}; >> + >> +/******************************************************************************* >> + * This structure represents the superset of information that is passed to >> + * BL31, e.g. while passing control to it from BL2, bl31_params >> + * and other platform specific params >> + ******************************************************************************/ >> +struct bl2_to_bl31_params_mem_t { >> + struct bl31_params_t bl31_params; >> + struct atf_image_info_t bl31_image_info; >> + struct atf_image_info_t bl32_image_info; >> + struct atf_image_info_t bl33_image_info; >> + struct entry_point_info_t bl33_ep_info; >> + struct entry_point_info_t bl32_ep_info; >> + struct entry_point_info_t bl31_ep_info; >> +}; >> + >> +#endif /*__ASSEMBLY__*/ >> + >> +#endif /* __BL_COMMON_H__ */ >> diff --git a/include/spl.h b/include/spl.h >> index 918c464..ab5eaca 100644 >> --- a/include/spl.h >> +++ b/include/spl.h >> @@ -251,4 +251,5 @@ int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr); >> int spl_mmc_load_image(struct spl_image_info *spl_image, >> struct spl_boot_device *bootdev); >> >> +void bl31_entry(void); >> #endif >> > Thanks, > Michal > > > >