arch/arm64/imx9: Add ROMAPI and AHAB support for i.MX9

This adds support for the i.MX9 ROMAPI, allowing boot in a more
device agnostic and portable manner. The ROMAPI "natively" allows to:
- Query the boot device for information.
- Copy data from the boot device to RAM.

An extra functionality was added to ROMAPI to calculate
offsets of sequential AHAB containers.

The AHAB functionality is built on top of raw ELE primitives and allows to:
- Authenticate a container image.
- Release the authenticated container.

Signed-off-by: Theodore Karatapanis <tkaratapanis@census-labs.com>
This commit is contained in:
Theodore Karatapanis 2025-05-06 21:22:32 +03:00 committed by Xiang Xiao
parent 3c48031ec3
commit d278c6cb15
7 changed files with 676 additions and 0 deletions

View file

@ -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 <imx_container.h>
/****************************************************************************
* 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 */

View file

@ -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 <stdint.h>
/****************************************************************************
* 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 */

View file

@ -91,6 +91,30 @@ config IMX9_DDR_TRAINING
---help--- ---help---
Perform DDR training to prepare the external memory for use. 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 onchip ROM API for image download
and bootinformation 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" menu "i.MX9 Peripheral Selection"
config IMX9_EDMA config IMX9_EDMA

View file

@ -89,6 +89,14 @@ ifeq ($(CONFIG_IMX9_BOOTLOADER), y)
CHIP_CSRCS += imx9_ele.c CHIP_CSRCS += imx9_ele.c
endif 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) ifeq ($(CONFIG_IMX9_DDR_TRAINING),y)
CHIP_CSRCS += $(DDR_CSRCS) CHIP_CSRCS += $(DDR_CSRCS)
endif endif

View file

@ -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 <stdbool.h>
#include <debug.h>
#include <stdio.h>
#include <nuttx/nuttx.h>
#include <nuttx/arch.h>
#include "imx9_ele.h"
#include <arch/imx9/imx9_romapi.h>
#include <arch/imx9/imx9_ahab.h>
/****************************************************************************
* 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;
}

View file

@ -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 <arch/imx9/imx9_romapi.h>
#include <nuttx/nuttx.h>
#include <imx_container.h>
#include <debug.h>
/****************************************************************************
* 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;
}

129
include/imx_container.h Normal file
View file

@ -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 <stdint.h>
#include <stdbool.h>
#include <nuttx/compiler.h>
/****************************************************************************
* 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 */