GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,82 @@
if ARCH_IMX8
config AHAB_BOOT
bool "Support i.MX8 AHAB features"
help
This option enables the support for AHAB secure boot.
config IMX8
bool
config MU_BASE_SPL
hex "MU base address used in SPL"
default 0x5d1b0000
help
SPL runs in EL3 mode, it use MU0_A to communicate with SCU.
So we could not reuse the one in dts which is for normal U-Boot.
config IMX8QM
select IMX8
select SUPPORT_SPL
bool
config IMX8QXP
select IMX8
select SUPPORT_SPL
bool
config SYS_SOC
default "imx8"
config SPL_LOAD_IMX_CONTAINER
bool "Enable SPL loading U-Boot as a i.MX Container image"
depends on SPL
help
This is to let SPL could load i.MX8 Container image
config IMX_CONTAINER_CFG
string "i.MX Container config file"
depends on SPL
help
This is to specific the cfg file for generating container
image which will be loaded by SPL.
choice
prompt "i.MX8 board select"
optional
config TARGET_APALIS_IMX8
bool "Support Apalis iMX8 module"
select BOARD_LATE_INIT
select IMX8QM
config TARGET_COLIBRI_IMX8X
bool "Support Colibri iMX8X module"
select BOARD_LATE_INIT
select IMX8QXP
config TARGET_IMX8QM_MEK
bool "Support i.MX8QM MEK board"
select BOARD_LATE_INIT
select IMX8QM
config TARGET_IMX8QM_ROM7720_A1
bool "Support i.MX8QM ROM-7720-A1"
select BOARD_LATE_INIT
select SUPPORT_SPL
select IMX8QM
config TARGET_IMX8QXP_MEK
bool "Support i.MX8QXP MEK board"
select BOARD_LATE_INIT
select IMX8QXP
endchoice
source "board/freescale/imx8qm_mek/Kconfig"
source "board/freescale/imx8qxp_mek/Kconfig"
source "board/advantech/imx8qm_rom7720_a1/Kconfig"
source "board/toradex/apalis-imx8/Kconfig"
source "board/toradex/colibri-imx8x/Kconfig"
endif
@@ -0,0 +1,12 @@
#
# Copyright 2018 NXP
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += cpu.o iomux.o misc.o lowlevel_init.o
obj-$(CONFIG_OF_SYSTEM_SETUP) += fdt.o
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += image.o parse-container.o
endif
@@ -0,0 +1,347 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018-2019 NXP
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/sci/sci.h>
#include <asm/mach-imx/sys_proto.h>
#include <asm/arch-imx/cpu.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/image.h>
#include <console.h>
DECLARE_GLOBAL_DATA_PTR;
#define SEC_SECURE_RAM_BASE (0x31800000UL)
#define SEC_SECURE_RAM_END_BASE (SEC_SECURE_RAM_BASE + 0xFFFFUL)
#define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE (0x60000000UL)
#define SECO_PT 2U
static inline bool check_in_dram(ulong addr)
{
int i;
bd_t *bd = gd->bd;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
if (bd->bi_dram[i].size) {
if (addr >= bd->bi_dram[i].start &&
addr < (bd->bi_dram[i].start + bd->bi_dram[i].size))
return true;
}
}
return false;
}
int authenticate_os_container(ulong addr)
{
struct container_hdr *phdr;
int i, ret = 0;
int err;
sc_rm_mr_t mr;
sc_faddr_t start, end;
u16 length;
struct boot_img_t *img;
unsigned long s, e;
if (addr % 4) {
puts("Error: Image's address is not 4 byte aligned\n");
return -EINVAL;
}
if (!check_in_dram(addr)) {
puts("Error: Image's address is invalid\n");
return -EINVAL;
}
phdr = (struct container_hdr *)addr;
if (phdr->tag != 0x87 && phdr->version != 0x0) {
printf("Error: Wrong container header\n");
return -EFAULT;
}
if (!phdr->num_images) {
printf("Error: Wrong container, no image found\n");
return -EFAULT;
}
length = phdr->length_lsb + (phdr->length_msb << 8);
debug("container length %u\n", length);
memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)addr,
ALIGN(length, CONFIG_SYS_CACHELINE_SIZE));
err = sc_seco_authenticate(-1, SC_MISC_AUTH_CONTAINER,
SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE);
if (err) {
printf("Authenticate container hdr failed, return %d\n",
err);
ret = -EIO;
goto exit;
}
/* Copy images to dest address */
for (i = 0; i < phdr->num_images; i++) {
img = (struct boot_img_t *)(addr +
sizeof(struct container_hdr) +
i * sizeof(struct boot_img_t));
debug("img %d, dst 0x%llx, src 0x%lx, size 0x%x\n",
i, img->dst, img->offset + addr, img->size);
memcpy((void *)img->dst, (const void *)(img->offset + addr),
img->size);
s = img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
e = ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE);
flush_dcache_range(s, e);
/* Find the memreg and set permission for seco pt */
err = sc_rm_find_memreg(-1, &mr, s, e);
if (err) {
printf("Not found memreg for image: %d, error %d\n",
i, err);
ret = -ENOMEM;
goto exit;
}
err = sc_rm_get_memreg_info(-1, mr, &start, &end);
if (!err)
debug("memreg %u 0x%llx -- 0x%llx\n", mr, start, end);
err = sc_rm_set_memreg_permissions(-1, mr, SECO_PT,
SC_RM_PERM_FULL);
if (err) {
printf("Set permission failed for img %d, error %d\n",
i, err);
ret = -EPERM;
goto exit;
}
err = sc_seco_authenticate(-1, SC_MISC_VERIFY_IMAGE,
(1 << i));
if (err) {
printf("Authenticate img %d failed, return %d\n",
i, err);
ret = -EIO;
}
err = sc_rm_set_memreg_permissions(-1, mr, SECO_PT,
SC_RM_PERM_NONE);
if (err) {
printf("Remove permission failed for img %d, err %d\n",
i, err);
ret = -EPERM;
}
if (ret)
goto exit;
}
exit:
if (sc_seco_authenticate(-1, SC_MISC_REL_CONTAINER, 0) != SC_ERR_NONE)
printf("Error: release container failed!\n");
return ret;
}
static int do_authenticate(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
ulong addr;
if (argc < 2)
return CMD_RET_USAGE;
addr = simple_strtoul(argv[1], NULL, 16);
printf("Authenticate OS container at 0x%lx\n", addr);
if (authenticate_os_container(addr))
return CMD_RET_FAILURE;
return CMD_RET_SUCCESS;
}
static void display_life_cycle(u16 lc)
{
printf("Lifecycle: 0x%04X, ", lc);
switch (lc) {
case 0x1:
printf("Pristine\n\n");
break;
case 0x2:
printf("Fab\n\n");
break;
case 0x8:
printf("Open\n\n");
break;
case 0x20:
printf("NXP closed\n\n");
break;
case 0x80:
printf("OEM closed\n\n");
break;
case 0x100:
printf("Partial field return\n\n");
break;
case 0x200:
printf("Full field return\n\n");
break;
case 0x400:
printf("No return\n\n");
break;
default:
printf("Unknown\n\n");
break;
}
}
#define AHAB_AUTH_CONTAINER_REQ 0x87
#define AHAB_VERIFY_IMAGE_REQ 0x88
#define AHAB_NO_AUTHENTICATION_IND 0xee
#define AHAB_BAD_KEY_HASH_IND 0xfa
#define AHAB_INVALID_KEY_IND 0xf9
#define AHAB_BAD_SIGNATURE_IND 0xf0
#define AHAB_BAD_HASH_IND 0xf1
static void display_ahab_auth_event(u32 event)
{
u8 cmd = (event >> 16) & 0xff;
u8 resp_ind = (event >> 8) & 0xff;
switch (cmd) {
case AHAB_AUTH_CONTAINER_REQ:
printf("\tCMD = AHAB_AUTH_CONTAINER_REQ (0x%02X)\n", cmd);
printf("\tIND = ");
break;
case AHAB_VERIFY_IMAGE_REQ:
printf("\tCMD = AHAB_VERIFY_IMAGE_REQ (0x%02X)\n", cmd);
printf("\tIND = ");
break;
default:
return;
}
switch (resp_ind) {
case AHAB_NO_AUTHENTICATION_IND:
printf("AHAB_NO_AUTHENTICATION_IND (0x%02X)\n\n", resp_ind);
break;
case AHAB_BAD_KEY_HASH_IND:
printf("AHAB_BAD_KEY_HASH_IND (0x%02X)\n\n", resp_ind);
break;
case AHAB_INVALID_KEY_IND:
printf("AHAB_INVALID_KEY_IND (0x%02X)\n\n", resp_ind);
break;
case AHAB_BAD_SIGNATURE_IND:
printf("AHAB_BAD_SIGNATURE_IND (0x%02X)\n\n", resp_ind);
break;
case AHAB_BAD_HASH_IND:
printf("AHAB_BAD_HASH_IND (0x%02X)\n\n", resp_ind);
break;
default:
printf("Unknown Indicator (0x%02X)\n\n", resp_ind);
break;
}
}
static int do_ahab_status(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
int err;
u8 idx = 0U;
u32 event;
u16 lc;
err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
if (err != SC_ERR_NONE) {
printf("Error in get lifecycle\n");
return -EIO;
}
display_life_cycle(lc);
err = sc_seco_get_event(-1, idx, &event);
while (err == SC_ERR_NONE) {
printf("SECO Event[%u] = 0x%08X\n", idx, event);
display_ahab_auth_event(event);
idx++;
err = sc_seco_get_event(-1, idx, &event);
}
if (idx == 0)
printf("No SECO Events Found!\n\n");
return 0;
}
static int confirm_close(void)
{
puts("Warning: Please ensure your sample is in NXP closed state, "
"OEM SRK hash has been fused, \n"
" and you are able to boot a signed image successfully "
"without any SECO events reported.\n"
" If not, your sample will be unrecoverable.\n"
"\nReally perform this operation? <y/N>\n");
if (confirm_yesno())
return 1;
puts("Ahab close aborted\n");
return 0;
}
static int do_ahab_close(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
int err;
u16 lc;
if (!confirm_close())
return -EACCES;
err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
if (err != SC_ERR_NONE) {
printf("Error in get lifecycle\n");
return -EIO;
}
if (lc != 0x20) {
puts("Current lifecycle is NOT NXP closed, can't move to OEM closed\n");
display_life_cycle(lc);
return -EPERM;
}
err = sc_seco_forward_lifecycle(-1, 16);
if (err != SC_ERR_NONE) {
printf("Error in forward lifecycle to OEM closed\n");
return -EIO;
}
printf("Change to OEM closed successfully\n");
return 0;
}
U_BOOT_CMD(auth_cntr, CONFIG_SYS_MAXARGS, 1, do_authenticate,
"autenticate OS container via AHAB",
"addr\n"
"addr - OS container hex address\n"
);
U_BOOT_CMD(ahab_status, CONFIG_SYS_MAXARGS, 1, do_ahab_status,
"display AHAB lifecycle and events from seco",
""
);
U_BOOT_CMD(ahab_close, CONFIG_SYS_MAXARGS, 1, do_ahab_close,
"Change AHAB lifecycle to OEM closed",
""
);
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018 NXP
*/
#include <common.h>
#include <linux/errno.h>
#include <asm/arch/clock.h>
DECLARE_GLOBAL_DATA_PTR;
u32 mxc_get_clock(enum mxc_clock clk)
{
switch (clk) {
default:
printf("Unsupported mxc_clock %d\n", clk);
break;
}
return 0;
}
@@ -0,0 +1,538 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018 NXP
*/
#include <common.h>
#include <clk.h>
#include <cpu.h>
#include <cpu_func.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/uclass.h>
#include <errno.h>
#include <thermal.h>
#include <asm/arch/sci/sci.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch-imx/cpu.h>
#include <asm/armv8/cpu.h>
#include <asm/armv8/mmu.h>
#include <asm/mach-imx/boot_mode.h>
DECLARE_GLOBAL_DATA_PTR;
#define BT_PASSOVER_TAG 0x504F
struct pass_over_info_t *get_pass_over_info(void)
{
struct pass_over_info_t *p =
(struct pass_over_info_t *)PASS_OVER_INFO_ADDR;
if (p->barker != BT_PASSOVER_TAG ||
p->len != sizeof(struct pass_over_info_t))
return NULL;
return p;
}
int arch_cpu_init(void)
{
#ifdef CONFIG_SPL_BUILD
struct pass_over_info_t *pass_over;
if (is_soc_rev(CHIP_REV_A)) {
pass_over = get_pass_over_info();
if (pass_over && pass_over->g_ap_mu == 0) {
/*
* When ap_mu is 0, means the U-Boot booted
* from first container
*/
sc_misc_boot_status(-1, SC_MISC_BOOT_STATUS_SUCCESS);
}
}
#endif
return 0;
}
int arch_cpu_init_dm(void)
{
struct udevice *devp;
int node, ret;
node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8-mu");
ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp);
if (ret) {
printf("could not get scu %d\n", ret);
return ret;
}
if (is_imx8qm()) {
ret = sc_pm_set_resource_power_mode(-1, SC_R_SMMU,
SC_PM_PW_MODE_ON);
if (ret)
return ret;
}
return 0;
}
int print_bootinfo(void)
{
enum boot_device bt_dev = get_boot_device();
puts("Boot: ");
switch (bt_dev) {
case SD1_BOOT:
puts("SD0\n");
break;
case SD2_BOOT:
puts("SD1\n");
break;
case SD3_BOOT:
puts("SD2\n");
break;
case MMC1_BOOT:
puts("MMC0\n");
break;
case MMC2_BOOT:
puts("MMC1\n");
break;
case MMC3_BOOT:
puts("MMC2\n");
break;
case FLEXSPI_BOOT:
puts("FLEXSPI\n");
break;
case SATA_BOOT:
puts("SATA\n");
break;
case NAND_BOOT:
puts("NAND\n");
break;
case USB_BOOT:
puts("USB\n");
break;
default:
printf("Unknown device %u\n", bt_dev);
break;
}
return 0;
}
enum boot_device get_boot_device(void)
{
enum boot_device boot_dev = SD1_BOOT;
sc_rsrc_t dev_rsrc;
sc_misc_get_boot_dev(-1, &dev_rsrc);
switch (dev_rsrc) {
case SC_R_SDHC_0:
boot_dev = MMC1_BOOT;
break;
case SC_R_SDHC_1:
boot_dev = SD2_BOOT;
break;
case SC_R_SDHC_2:
boot_dev = SD3_BOOT;
break;
case SC_R_NAND:
boot_dev = NAND_BOOT;
break;
case SC_R_FSPI_0:
boot_dev = FLEXSPI_BOOT;
break;
case SC_R_SATA_0:
boot_dev = SATA_BOOT;
break;
case SC_R_USB_0:
case SC_R_USB_1:
case SC_R_USB_2:
boot_dev = USB_BOOT;
break;
default:
break;
}
return boot_dev;
}
#ifdef CONFIG_ENV_IS_IN_MMC
__weak int board_mmc_get_env_dev(int devno)
{
return CONFIG_SYS_MMC_ENV_DEV;
}
int mmc_get_env_dev(void)
{
sc_rsrc_t dev_rsrc;
int devno;
sc_misc_get_boot_dev(-1, &dev_rsrc);
switch (dev_rsrc) {
case SC_R_SDHC_0:
devno = 0;
break;
case SC_R_SDHC_1:
devno = 1;
break;
case SC_R_SDHC_2:
devno = 2;
break;
default:
/* If not boot from sd/mmc, use default value */
return CONFIG_SYS_MMC_ENV_DEV;
}
return board_mmc_get_env_dev(devno);
}
#endif
#define MEMSTART_ALIGNMENT SZ_2M /* Align the memory start with 2MB */
static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start,
sc_faddr_t *addr_end)
{
sc_faddr_t start, end;
int ret;
bool owned;
owned = sc_rm_is_memreg_owned(-1, mr);
if (owned) {
ret = sc_rm_get_memreg_info(-1, mr, &start, &end);
if (ret) {
printf("Memreg get info failed, %d\n", ret);
return -EINVAL;
}
debug("0x%llx -- 0x%llx\n", start, end);
*addr_start = start;
*addr_end = end;
return 0;
}
return -EINVAL;
}
phys_size_t get_effective_memsize(void)
{
sc_rm_mr_t mr;
sc_faddr_t start, end, end1;
int err;
end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
for (mr = 0; mr < 64; mr++) {
err = get_owned_memreg(mr, &start, &end);
if (!err) {
start = roundup(start, MEMSTART_ALIGNMENT);
/* Too small memory region, not use it */
if (start > end)
continue;
/* Find the memory region runs the U-Boot */
if (start >= PHYS_SDRAM_1 && start <= end1 &&
(start <= CONFIG_SYS_TEXT_BASE &&
end >= CONFIG_SYS_TEXT_BASE)) {
if ((end + 1) <= ((sc_faddr_t)PHYS_SDRAM_1 +
PHYS_SDRAM_1_SIZE))
return (end - PHYS_SDRAM_1 + 1);
else
return PHYS_SDRAM_1_SIZE;
}
}
}
return PHYS_SDRAM_1_SIZE;
}
int dram_init(void)
{
sc_rm_mr_t mr;
sc_faddr_t start, end, end1, end2;
int err;
end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE;
for (mr = 0; mr < 64; mr++) {
err = get_owned_memreg(mr, &start, &end);
if (!err) {
start = roundup(start, MEMSTART_ALIGNMENT);
/* Too small memory region, not use it */
if (start > end)
continue;
if (start >= PHYS_SDRAM_1 && start <= end1) {
if ((end + 1) <= end1)
gd->ram_size += end - start + 1;
else
gd->ram_size += end1 - start;
} else if (start >= PHYS_SDRAM_2 && start <= end2) {
if ((end + 1) <= end2)
gd->ram_size += end - start + 1;
else
gd->ram_size += end2 - start;
}
}
}
/* If error, set to the default value */
if (!gd->ram_size) {
gd->ram_size = PHYS_SDRAM_1_SIZE;
gd->ram_size += PHYS_SDRAM_2_SIZE;
}
return 0;
}
static void dram_bank_sort(int current_bank)
{
phys_addr_t start;
phys_size_t size;
while (current_bank > 0) {
if (gd->bd->bi_dram[current_bank - 1].start >
gd->bd->bi_dram[current_bank].start) {
start = gd->bd->bi_dram[current_bank - 1].start;
size = gd->bd->bi_dram[current_bank - 1].size;
gd->bd->bi_dram[current_bank - 1].start =
gd->bd->bi_dram[current_bank].start;
gd->bd->bi_dram[current_bank - 1].size =
gd->bd->bi_dram[current_bank].size;
gd->bd->bi_dram[current_bank].start = start;
gd->bd->bi_dram[current_bank].size = size;
}
current_bank--;
}
}
int dram_init_banksize(void)
{
sc_rm_mr_t mr;
sc_faddr_t start, end, end1, end2;
int i = 0;
int err;
end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE;
for (mr = 0; mr < 64 && i < CONFIG_NR_DRAM_BANKS; mr++) {
err = get_owned_memreg(mr, &start, &end);
if (!err) {
start = roundup(start, MEMSTART_ALIGNMENT);
if (start > end) /* Small memory region, no use it */
continue;
if (start >= PHYS_SDRAM_1 && start <= end1) {
gd->bd->bi_dram[i].start = start;
if ((end + 1) <= end1)
gd->bd->bi_dram[i].size =
end - start + 1;
else
gd->bd->bi_dram[i].size = end1 - start;
dram_bank_sort(i);
i++;
} else if (start >= PHYS_SDRAM_2 && start <= end2) {
gd->bd->bi_dram[i].start = start;
if ((end + 1) <= end2)
gd->bd->bi_dram[i].size =
end - start + 1;
else
gd->bd->bi_dram[i].size = end2 - start;
dram_bank_sort(i);
i++;
}
}
}
/* If error, set to the default value */
if (!i) {
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
}
return 0;
}
static u64 get_block_attrs(sc_faddr_t addr_start)
{
u64 attr = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN;
if ((addr_start >= PHYS_SDRAM_1 &&
addr_start <= ((sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE)) ||
(addr_start >= PHYS_SDRAM_2 &&
addr_start <= ((sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE)))
return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE);
return attr;
}
static u64 get_block_size(sc_faddr_t addr_start, sc_faddr_t addr_end)
{
sc_faddr_t end1, end2;
end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE;
if (addr_start >= PHYS_SDRAM_1 && addr_start <= end1) {
if ((addr_end + 1) > end1)
return end1 - addr_start;
} else if (addr_start >= PHYS_SDRAM_2 && addr_start <= end2) {
if ((addr_end + 1) > end2)
return end2 - addr_start;
}
return (addr_end - addr_start + 1);
}
#define MAX_PTE_ENTRIES 512
#define MAX_MEM_MAP_REGIONS 16
static struct mm_region imx8_mem_map[MAX_MEM_MAP_REGIONS];
struct mm_region *mem_map = imx8_mem_map;
void enable_caches(void)
{
sc_rm_mr_t mr;
sc_faddr_t start, end;
int err, i;
/* Create map for registers access from 0x1c000000 to 0x80000000*/
imx8_mem_map[0].virt = 0x1c000000UL;
imx8_mem_map[0].phys = 0x1c000000UL;
imx8_mem_map[0].size = 0x64000000UL;
imx8_mem_map[0].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN;
i = 1;
for (mr = 0; mr < 64 && i < MAX_MEM_MAP_REGIONS; mr++) {
err = get_owned_memreg(mr, &start, &end);
if (!err) {
imx8_mem_map[i].virt = start;
imx8_mem_map[i].phys = start;
imx8_mem_map[i].size = get_block_size(start, end);
imx8_mem_map[i].attrs = get_block_attrs(start);
i++;
}
}
if (i < MAX_MEM_MAP_REGIONS) {
imx8_mem_map[i].size = 0;
imx8_mem_map[i].attrs = 0;
} else {
puts("Error, need more MEM MAP REGIONS reserved\n");
icache_enable();
return;
}
for (i = 0; i < MAX_MEM_MAP_REGIONS; i++) {
debug("[%d] vir = 0x%llx phys = 0x%llx size = 0x%llx attrs = 0x%llx\n",
i, imx8_mem_map[i].virt, imx8_mem_map[i].phys,
imx8_mem_map[i].size, imx8_mem_map[i].attrs);
}
icache_enable();
dcache_enable();
}
#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
u64 get_page_table_size(void)
{
u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
u64 size = 0;
/*
* For each memory region, the max table size:
* 2 level 3 tables + 2 level 2 tables + 1 level 1 table
*/
size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt;
/*
* We need to duplicate our page table once to have an emergency pt to
* resort to when splitting page tables later on
*/
size *= 2;
/*
* We may need to split page tables later on if dcache settings change,
* so reserve up to 4 (random pick) page tables for that.
*/
size += one_pt * 4;
return size;
}
#endif
#if defined(CONFIG_IMX8QM)
#define FUSE_MAC0_WORD0 452
#define FUSE_MAC0_WORD1 453
#define FUSE_MAC1_WORD0 454
#define FUSE_MAC1_WORD1 455
#elif defined(CONFIG_IMX8QXP)
#define FUSE_MAC0_WORD0 708
#define FUSE_MAC0_WORD1 709
#define FUSE_MAC1_WORD0 710
#define FUSE_MAC1_WORD1 711
#endif
void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
{
u32 word[2], val[2] = {};
int i, ret;
if (dev_id == 0) {
word[0] = FUSE_MAC0_WORD0;
word[1] = FUSE_MAC0_WORD1;
} else {
word[0] = FUSE_MAC1_WORD0;
word[1] = FUSE_MAC1_WORD1;
}
for (i = 0; i < 2; i++) {
ret = sc_misc_otp_fuse_read(-1, word[i], &val[i]);
if (ret < 0)
goto err;
}
mac[0] = val[0];
mac[1] = val[0] >> 8;
mac[2] = val[0] >> 16;
mac[3] = val[0] >> 24;
mac[4] = val[1];
mac[5] = val[1] >> 8;
debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n",
__func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return;
err:
printf("%s: fuse %d, err: %d\n", __func__, word[i], ret);
}
u32 get_cpu_rev(void)
{
u32 id = 0, rev = 0;
int ret;
ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id);
if (ret)
return 0;
rev = (id >> 5) & 0xf;
id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */
return (id << 12) | rev;
}
@@ -0,0 +1,292 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 NXP
*/
#include <common.h>
#include <asm/arch/sci/sci.h>
#include <asm/arch/sys_proto.h>
#include <dm/ofnode.h>
#include <fdt_support.h>
DECLARE_GLOBAL_DATA_PTR;
static bool check_owned_resource(sc_rsrc_t rsrc_id)
{
bool owned;
owned = sc_rm_is_resource_owned(-1, rsrc_id);
return owned;
}
static int disable_fdt_node(void *blob, int nodeoffset)
{
int rc, ret;
const char *status = "disabled";
do {
rc = fdt_setprop(blob, nodeoffset, "status", status,
strlen(status) + 1);
if (rc) {
if (rc == -FDT_ERR_NOSPACE) {
ret = fdt_increase_size(blob, 512);
if (ret)
return ret;
}
}
} while (rc == -FDT_ERR_NOSPACE);
return rc;
}
static void update_fdt_with_owned_resources(void *blob)
{
/*
* Traverses the fdt nodes, check its power domain and use
* the resource id in the power domain for checking whether
* it is owned by current partition
*/
struct fdtdec_phandle_args args;
int offset = 0, depth = 0;
u32 rsrc_id;
int rc, i;
for (offset = fdt_next_node(blob, offset, &depth); offset > 0;
offset = fdt_next_node(blob, offset, &depth)) {
debug("Node name: %s, depth %d\n",
fdt_get_name(blob, offset, NULL), depth);
if (!fdt_get_property(blob, offset, "power-domains", NULL)) {
debug(" - ignoring node %s\n",
fdt_get_name(blob, offset, NULL));
continue;
}
if (!fdtdec_get_is_enabled(blob, offset)) {
debug(" - ignoring node %s\n",
fdt_get_name(blob, offset, NULL));
continue;
}
i = 0;
while (true) {
rc = fdtdec_parse_phandle_with_args(blob, offset,
"power-domains",
"#power-domain-cells",
0, i++, &args);
if (rc == -ENOENT) {
break;
} else if (rc) {
printf("Parse power-domains of %s wrong: %d\n",
fdt_get_name(blob, offset, NULL), rc);
continue;
}
rsrc_id = args.args[0];
if (!check_owned_resource(rsrc_id)) {
rc = disable_fdt_node(blob, offset);
if (!rc) {
printf("Disable %s rsrc %u not owned\n",
fdt_get_name(blob, offset, NULL),
rsrc_id);
} else {
printf("Unable to disable %s, err=%s\n",
fdt_get_name(blob, offset, NULL),
fdt_strerror(rc));
}
}
}
}
}
static int config_smmu_resource_sid(int rsrc, int sid)
{
int err;
if (!check_owned_resource(rsrc)) {
printf("%s rsrc[%d] not owned\n", __func__, rsrc);
return -1;
}
err = sc_rm_set_master_sid(-1, rsrc, sid);
debug("set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
if (err != SC_ERR_NONE) {
pr_err("fail set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
return -EINVAL;
}
return 0;
}
static int config_smmu_fdt_device_sid(void *blob, int device_offset, int sid)
{
const char *name = fdt_get_name(blob, device_offset, NULL);
struct fdtdec_phandle_args args;
int rsrc, ret;
int proplen;
const fdt32_t *prop;
int i;
prop = fdt_getprop(blob, device_offset, "fsl,sc_rsrc_id", &proplen);
if (prop) {
int i;
debug("configure node %s sid 0x%x for %d resources\n",
name, sid, (int)(proplen / sizeof(fdt32_t)));
for (i = 0; i < proplen / sizeof(fdt32_t); ++i) {
ret = config_smmu_resource_sid(fdt32_to_cpu(prop[i]),
sid);
if (ret)
return ret;
}
return 0;
}
i = 0;
while (true) {
ret = fdtdec_parse_phandle_with_args(blob, device_offset,
"power-domains",
"#power-domain-cells",
0, i++, &args);
if (ret == -ENOENT) {
break;
} else if (ret) {
printf("Parse power-domains of node %s wrong: %d\n",
fdt_get_name(blob, device_offset, NULL), ret);
continue;
}
debug("configure node %s sid 0x%x rsrc=%d\n",
name, sid, rsrc);
rsrc = args.args[0];
ret = config_smmu_resource_sid(rsrc, sid);
if (ret)
break;
}
return ret;
}
static int config_smmu_fdt(void *blob)
{
int offset, proplen, i, ret;
const fdt32_t *prop;
const char *name;
/* Legacy smmu bindings, still used by xen. */
offset = fdt_node_offset_by_compatible(blob, 0, "arm,mmu-500");
prop = fdt_getprop(blob, offset, "mmu-masters", &proplen);
if (offset > 0 && prop) {
debug("found legacy mmu-masters property\n");
for (i = 0; i < proplen / 8; ++i) {
u32 phandle = fdt32_to_cpu(prop[2 * i]);
int sid = fdt32_to_cpu(prop[2 * i + 1]);
int device_offset;
device_offset = fdt_node_offset_by_phandle(blob,
phandle);
if (device_offset < 0) {
pr_err("Not find device from mmu_masters: %d",
device_offset);
continue;
}
ret = config_smmu_fdt_device_sid(blob, device_offset,
sid);
if (ret)
return ret;
}
/* Ignore new bindings if old bindings found, just like linux. */
return 0;
}
/* Generic smmu bindings */
offset = 0;
while ((offset = fdt_next_node(blob, offset, NULL)) > 0) {
name = fdt_get_name(blob, offset, NULL);
prop = fdt_getprop(blob, offset, "iommus", &proplen);
if (!prop)
continue;
debug("node %s iommus proplen %d\n", name, proplen);
if (proplen == 12) {
int sid = fdt32_to_cpu(prop[1]);
config_smmu_fdt_device_sid(blob, offset, sid);
} else if (proplen != 4) {
debug("node %s ignore unexpected iommus proplen=%d\n",
name, proplen);
}
}
return 0;
}
static int ft_add_optee_node(void *fdt, bd_t *bd)
{
const char *path, *subpath;
int offs;
/*
* No TEE space allocated indicating no TEE running, so no
* need to add optee node in dts
*/
if (!boot_pointer[1])
return 0;
offs = fdt_increase_size(fdt, 512);
if (offs) {
printf("No Space for dtb\n");
return 1;
}
path = "/firmware";
offs = fdt_path_offset(fdt, path);
if (offs < 0) {
path = "/";
offs = fdt_path_offset(fdt, path);
if (offs < 0) {
printf("Could not find root node.\n");
return offs;
}
subpath = "firmware";
offs = fdt_add_subnode(fdt, offs, subpath);
if (offs < 0) {
printf("Could not create %s node.\n", subpath);
return offs;
}
}
subpath = "optee";
offs = fdt_add_subnode(fdt, offs, subpath);
if (offs < 0) {
printf("Could not create %s node.\n", subpath);
return offs;
}
fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz");
fdt_setprop_string(fdt, offs, "method", "smc");
return 0;
}
int ft_system_setup(void *blob, bd_t *bd)
{
int ret;
update_fdt_with_owned_resources(blob);
if (is_imx8qm()) {
ret = config_smmu_fdt(blob);
if (ret)
return ret;
}
return ft_add_optee_node(blob, bd);
}
@@ -0,0 +1,246 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 NXP
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <mmc.h>
#include <spi_flash.h>
#include <nand.h>
#include <asm/arch/image.h>
#include <asm/arch/sys_proto.h>
#include <asm/mach-imx/boot_mode.h>
#define MMC_DEV 0
#define QSPI_DEV 1
#define NAND_DEV 2
#define QSPI_NOR_DEV 3
static int __get_container_size(ulong addr)
{
struct container_hdr *phdr;
struct boot_img_t *img_entry;
struct signature_block_hdr *sign_hdr;
u8 i = 0;
u32 max_offset = 0, img_end;
phdr = (struct container_hdr *)addr;
if (phdr->tag != 0x87 && phdr->version != 0x0) {
debug("Wrong container header\n");
return -EFAULT;
}
max_offset = sizeof(struct container_hdr);
img_entry = (struct boot_img_t *)(addr + sizeof(struct container_hdr));
for (i = 0; i < phdr->num_images; i++) {
img_end = img_entry->offset + img_entry->size;
if (img_end > max_offset)
max_offset = img_end;
debug("img[%u], end = 0x%x\n", i, img_end);
img_entry++;
}
if (phdr->sig_blk_offset != 0) {
sign_hdr = (struct signature_block_hdr *)(addr + phdr->sig_blk_offset);
u16 len = sign_hdr->length_lsb + (sign_hdr->length_msb << 8);
if (phdr->sig_blk_offset + len > max_offset)
max_offset = phdr->sig_blk_offset + len;
debug("sigblk, end = 0x%x\n", phdr->sig_blk_offset + len);
}
return max_offset;
}
static int get_container_size(void *dev, int dev_type, unsigned long offset)
{
u8 *buf = malloc(CONTAINER_HDR_ALIGNMENT);
int ret = 0;
if (!buf) {
printf("Malloc buffer failed\n");
return -ENOMEM;
}
#ifdef CONFIG_SPL_MMC_SUPPORT
if (dev_type == MMC_DEV) {
unsigned long count = 0;
struct mmc *mmc = (struct mmc *)dev;
count = blk_dread(mmc_get_blk_desc(mmc),
offset / mmc->read_bl_len,
CONTAINER_HDR_ALIGNMENT / mmc->read_bl_len,
buf);
if (count == 0) {
printf("Read container image from MMC/SD failed\n");
return -EIO;
}
}
#endif
#ifdef CONFIG_SPL_SPI_LOAD
if (dev_type == QSPI_DEV) {
struct spi_flash *flash = (struct spi_flash *)dev;
ret = spi_flash_read(flash, offset,
CONTAINER_HDR_ALIGNMENT, buf);
if (ret != 0) {
printf("Read container image from QSPI failed\n");
return -EIO;
}
}
#endif
#ifdef CONFIG_SPL_NAND_SUPPORT
if (dev_type == NAND_DEV) {
ret = nand_spl_load_image(offset, CONTAINER_HDR_ALIGNMENT,
buf);
if (ret != 0) {
printf("Read container image from NAND failed\n");
return -EIO;
}
}
#endif
#ifdef CONFIG_SPL_NOR_SUPPORT
if (dev_type == QSPI_NOR_DEV)
memcpy(buf, (const void *)offset, CONTAINER_HDR_ALIGNMENT);
#endif
ret = __get_container_size((ulong)buf);
free(buf);
return ret;
}
static unsigned long get_boot_device_offset(void *dev, int dev_type)
{
unsigned long offset = 0;
if (dev_type == MMC_DEV) {
struct mmc *mmc = (struct mmc *)dev;
if (IS_SD(mmc) || mmc->part_config == MMCPART_NOAVAILABLE) {
offset = CONTAINER_HDR_MMCSD_OFFSET;
} else {
u8 part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
if (part == 1 || part == 2) {
if (is_imx8qxp() && is_soc_rev(CHIP_REV_B))
offset = CONTAINER_HDR_MMCSD_OFFSET;
else
offset = CONTAINER_HDR_EMMC_OFFSET;
} else {
offset = CONTAINER_HDR_MMCSD_OFFSET;
}
}
} else if (dev_type == QSPI_DEV) {
offset = CONTAINER_HDR_QSPI_OFFSET;
} else if (dev_type == NAND_DEV) {
offset = CONTAINER_HDR_NAND_OFFSET;
} else if (dev_type == QSPI_NOR_DEV) {
offset = CONTAINER_HDR_QSPI_OFFSET + 0x08000000;
}
return offset;
}
static int get_imageset_end(void *dev, int dev_type)
{
unsigned long offset1 = 0, offset2 = 0;
int value_container[2];
offset1 = get_boot_device_offset(dev, dev_type);
offset2 = CONTAINER_HDR_ALIGNMENT + offset1;
value_container[0] = get_container_size(dev, dev_type, offset1);
if (value_container[0] < 0) {
printf("Parse seco container failed %d\n", value_container[0]);
return value_container[0];
}
debug("seco container size 0x%x\n", value_container[0]);
value_container[1] = get_container_size(dev, dev_type, offset2);
if (value_container[1] < 0) {
debug("Parse scu container failed %d, only seco container\n",
value_container[1]);
/* return seco container total size */
return value_container[0] + offset1;
}
debug("scu container size 0x%x\n", value_container[1]);
return value_container[1] + offset2;
}
#ifdef CONFIG_SPL_SPI_LOAD
unsigned long spl_spi_get_uboot_offs(struct spi_flash *flash)
{
int end;
end = get_imageset_end(flash, QSPI_DEV);
end = ROUND(end, SZ_1K);
printf("Load image from QSPI 0x%x\n", end);
return end;
}
#endif
#ifdef CONFIG_SPL_MMC_SUPPORT
unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
{
int end;
end = get_imageset_end(mmc, MMC_DEV);
end = ROUND(end, SZ_1K);
printf("Load image from MMC/SD 0x%x\n", end);
return end / mmc->read_bl_len;
}
#endif
#ifdef CONFIG_SPL_NAND_SUPPORT
uint32_t spl_nand_get_uboot_raw_page(void)
{
int end;
end = get_imageset_end((void *)NULL, NAND_DEV);
end = ROUND(end, SZ_16K);
printf("Load image from NAND 0x%x\n", end);
return end;
}
#endif
#ifdef CONFIG_SPL_NOR_SUPPORT
unsigned long spl_nor_get_uboot_base(void)
{
int end;
/* Calculate the image set end,
* if it is less than CONFIG_SYS_UBOOT_BASE(0x8281000),
* we use CONFIG_SYS_UBOOT_BASE
* Otherwise, use the calculated address
*/
end = get_imageset_end((void *)NULL, QSPI_NOR_DEV);
if (end <= CONFIG_SYS_UBOOT_BASE)
end = CONFIG_SYS_UBOOT_BASE;
else
end = ROUND(end, SZ_1K);
printf("Load image from NOR 0x%x\n", end);
return end;
}
#endif
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018 NXP
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/iomux.h>
#include <asm/arch/sci/sci.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* configures a single pad in the iomuxer
*/
void imx8_iomux_setup_pad(iomux_cfg_t pad)
{
sc_pad_t pin_id = pad & PIN_ID_MASK;
int ret;
u32 val = (u32)((pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT);
val |= PADRING_IFMUX_EN_MASK;
val |= PADRING_GP_EN_MASK;
ret = sc_pad_set(-1, pin_id, val);
if (ret)
printf("sc_pad_set failed!, pin: %u, val: 0x%x\n", pin_id, val);
debug("iomux: pin %d, val = 0x%x\n", pin_id, val);
}
/* configures a list of pads within declared with IOMUX_PADS macro */
void imx8_iomux_setup_multiple_pads(iomux_cfg_t const *pad_list, u32 count)
{
iomux_cfg_t const *p = pad_list;
int i;
for (i = 0; i < count; i++) {
imx8_iomux_setup_pad(*p);
p++;
}
}
@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2019 NXP
*/
#include <config.h>
.align 8
.global boot_pointer
boot_pointer:
.space 32
/*
* Routine: save_boot_params (called after reset from start.S)
*/
.global save_boot_params
save_boot_params:
/* The firmware provided ATAG/FDT address can be found in r2/x0 */
adr x0, boot_pointer
stp x1, x2, [x0], #16
stp x3, x4, [x0], #16
/*
* We use absolute address not PC relative address for return.
* When running SPL on iMX8, the A core starts at address 0,
* an alias to OCRAM 0x100000, our linker address for SPL is
* from 0x100000. So using absolute address can jump to the OCRAM
* address from the alias. The alias only map first 96KB of OCRAM,
* so this require the SPL size can't beyond 96KB.
* But when using SPL DM, the size increase significantly and
* always beyonds 96KB. That's why we have to jump to OCRAM.
* Normal u-boot also runs into this codes, but there is no impact.
*/
ldr x1, =save_boot_params_ret
br x1
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: GPL-2.0+
#include <common.h>
#include <asm/arch/sci/sci.h>
#include <asm/mach-imx/sys_proto.h>
int sc_pm_setup_uart(sc_rsrc_t uart_rsrc, sc_pm_clock_rate_t clk_rate)
{
sc_pm_clock_rate_t rate = clk_rate;
int ret;
/* Power up UARTn */
ret = sc_pm_set_resource_power_mode(-1, uart_rsrc, SC_PM_PW_MODE_ON);
if (ret)
return ret;
/* Set UARTn clock root to 'rate' MHz */
ret = sc_pm_set_clock_rate(-1, uart_rsrc, SC_PM_CLK_PER, &rate);
if (ret)
return ret;
/* Enable UARTn clock root */
ret = sc_pm_clock_enable(-1, uart_rsrc, SC_PM_CLK_PER, true, false);
if (ret)
return ret;
return 0;
}
#define FSL_SIP_BUILDINFO 0xC2000003
#define FSL_SIP_BUILDINFO_GET_COMMITHASH 0x00
void build_info(void)
{
u32 seco_build = 0, seco_commit = 0;
u32 sc_build = 0, sc_commit = 0;
ulong atf_commit = 0;
/* Get SCFW build and commit id */
sc_misc_build_info(-1, &sc_build, &sc_commit);
if (!sc_build) {
printf("SCFW does not support build info\n");
sc_commit = 0; /* Display 0 if build info not supported */
}
/* Get SECO FW build and commit id */
sc_seco_build_info(-1, &seco_build, &seco_commit);
if (!seco_build) {
debug("SECO FW does not support build info\n");
/* Display 0 when the build info is not supported */
seco_commit = 0;
}
/* Get ARM Trusted Firmware commit id */
atf_commit = call_imx_sip(FSL_SIP_BUILDINFO,
FSL_SIP_BUILDINFO_GET_COMMITHASH, 0, 0, 0);
if (atf_commit == 0xffffffff) {
debug("ATF does not support build info\n");
atf_commit = 0x30; /* Display 0 */
}
printf("Build: SCFW %08x, SECO-FW %08x, ATF %s\n",
sc_commit, seco_commit, (char *)&atf_commit);
}
@@ -0,0 +1,207 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018-2019 NXP
*/
#include <common.h>
#include <errno.h>
#include <spl.h>
#include <asm/arch/image.h>
#include <asm/arch/sci/sci.h>
#define SEC_SECURE_RAM_BASE 0x31800000UL
#define SEC_SECURE_RAM_END_BASE (SEC_SECURE_RAM_BASE + 0xFFFFUL)
#define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE 0x60000000UL
#define SECO_PT 2U
#ifdef CONFIG_AHAB_BOOT
static int authenticate_image(struct boot_img_t *img, int image_index)
{
sc_faddr_t start, end;
sc_rm_mr_t mr;
int err;
int ret = 0;
debug("img %d, dst 0x%llx, src 0x%x, size 0x%x\n",
image_index, img->dst, img->offset, img->size);
/* Find the memreg and set permission for seco pt */
err = sc_rm_find_memreg(-1, &mr,
img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1),
ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE));
if (err) {
printf("can't find memreg for image: %d, err %d\n",
image_index, err);
return -ENOMEM;
}
err = sc_rm_get_memreg_info(-1, mr, &start, &end);
if (!err)
debug("memreg %u 0x%llx -- 0x%llx\n", mr, start, end);
err = sc_rm_set_memreg_permissions(-1, mr,
SECO_PT, SC_RM_PERM_FULL);
if (err) {
printf("set permission failed for img %d, error %d\n",
image_index, err);
return -EPERM;
}
err = sc_seco_authenticate(-1, SC_MISC_VERIFY_IMAGE,
1 << image_index);
if (err) {
printf("authenticate img %d failed, return %d\n",
image_index, err);
ret = -EIO;
}
err = sc_rm_set_memreg_permissions(-1, mr,
SECO_PT, SC_RM_PERM_NONE);
if (err) {
printf("remove permission failed for img %d, error %d\n",
image_index, err);
ret = -EPERM;
}
return ret;
}
#endif
static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image,
struct spl_load_info *info,
struct container_hdr *container,
int image_index,
u32 container_sector)
{
struct boot_img_t *images;
ulong sector;
u32 sectors;
if (image_index > container->num_images) {
debug("Invalid image number\n");
return NULL;
}
images = (struct boot_img_t *)((u8 *)container +
sizeof(struct container_hdr));
if (images[image_index].offset % info->bl_len) {
printf("%s: image%d offset not aligned to %u\n",
__func__, image_index, info->bl_len);
return NULL;
}
sectors = roundup(images[image_index].size, info->bl_len) /
info->bl_len;
sector = images[image_index].offset / info->bl_len +
container_sector;
debug("%s: container: %p sector: %lu sectors: %u\n", __func__,
container, sector, sectors);
if (info->read(info, sector, sectors,
(void *)images[image_index].entry) != sectors) {
printf("%s wrong\n", __func__);
return NULL;
}
#ifdef CONFIG_AHAB_BOOT
if (authenticate_image(&images[image_index], image_index)) {
printf("Failed to authenticate image %d\n", image_index);
return NULL;
}
#endif
return &images[image_index];
}
static int read_auth_container(struct spl_image_info *spl_image,
struct spl_load_info *info, ulong sector)
{
struct container_hdr *container = NULL;
u16 length;
u32 sectors;
int i, size, ret = 0;
size = roundup(CONTAINER_HDR_ALIGNMENT, info->bl_len);
sectors = size / info->bl_len;
/*
* It will not override the ATF code, so safe to use it here,
* no need malloc
*/
container = (struct container_hdr *)spl_get_load_buffer(-size, size);
debug("%s: container: %p sector: %lu sectors: %u\n", __func__,
container, sector, sectors);
if (info->read(info, sector, sectors, container) != sectors)
return -EIO;
if (container->tag != 0x87 && container->version != 0x0) {
printf("Wrong container header");
return -ENOENT;
}
if (!container->num_images) {
printf("Wrong container, no image found");
return -ENOENT;
}
length = container->length_lsb + (container->length_msb << 8);
debug("Container length %u\n", length);
if (length > CONTAINER_HDR_ALIGNMENT) {
size = roundup(length, info->bl_len);
sectors = size / info->bl_len;
container = (struct container_hdr *)spl_get_load_buffer(-size, size);
debug("%s: container: %p sector: %lu sectors: %u\n",
__func__, container, sector, sectors);
if (info->read(info, sector, sectors, container) !=
sectors)
return -EIO;
}
#ifdef CONFIG_AHAB_BOOT
memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)container,
ALIGN(length, CONFIG_SYS_CACHELINE_SIZE));
ret = sc_seco_authenticate(-1, SC_MISC_AUTH_CONTAINER,
SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE);
if (ret) {
printf("authenticate container hdr failed, return %d\n", ret);
return ret;
}
#endif
for (i = 0; i < container->num_images; i++) {
struct boot_img_t *image = read_auth_image(spl_image, info,
container, i,
sector);
if (!image) {
ret = -EINVAL;
goto end_auth;
}
if (i == 0) {
spl_image->load_addr = image->dst;
spl_image->entry_point = image->entry;
}
}
end_auth:
#ifdef CONFIG_AHAB_BOOT
if (sc_seco_authenticate(-1, SC_MISC_REL_CONTAINER, 0))
printf("Error: release container failed!\n");
#endif
return ret;
}
int spl_load_imx_container(struct spl_image_info *spl_image,
struct spl_load_info *info, ulong sector)
{
return read_auth_container(spl_image, info, sector);
}