diff --git a/arch/arm64/include/imx9/imx9_ahab.h b/arch/arm64/include/imx9/imx9_ahab.h new file mode 100644 index 00000000000..d79000fb152 --- /dev/null +++ b/arch/arm64/include/imx9/imx9_ahab.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/arm64/include/imx9/imx9_ahab.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_INCLUDE_IMX9_IMX9_AHAB_H +#define __ARCH_ARM64_INCLUDE_IMX9_IMX9_AHAB_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ahab_auth_release + * + * Description: + * Release the current container used by ELE for AHAB. + * + * Returned Value: + * Zero (OK) is returned for success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int ahab_auth_release(void); + +/**************************************************************************** + * Name: ahab_read_auth_image + * + * Description: + * Copy to RAM, then authenticate the image_index image of the container. + * + * Input Parameters: + * container - Pointer to a copy of the AHAB container header in RAM. + * image_index - The index of the image in the current container. + * container_offset - Offset of the container in the boot device. + * + * Returned Value: + * NULL pointer for failure, otherwise a pointer to the beginning of the + * authenticated, image's header. + * + ****************************************************************************/ + +struct boot_img_hdr *ahab_read_auth_image(struct container_hdr *container, + int image_index, + unsigned long container_offset); + +#endif /* __ARCH_ARM64_INCLUDE_IMX9_IMX9_AHAB_H */ diff --git a/arch/arm64/include/imx9/imx9_romapi.h b/arch/arm64/include/imx9/imx9_romapi.h new file mode 100644 index 00000000000..ba7ba2201d1 --- /dev/null +++ b/arch/arm64/include/imx9/imx9_romapi.h @@ -0,0 +1,153 @@ +/**************************************************************************** + * arch/arm64/include/imx9/imx9_romapi.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_INCLUDE_IMX9_IMX9_ROMAPI_H +#define __ARCH_ARM64_INCLUDE_IMX9_IMX9_ROMAPI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* infor_type values for imx9_rom_api_query_boot_infor(). */ + +#define QUERY_ROM_VER 1 +#define QUERY_BOOT_DEV 2 +#define QUERY_PAGE_SZ 3 +#define QUERY_IVT_OFF 4 +#define QUERY_BOOT_STAGE 5 +#define QUERY_IMG_OFF 6 + +/* Native return values from ROM API. */ + +#define ROMAPI_INVALID_PARA 1 +#define ROMAPI_READ_FAILURE 2 +#define ROMAPI_DEVICE_NOT_READY 3 +#define ROMAPI_OUT_OF_DEVICE_MEMORY 4 +#define ROMAPI_OK 0xf0 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Boot device types returned by ROM API (i.MX93). */ + +enum imx9_romapi_bootdev_e +{ + BOOTDEV_SD = 1, + BOOTDEV_MMC = 2, + BOOTDEV_NAND = 3, + BOOTDEV_FLEXSPI_NOR = 4, + BOOTDEV_SPI_NOR = 6, + BOOTDEV_FLEXSPI_NAND = 8, + BOOTDEV_USB = 0xe, + BOOTDEV_MEM_DEV = 0xf, + BOOTDEV_INVALID = 0xff +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_romapi_load_image + * + * Description: + * Use the i.MX9 ROM API, to copy data from the boot device to memory. + * + * Input Parameters: + * dest - Copy destination. + * offset - Offset from boot device to copy from. + * size - Size in bytes to copy. + * + * Returned Value: + * ROMAPI_OK - Success. + * ROMAPI_INVALID_PARA - Invalid parameters. + * ROMAPI_READ_FAILURE - Low level device read failure. + * ROMAPI_DEVICE_NOT_READY - The device isn't initialized or is invalid. + * ROMAPI_OUT_OF_DEVICE_MEMORY - Attempted to read data outside of the + * boot device's memory. + * + ****************************************************************************/ + +uint32_t imx9_romapi_load_image(uint8_t *dest, uint32_t offset, + uint32_t size); + +/**************************************************************************** + * Name: imx9_romapi_query_boot_infor + * + * Description: + * Query information from the ROM API. + * + * Input Parameters: + * infor_type - Type of information to query. + * infor - Points to the word to save the queried information. + * + * Returned Value: + * ROMAPI_OK - Success. + * ROMAPI_INVALID_PARA - Invalid parameters. + * + ****************************************************************************/ + +uint32_t imx9_romapi_query_boot_infor(uint32_t infor_type, uint32_t *infor); + +/**************************************************************************** + * Name: imx9_romapi_get_boot_device + * + * Description: + * Get the boot device type. + * + * Returned Value: + * The device type. + * + ****************************************************************************/ + +enum imx9_romapi_bootdev_e imx9_romapi_get_boot_device(void); + +/**************************************************************************** + * Name: imx9_romapi_get_seq_cntr_base + * + * Description: + * Get the offset in bytes from the boot device of the cntr_idx container. + * The containers are assumed to be sequential in the boot device's + * memory. + * + * Input Parameters: + * image_offset - Image offset of the first container in the boot device. + * pagesize - Pagesize of the boot device. + * cntr_idx - Index of the container. + * + * Returned Value: + * The offset from the boot device in bytes of the cntr_idx container. + * -1 is returned in case of error. + * + ****************************************************************************/ + +int64_t imx9_romapi_get_seq_cntr_base(uint32_t image_offset, + uint32_t pagesize, + uint8_t cntr_idx); +#endif /* __ARCH_ARM64_INCLUDE_IMX9_IMX9_ROMAPI_H */ diff --git a/arch/arm64/src/imx9/Kconfig b/arch/arm64/src/imx9/Kconfig index 3686bfd8b4f..7a2e87f95c4 100644 --- a/arch/arm64/src/imx9/Kconfig +++ b/arch/arm64/src/imx9/Kconfig @@ -91,6 +91,30 @@ config IMX9_DDR_TRAINING ---help--- Perform DDR training to prepare the external memory for use. +config IMX9_ROMAPI + bool "ROM API functionality" + depends on IMX9_BOOTLOADER + default n + ---help--- + Enable wrappers that call the on‑chip ROM API for image download + and boot‑information queries. Required for AHAB secure boot + unless an alternative generic device loader is supplied. + +config IMX9_AHAB_BOOT + bool "Support i.MX9 AHAB features" + depends on IMX9_BOOTLOADER + select IMX9_ROMAPI # AHAB needs a loader; ROMAPI is the default + default n + ---help--- + Enable AHAB functionality + +config IMX_AHAB_CNTR_ADDR + hex "Load address of the AHAB container in RAM" + depends on IMX9_AHAB_BOOT + default 0x80000000 + ---help--- + Physical address where the AHAB container header is loaded into memory. + menu "i.MX9 Peripheral Selection" config IMX9_EDMA diff --git a/arch/arm64/src/imx9/Make.defs b/arch/arm64/src/imx9/Make.defs index ad458a4815b..00f0015015b 100644 --- a/arch/arm64/src/imx9/Make.defs +++ b/arch/arm64/src/imx9/Make.defs @@ -89,6 +89,14 @@ ifeq ($(CONFIG_IMX9_BOOTLOADER), y) CHIP_CSRCS += imx9_ele.c endif +ifeq ($(CONFIG_IMX9_ROMAPI), y) + CHIP_CSRCS += imx9_romapi.c +endif + +ifeq ($(CONFIG_IMX9_AHAB_BOOT), y) + CHIP_CSRCS += imx9_ahab.c +endif + ifeq ($(CONFIG_IMX9_DDR_TRAINING),y) CHIP_CSRCS += $(DDR_CSRCS) endif diff --git a/arch/arm64/src/imx9/imx9_ahab.c b/arch/arm64/src/imx9/imx9_ahab.c new file mode 100644 index 00000000000..23fbe5e767e --- /dev/null +++ b/arch/arm64/src/imx9/imx9_ahab.c @@ -0,0 +1,120 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_ahab.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include "imx9_ele.h" +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +struct boot_img_hdr *ahab_read_auth_image(struct container_hdr *container, + int image_index, + unsigned long container_offset) +{ + struct boot_img_hdr *images; + unsigned long offset; + unsigned long size; + + _info("Image index is %d number of container images are %hhu\n", + image_index, container->num_images); + if (image_index > container->num_images) + { + _info("[%s]: Invalid image number\n", __func__); + return NULL; + } + + images = (struct boot_img_hdr *)((uint8_t *)container + + sizeof(struct container_hdr)); + + uint32_t ret; + uint32_t pagesize; + ret = imx9_romapi_query_boot_infor(QUERY_PAGE_SZ, &pagesize); + if (ret != ROMAPI_OK) + { + _err("[%s]: Failed to query pagesize\n", __func__); + return NULL; + } + + if (!IS_ALIGNED(images[image_index].offset, pagesize)) + { + _err("[%s]: image%d offset not aligned to %u\n", __func__, + image_index, pagesize); + return NULL; + } + + size = ALIGN_UP(images[image_index].size, pagesize); + + offset = images[image_index].offset + container_offset; + + _info("[%s]: container: %p offset: %lu size: %lu\n", __func__, + container, offset, size); + + imx9_romapi_load_image((uint8_t *)images[image_index].dst, offset, + size); + + /* Flush the cache so ELE can read from RAM the updated values. */ + + up_flush_dcache((unsigned long)images[image_index].dst, + images[image_index].dst + size); + + uint32_t respo; + if (imx9_ele_verify_image(image_index, &respo)) + { + _err("[%s]: Failed with response %x\n", __func__, respo); + return NULL; + } + else + { + _info("[%s]: Image successfully verified.", __func__); + } + + return &images[image_index]; +} + +int ahab_auth_release(void) +{ + int err; + uint32_t resp; + + err = imx9_ele_release_container(&resp); + if (err) + { + _err("[%s]: ELE error 0x%x\n", __func__, resp); + } + else + { + _info("[%s]: Container successfully released\n", __func__); + } + + return err; +} diff --git a/arch/arm64/src/imx9/imx9_romapi.c b/arch/arm64/src/imx9/imx9_romapi.c new file mode 100644 index 00000000000..fdf20a79a08 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_romapi.c @@ -0,0 +1,171 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_romapi.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* i.MX9 ROM API structure. */ + +struct romapi_s +{ + uint16_t ver; + uint16_t tag; + uint32_t reserved1; + uint32_t (*load_image)(uint8_t *dest, uint32_t offset, uint32_t size, + uint32_t xor); + uint32_t (*query_boot_infor)(uint32_t infor_type, uint32_t *infor, + uint32_t xor); +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Physical address of the ROM api. */ + +static struct romapi_s *imx9_romapi_s = (struct romapi_s *)0x1980; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +uint32_t imx9_romapi_load_image(uint8_t *dest, uint32_t offset, + uint32_t size) +{ + uint32_t xor; + uint32_t ret; + + xor = (uintptr_t)dest ^ offset ^ size; + ret = imx9_romapi_s->load_image(dest, offset, size, xor); + + if (ret != ROMAPI_OK) + { + _err("[%s]: Couldn't download image.", __func__); + } + + return ret; +} + +uint32_t imx9_romapi_query_boot_infor(uint32_t infor_type, uint32_t *infor) +{ + uint32_t ret; + uint32_t xor; + + xor = infor_type ^ (uintptr_t)infor; + ret = imx9_romapi_s->query_boot_infor(infor_type, infor, xor); + + if (ret != ROMAPI_OK) + { + _err("[%s]: Couldn't query boot info.", __func__); + } + + return ret; +} + +enum imx9_romapi_bootdev_e imx9_romapi_get_boot_device(void) +{ + int ret; + uint32_t boot; + enum imx9_romapi_bootdev_e boot_type; + uint32_t xor = (uintptr_t)&boot ^ QUERY_BOOT_DEV; + + ret = imx9_romapi_s->query_boot_infor(QUERY_BOOT_DEV, &boot, xor); + + if (ret != ROMAPI_OK) + { + return BOOTDEV_INVALID; + } + + boot_type = boot >> 16; + + switch (boot_type) + { + case BOOTDEV_SD: + break; + case BOOTDEV_MMC: + break; + case BOOTDEV_NAND: + break; + case BOOTDEV_FLEXSPI_NOR: + break; + case BOOTDEV_SPI_NOR: + break; + case BOOTDEV_FLEXSPI_NAND: + break; + case BOOTDEV_USB: + break; + case BOOTDEV_MEM_DEV: + break; + default: + _err("[%s]: Invalid boot device.\n", __func__); + boot_type = BOOTDEV_INVALID; + break; + } + + return boot_type; +} + +int64_t imx9_romapi_get_seq_cntr_base(uint32_t image_offset, + uint32_t pagesize, + uint8_t cntr_idx) +{ + uint32_t size; + uint32_t ret; + uint16_t cntr_size; + struct container_hdr *hdr; + + size = ALIGN_UP(sizeof(struct container_hdr), pagesize); + hdr = (struct container_hdr *)(CONFIG_IMX_AHAB_CNTR_ADDR); + + if (CONTAINER_HDR_ALIGNMENT % pagesize != 0) + { + _err("[%s]: Unsupported pagesize.\n", __func__); + return -1; + } + + for (uint8_t i = 0; i < cntr_idx; i++) + { + ret = imx9_romapi_load_image((uint8_t *)CONFIG_IMX_AHAB_CNTR_ADDR, + image_offset, size); + if (ret != ROMAPI_OK) + { + _err("[%s]: Failure at iteration %hhu\n", __func__, i); + return -1; + } + + cntr_size = hdr->length_lsb + (hdr->length_msb << 8); + image_offset = ALIGN_UP((cntr_size + image_offset), + CONTAINER_HDR_ALIGNMENT); + } + + return image_offset; +} diff --git a/include/imx_container.h b/include/imx_container.h new file mode 100644 index 00000000000..a948888781b --- /dev/null +++ b/include/imx_container.h @@ -0,0 +1,129 @@ +/**************************************************************************** + * include/imx_container.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_IMX_CONTAINER_H +#define __INCLUDE_IMX_CONTAINER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IV_MAX_LEN 32 +#define HASH_MAX_LEN 64 + +#define CONTAINER_HDR_ALIGNMENT 0x400 +#define CONTAINER_HDR_EMMC_OFFSET 0 +#define CONTAINER_HDR_MMCSD_OFFSET SZ_32K +#define CONTAINER_HDR_QSPI_OFFSET SZ_4K +#define CONTAINER_HDR_NAND_OFFSET SZ_128M + +#define CONTAINER_HDR_TAG 0x87 +#define CONTAINER_HDR_VERSION 0 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* i.MX AHAB container header. */ + +begin_packed_struct struct container_hdr +{ + uint8_t version; + uint8_t length_lsb; + uint8_t length_msb; + uint8_t tag; + uint32_t flags; + uint16_t sw_version; + uint8_t fuse_version; + uint8_t num_images; + uint16_t sig_blk_offset; + uint16_t reserved; +} end_packed_struct; + +/* i.MX AHAB container, image header. */ + +begin_packed_struct struct boot_img_hdr +{ + uint32_t offset; + uint32_t size; + uint64_t dst; + uint64_t entry; + uint32_t hab_flags; + uint32_t meta; + uint8_t hash[HASH_MAX_LEN]; + uint8_t iv[IV_MAX_LEN]; +} end_packed_struct; + +/* i.MX AHAB container, signature block header. */ + +begin_packed_struct struct signature_block_hdr +{ + uint8_t version; + uint8_t length_lsb; + uint8_t length_msb; + uint8_t tag; + uint16_t srk_table_offset; + uint16_t cert_offset; + uint16_t blob_offset; + uint16_t signature_offset; + uint32_t reserved; +} end_packed_struct; + +/* Header used for the generation of an encrypted key blob from ELE. */ + +begin_packed_struct struct generate_key_blob_hdr +{ + uint8_t version; + uint8_t length_lsb; + uint8_t length_msb; + uint8_t tag; + uint8_t flags; + uint8_t size; + uint8_t algorithm; + uint8_t mode; +} end_packed_struct; + +/**************************************************************************** + * Name: imx_valid_container_hdr + * + * Description: + * Simple validation of the container header. + * + * Returned Value: + * true for Success, otherwise false + * + ****************************************************************************/ + +static inline bool imx_valid_container_hdr(struct container_hdr *container) +{ + return container->tag == CONTAINER_HDR_TAG && + container->version == CONTAINER_HDR_VERSION; +} +#endif /* __INCLUDE_IMX_CONTAINER_H */