mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2025-12-10 07:44:53 +01:00
After secure sysupgrade, uboot/TZ successfully authenticates rootfs even if the signature & certificates are not appended to kernel image. This is because the header and certificates copied to DDR memory before sysupgrade is retained. Updated the code to clear this DDR memory after authentication. Change-Id: Ic2331326baefc945c217a507d4379951dba821ab Signed-off-by: Anusha Rao <quic_anusha@quicinc.com> Signed-off-by: Timple Raj M <quic_timple@quicinc.com>
907 lines
24 KiB
C
907 lines
24 KiB
C
/*
|
|
* Copyright (c) 2015-2017, 2020 The Linux Foundation. All rights reserved.
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <command.h>
|
|
#include <image.h>
|
|
#include <nand.h>
|
|
#include <errno.h>
|
|
#include <asm/arch-qca-common/scm.h>
|
|
#include <part.h>
|
|
#include <linux/mtd/ubi.h>
|
|
#include <asm/arch-qca-common/smem.h>
|
|
#include <mmc.h>
|
|
#include <part_efi.h>
|
|
#include <fdtdec.h>
|
|
#include "fdt_info.h"
|
|
#include <asm/errno.h>
|
|
#include <asm/arch-qca-common/qca_common.h>
|
|
#include <usb.h>
|
|
#include <elf.h>
|
|
|
|
#define SEC_AUTH_SW_ID 0x17
|
|
#define ROOTFS_IMAGE_TYPE 0x13
|
|
#define NO_OF_PROGRAM_HDRS 3
|
|
#define ELF_HDR_PLUS_PHDR_SIZE sizeof(Elf32_Ehdr) + \
|
|
(NO_OF_PROGRAM_HDRS * sizeof(Elf32_Phdr))
|
|
|
|
#define PRIMARY_PARTITION 1
|
|
#define SECONDARY_PARTITION 2
|
|
|
|
extern int qca_scm_part_info(void *cmd_buf, size_t cmd_len);
|
|
|
|
unsigned long __stack_chk_guard = 0x000a0dff;
|
|
static int debug = 0;
|
|
static char mtdids[256];
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
static qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
|
|
int ipq_fs_on_nand ;
|
|
extern int nand_env_device;
|
|
extern qca_mmc mmc_host;
|
|
|
|
#ifdef CONFIG_QCA_MMC
|
|
static qca_mmc *host = &mmc_host;
|
|
#endif
|
|
|
|
typedef struct {
|
|
unsigned int image_type;
|
|
unsigned int header_vsn_num;
|
|
unsigned int image_src;
|
|
unsigned char *image_dest_ptr;
|
|
unsigned int image_size;
|
|
unsigned int code_size;
|
|
unsigned char *signature_ptr;
|
|
unsigned int signature_size;
|
|
unsigned char *cert_chain_ptr;
|
|
unsigned int cert_chain_size;
|
|
} mbn_header_t;
|
|
|
|
typedef struct {
|
|
unsigned int kernel_load_addr;
|
|
unsigned int kernel_load_size;
|
|
} kernel_img_info_t;
|
|
|
|
kernel_img_info_t kernel_img_info;
|
|
|
|
char dtb_config_name[64];
|
|
|
|
#ifdef CONFIG_IPQ_ELF_AUTH
|
|
typedef struct {
|
|
unsigned int img_offset;
|
|
unsigned int img_load_addr;
|
|
unsigned int img_size;
|
|
} image_info;
|
|
#endif
|
|
|
|
void __stack_chk_fail(void)
|
|
{
|
|
printf("stack-protector: U-boot stack is corrupted.\n");
|
|
bad_mode ();
|
|
}
|
|
/*
|
|
* Set the root device and bootargs for mounting root filesystem.
|
|
*/
|
|
static int set_fs_bootargs(int *fs_on_nand)
|
|
{
|
|
char *bootargs;
|
|
unsigned int active_part = 0;
|
|
int ret = 0;
|
|
char boot_args[MAX_BOOT_ARGS_SIZE] = {'\0'};
|
|
|
|
|
|
|
|
#define nand_rootfs "ubi.mtd=" QCA_ROOT_FS_PART_NAME " root=mtd:ubi_rootfs rootfstype=squashfs"
|
|
|
|
if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) {
|
|
if (get_which_flash_param("rootfs") ||
|
|
((sfi->flash_secondary_type == SMEM_BOOT_NAND_FLASH) ||
|
|
(sfi->flash_secondary_type == SMEM_BOOT_QSPI_NAND_FLASH))) {
|
|
bootargs = nand_rootfs;
|
|
*fs_on_nand = 1;
|
|
|
|
if (sfi->rootfs.offset == 0xBAD0FF5E) {
|
|
if(smem_bootconfig_info() == 0)
|
|
active_part = get_rootfs_active_partition();
|
|
|
|
sfi->rootfs.offset = active_part * IPQ_NAND_ROOTFS_SIZE;
|
|
sfi->rootfs.size = IPQ_NAND_ROOTFS_SIZE;
|
|
}
|
|
|
|
fdt_setprop((void *)gd->fdt_blob, 0, "nor_nand_available",
|
|
fs_on_nand, sizeof(int));
|
|
snprintf(mtdids, sizeof(mtdids),
|
|
"nand%d=nand%d,nand%d=" QCA_SPI_NOR_DEVICE,
|
|
is_spi_nand_available(),
|
|
is_spi_nand_available(),
|
|
CONFIG_SPI_FLASH_INFO_IDX
|
|
);
|
|
|
|
if (getenv("fsbootargs") == NULL)
|
|
setenv("fsbootargs", bootargs);
|
|
} else {
|
|
bootargs = boot_args;
|
|
if (smem_bootconfig_info() == 0) {
|
|
active_part = get_rootfs_active_partition();
|
|
if (active_part) {
|
|
strlcpy(bootargs, "rootfsname=rootfs_1", sizeof(boot_args));
|
|
if (sfi->rootfs.offset == 0xBAD0FF5E)
|
|
ret = set_uuid_bootargs(bootargs, "rootfs_1", sizeof(boot_args), false);
|
|
} else {
|
|
strlcpy(bootargs, "rootfsname=rootfs", sizeof(boot_args));
|
|
if (sfi->rootfs.offset == 0xBAD0FF5E)
|
|
ret = set_uuid_bootargs(bootargs, "rootfs", sizeof(boot_args), false);
|
|
}
|
|
} else {
|
|
strlcpy(bootargs, "rootfsname=rootfs", sizeof(boot_args));
|
|
if (sfi->rootfs.offset == 0xBAD0FF5E)
|
|
ret = set_uuid_bootargs(bootargs, "rootfs", sizeof(boot_args), false);
|
|
}
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
*fs_on_nand = 0;
|
|
|
|
snprintf(mtdids, sizeof(mtdids), "nand%d="
|
|
QCA_SPI_NOR_DEVICE, CONFIG_SPI_FLASH_INFO_IDX);
|
|
|
|
if (getenv("fsbootargs") == NULL)
|
|
setenv("fsbootargs", bootargs);
|
|
}
|
|
} else if (((sfi->flash_type == SMEM_BOOT_NAND_FLASH) ||
|
|
(sfi->flash_type == SMEM_BOOT_QSPI_NAND_FLASH))) {
|
|
bootargs = nand_rootfs;
|
|
if (getenv("fsbootargs") == NULL)
|
|
setenv("fsbootargs", bootargs);
|
|
*fs_on_nand = 1;
|
|
|
|
snprintf(mtdids, sizeof(mtdids), "nand0=nand0");
|
|
|
|
#ifdef CONFIG_QCA_MMC
|
|
} else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH) {
|
|
bootargs = boot_args;
|
|
if (smem_bootconfig_info() == 0) {
|
|
active_part = get_rootfs_active_partition();
|
|
if (active_part) {
|
|
strlcpy(bootargs, "rootfsname=rootfs_1 gpt", sizeof(boot_args));
|
|
ret = set_uuid_bootargs(bootargs, "rootfs_1", sizeof(boot_args), true);
|
|
} else {
|
|
strlcpy(bootargs, "rootfsname=rootfs gpt", sizeof(boot_args));
|
|
bootargs = "rootfsname=rootfs gpt";
|
|
ret = set_uuid_bootargs(bootargs, "rootfs", sizeof(boot_args), true);
|
|
}
|
|
} else {
|
|
strlcpy(bootargs, "rootfsname=rootfs gpt", sizeof(boot_args));
|
|
ret = set_uuid_bootargs(bootargs, "rootfs", sizeof(boot_args), true);
|
|
}
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
*fs_on_nand = 0;
|
|
if (getenv("fsbootargs") == NULL)
|
|
setenv("fsbootargs", bootargs);
|
|
#endif
|
|
} else {
|
|
printf("bootipq: unsupported boot flash type\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
return run_command("setenv bootargs ${bootargs} ${fsbootargs} rootwait", 0);
|
|
}
|
|
|
|
int config_select(unsigned int addr, char *rcmd, int rcmd_size)
|
|
{
|
|
/* Selecting a config name from the list of available
|
|
* config names by passing them to the fit_conf_get_node()
|
|
* function which is used to get the node_offset with the
|
|
* config name passed. Based on the return value index based
|
|
* or board name based config is used.
|
|
*/
|
|
|
|
#ifdef CONFIG_ARCH_IPQ806x
|
|
int soc_version = 0;
|
|
#endif
|
|
int i, strings_count;
|
|
const char *config = getenv("config_name");
|
|
|
|
if (config) {
|
|
printf("Manual device tree config selected!\n");
|
|
strlcpy(dtb_config_name, config, sizeof(dtb_config_name));
|
|
if (fit_conf_get_node((void *)addr, dtb_config_name) >= 0) {
|
|
snprintf(rcmd, rcmd_size, "bootm 0x%x#%s\n",
|
|
addr, dtb_config_name);
|
|
return 0;
|
|
}
|
|
|
|
} else {
|
|
strings_count = fdt_count_strings(gd->fdt_blob, 0, "config_name");
|
|
|
|
if (!strings_count) {
|
|
printf("Failed to get config_name\n");
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < strings_count; i++) {
|
|
fdt_get_string_index(gd->fdt_blob, 0, "config_name",
|
|
i, &config);
|
|
|
|
snprintf((char *)dtb_config_name,
|
|
sizeof(dtb_config_name), "%s", config);
|
|
|
|
#ifdef CONFIG_ARCH_IPQ806x
|
|
ipq_smem_get_socinfo_version((uint32_t *)&soc_version);
|
|
if(SOCINFO_VERSION_MAJOR(soc_version) >= 2) {
|
|
snprintf(dtb_config_name + strlen("config@"),
|
|
sizeof(dtb_config_name) - strlen("config@"),
|
|
"v%d.0-%s",
|
|
SOCINFO_VERSION_MAJOR(soc_version),
|
|
config + strlen("config@"));
|
|
}
|
|
#endif
|
|
if (fit_conf_get_node((void *)addr, dtb_config_name) >= 0) {
|
|
snprintf(rcmd, rcmd_size, "bootm 0x%x#%s\n",
|
|
addr, dtb_config_name);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
printf("Config not available\n");
|
|
return -1;
|
|
}
|
|
|
|
__weak int switch_ce_channel_buf(unsigned int channel_id)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_IPQ_ELF_AUTH
|
|
static int parse_elf_image_phdr(image_info *img_info, unsigned int addr)
|
|
{
|
|
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
|
|
Elf32_Phdr *phdr; /* Program header structure pointer */
|
|
int i;
|
|
|
|
ehdr = (Elf32_Ehdr *)addr;
|
|
phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
|
|
|
|
if (!IS_ELF(*ehdr)) {
|
|
printf("It is not a elf image \n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (ehdr->e_type != ET_EXEC) {
|
|
printf("Not a valid elf image\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Load each program header */
|
|
for (i = 0; i < NO_OF_PROGRAM_HDRS; ++i) {
|
|
printf("Parsing phdr load addr 0x%x offset 0x%x size 0x%x type 0x%x\n",
|
|
phdr->p_paddr, phdr->p_offset, phdr->p_filesz, phdr->p_type);
|
|
if(phdr->p_type == PT_LOAD) {
|
|
img_info->img_offset = phdr->p_offset;
|
|
img_info->img_load_addr = phdr->p_paddr;
|
|
img_info->img_size = phdr->p_filesz;
|
|
return 0;
|
|
}
|
|
++phdr;
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_IPQ_ROOTFS_AUTH
|
|
static int copy_rootfs(unsigned int request, uint32_t size)
|
|
{
|
|
char runcmd[256];
|
|
#ifdef CONFIG_QCA_MMC
|
|
int ret;
|
|
block_dev_desc_t *blk_dev;
|
|
disk_partition_t disk_info;
|
|
unsigned int active_part = 0;
|
|
#endif
|
|
|
|
if (ipq_fs_on_nand) {
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"ubi read 0x%x ubi_rootfs &&", request);
|
|
#ifdef CONFIG_QCA_MMC
|
|
} else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH ||
|
|
((sfi->flash_type == SMEM_BOOT_SPI_FLASH) &&
|
|
(sfi->rootfs.offset == 0xBAD0FF5E))) {
|
|
blk_dev = mmc_get_dev(host->dev_num);
|
|
if (smem_bootconfig_info() == 0) {
|
|
active_part = get_rootfs_active_partition();
|
|
if (active_part) {
|
|
ret = get_partition_info_efi_by_name(blk_dev,
|
|
"rootfs_1", &disk_info);
|
|
} else {
|
|
ret = get_partition_info_efi_by_name(blk_dev,
|
|
"rootfs", &disk_info);
|
|
}
|
|
}else {
|
|
ret = get_partition_info_efi_by_name(blk_dev,
|
|
"rootfs", &disk_info);
|
|
}
|
|
if(ret == 0)
|
|
snprintf(runcmd, sizeof(runcmd), "mmc read 0x%x 0x%X 0x%X &&",
|
|
request, (uint)disk_info.start,
|
|
(uint)(size / disk_info.blksz) + 1);
|
|
else
|
|
return CMD_RET_FAILURE;
|
|
#endif
|
|
} else {
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"sf read 0x%x 0x%x 0x%x && ",
|
|
request, (uint)sfi->rootfs.offset, (uint)sfi->rootfs.size);
|
|
}
|
|
if (debug)
|
|
printf("runcmd: %s\n", runcmd);
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
|
return CMD_RET_FAILURE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifndef CONFIG_IPQ_ELF_AUTH
|
|
static int authenticate_rootfs(unsigned int kernel_addr)
|
|
{
|
|
unsigned int kernel_imgsize;
|
|
unsigned int request;
|
|
int ret;
|
|
mbn_header_t *mbn_ptr;
|
|
struct {
|
|
unsigned long type;
|
|
unsigned long size;
|
|
unsigned long addr;
|
|
} rootfs_img_info;
|
|
|
|
request = CONFIG_ROOTFS_LOAD_ADDR;
|
|
rootfs_img_info.addr = CONFIG_ROOTFS_LOAD_ADDR;
|
|
rootfs_img_info.type = SEC_AUTH_SW_ID;
|
|
request += sizeof(mbn_header_t);/* space for mbn header */
|
|
|
|
/* get , kernel size = header + kernel + certificate */
|
|
mbn_ptr = (mbn_header_t *) kernel_addr;
|
|
kernel_imgsize = mbn_ptr->image_size + sizeof(mbn_header_t);
|
|
|
|
/* get rootfs MBN header and validate it */
|
|
mbn_ptr = (mbn_header_t *)((uint32_t)mbn_ptr + kernel_imgsize);
|
|
if (mbn_ptr->image_type != ROOTFS_IMAGE_TYPE &&
|
|
(mbn_ptr->code_size + mbn_ptr->signature_size +
|
|
mbn_ptr->cert_chain_size != mbn_ptr->image_size))
|
|
return CMD_RET_FAILURE;
|
|
|
|
/* pack, MBN header + rootfs + certificate */
|
|
/* copy rootfs from the boot device */
|
|
copy_rootfs(request, mbn_ptr->code_size);
|
|
|
|
/* copy rootfs MBN header */
|
|
memcpy((void *)CONFIG_ROOTFS_LOAD_ADDR, (void *)kernel_addr + kernel_imgsize,
|
|
sizeof(mbn_header_t));
|
|
/* copy rootfs certificate */
|
|
memcpy((void *)request + mbn_ptr->code_size,
|
|
(void *)kernel_addr + kernel_imgsize + sizeof(mbn_header_t),
|
|
mbn_ptr->signature_size + mbn_ptr->cert_chain_size);
|
|
|
|
/* copy rootfs size */
|
|
rootfs_img_info.size = sizeof(mbn_header_t) + mbn_ptr->image_size;
|
|
|
|
ret = qca_scm_secure_authenticate(&rootfs_img_info, sizeof(rootfs_img_info));
|
|
|
|
memset((void *)kernel_img_info.kernel_load_addr, 0, sizeof(mbn_header_t));
|
|
memset(mbn_ptr, 0,
|
|
(sizeof(mbn_header_t) + mbn_ptr->signature_size + mbn_ptr->cert_chain_size));
|
|
|
|
if (ret)
|
|
return CMD_RET_FAILURE;
|
|
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
|
|
#else
|
|
static int authenticate_rootfs_elf(unsigned int rootfs_hdr)
|
|
{
|
|
int ret;
|
|
unsigned int request;
|
|
image_info img_info;
|
|
struct {
|
|
unsigned long type;
|
|
unsigned long size;
|
|
unsigned long addr;
|
|
} rootfs_img_info;
|
|
|
|
request = CONFIG_ROOTFS_LOAD_ADDR;
|
|
rootfs_img_info.addr = request;
|
|
rootfs_img_info.type = SEC_AUTH_SW_ID;
|
|
|
|
if (parse_elf_image_phdr(&img_info, rootfs_hdr))
|
|
return CMD_RET_FAILURE;
|
|
|
|
memcpy((void*)request, (void*)rootfs_hdr, img_info.img_offset);
|
|
|
|
request += img_info.img_offset;
|
|
|
|
/* copy rootfs from the boot device */
|
|
copy_rootfs(request, img_info.img_size);
|
|
|
|
rootfs_img_info.size = img_info.img_offset + img_info.img_size;
|
|
ret = qca_scm_secure_authenticate(&rootfs_img_info, sizeof(rootfs_img_info));
|
|
memset((void *)rootfs_hdr, 0, img_info.img_offset);
|
|
if (ret)
|
|
return CMD_RET_FAILURE;
|
|
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
static int do_boot_signedimg(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
|
{
|
|
char runcmd[256];
|
|
int ret;
|
|
unsigned int request;
|
|
#ifdef CONFIG_VERSION_ROLLBACK_PARTITION_INFO
|
|
int part = PRIMARY_PARTITION;
|
|
#endif
|
|
#ifdef CONFIG_QCA_MMC
|
|
block_dev_desc_t *blk_dev;
|
|
disk_partition_t disk_info;
|
|
unsigned int active_part = 0;
|
|
#endif
|
|
#ifdef CONFIG_IPQ_ELF_AUTH
|
|
image_info img_info;
|
|
#endif
|
|
|
|
if (argc == 2 && strncmp(argv[1], "debug", 5) == 0)
|
|
debug = 1;
|
|
|
|
if ((ret = set_fs_bootargs(&ipq_fs_on_nand)))
|
|
return ret;
|
|
|
|
/* check the smem info to see which flash used for booting */
|
|
if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) {
|
|
if (debug) {
|
|
printf("Using nand device %d\n", CONFIG_SPI_FLASH_INFO_IDX);
|
|
}
|
|
} else if (((sfi->flash_type == SMEM_BOOT_NAND_FLASH) ||
|
|
(sfi->flash_type == SMEM_BOOT_QSPI_NAND_FLASH))) {
|
|
if (debug) {
|
|
printf("Using nand device 0\n");
|
|
}
|
|
} else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH) {
|
|
if (debug) {
|
|
printf("Using MMC device\n");
|
|
}
|
|
} else {
|
|
printf("Unsupported BOOT flash type\n");
|
|
return -1;
|
|
}
|
|
if (debug) {
|
|
run_command("printenv bootargs", 0);
|
|
printf("Booting from flash\n");
|
|
}
|
|
|
|
request = CONFIG_SYS_LOAD_ADDR;
|
|
kernel_img_info.kernel_load_addr = request;
|
|
|
|
#ifdef CONFIG_VERSION_ROLLBACK_PARTITION_INFO
|
|
if (smem_bootconfig_info() == 0){
|
|
ret = get_rootfs_active_partition();
|
|
if (ret){
|
|
part = SECONDARY_PARTITION;
|
|
}
|
|
}
|
|
ret = qca_scm_part_info(&part, sizeof(part));
|
|
if (ret) {
|
|
printf(" Partition info authentication failed \n");
|
|
BUG();
|
|
}
|
|
#endif
|
|
if (ipq_fs_on_nand) {
|
|
#ifdef CONFIG_CMD_UBI
|
|
/*
|
|
* The kernel will be available inside a UBI volume
|
|
*/
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"nand device %d && "
|
|
"setenv mtdids nand%d=nand%d && "
|
|
"setenv mtdparts mtdparts=nand%d:0x%llx@0x%llx(fs),${msmparts} && "
|
|
"ubi part fs && ", is_spi_nand_available(),
|
|
is_spi_nand_available(),
|
|
is_spi_nand_available(),
|
|
is_spi_nand_available(),
|
|
sfi->rootfs.size, sfi->rootfs.offset);
|
|
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
|
return CMD_RET_FAILURE;
|
|
|
|
#ifdef CONFIG_IPQ_ELF_AUTH
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"ubi read 0x%x kernel 0x%x && ",
|
|
request, ELF_HDR_PLUS_PHDR_SIZE);
|
|
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
|
return CMD_RET_FAILURE;
|
|
|
|
if (parse_elf_image_phdr(&img_info, request))
|
|
return CMD_RET_FAILURE;
|
|
|
|
request = img_info.img_load_addr - img_info.img_offset;
|
|
#endif
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"ubi read 0x%x kernel && ", request);
|
|
|
|
if (debug)
|
|
printf("%s", runcmd);
|
|
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
|
return CMD_RET_FAILURE;
|
|
|
|
kernel_img_info.kernel_load_size =
|
|
(unsigned int)ubi_get_volume_size("kernel");
|
|
#endif
|
|
#ifdef CONFIG_QCA_MMC
|
|
} else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH ||
|
|
((sfi->flash_type == SMEM_BOOT_SPI_FLASH) &&
|
|
(sfi->rootfs.offset == 0xBAD0FF5E))) {
|
|
blk_dev = mmc_get_dev(host->dev_num);
|
|
if (smem_bootconfig_info() == 0) {
|
|
active_part = get_rootfs_active_partition();
|
|
if (active_part) {
|
|
ret = get_partition_info_efi_by_name(blk_dev,
|
|
"0:HLOS_1", &disk_info);
|
|
} else {
|
|
ret = get_partition_info_efi_by_name(blk_dev,
|
|
"0:HLOS", &disk_info);
|
|
}
|
|
} else {
|
|
ret = get_partition_info_efi_by_name(blk_dev,
|
|
"0:HLOS", &disk_info);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
#ifdef CONFIG_IPQ_ELF_AUTH
|
|
snprintf(runcmd, sizeof(runcmd), "mmc read 0x%x 0x%X 0x%X",
|
|
CONFIG_SYS_LOAD_ADDR,
|
|
(uint)disk_info.start, ELF_HDR_PLUS_PHDR_SIZE);
|
|
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
|
return CMD_RET_FAILURE;
|
|
|
|
if (parse_elf_image_phdr(&img_info, request))
|
|
return CMD_RET_FAILURE;
|
|
|
|
request = img_info.img_load_addr - img_info.img_offset;
|
|
#endif
|
|
snprintf(runcmd, sizeof(runcmd), "mmc read 0x%x 0x%X 0x%X",
|
|
request,
|
|
(uint)disk_info.start, (uint)disk_info.size);
|
|
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
|
return CMD_RET_FAILURE;
|
|
|
|
kernel_img_info.kernel_load_size = disk_info.size * disk_info.blksz;
|
|
}
|
|
#endif
|
|
} else {
|
|
/*
|
|
* Kernel is in a separate partition
|
|
*/
|
|
snprintf(runcmd, sizeof(runcmd), "sf probe &&");
|
|
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
|
return CMD_RET_FAILURE;
|
|
|
|
#ifdef CONFIG_IPQ_ELF_AUTH
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"sf read 0x%x 0x%x 0x%x && ",
|
|
CONFIG_SYS_LOAD_ADDR,
|
|
(uint)sfi->hlos.offset, ELF_HDR_PLUS_PHDR_SIZE);
|
|
|
|
if (debug)
|
|
printf("%s", runcmd);
|
|
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
|
return CMD_RET_FAILURE;
|
|
|
|
if (parse_elf_image_phdr(&img_info, request))
|
|
return CMD_RET_FAILURE;
|
|
|
|
request = img_info.img_load_addr - img_info.img_offset;
|
|
#endif
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"sf read 0x%x 0x%x 0x%x && ",
|
|
request,
|
|
(uint)sfi->hlos.offset, (uint)sfi->hlos.size);
|
|
|
|
if (debug)
|
|
printf("%s", runcmd);
|
|
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS)
|
|
return CMD_RET_FAILURE;
|
|
|
|
kernel_img_info.kernel_load_size = sfi->hlos.size;
|
|
}
|
|
|
|
setenv("mtdids", mtdids);
|
|
|
|
#ifndef CONFIG_IPQ_ELF_AUTH
|
|
mbn_header_t * mbn_ptr = (mbn_header_t *) request;
|
|
request += sizeof(mbn_header_t);
|
|
#else
|
|
kernel_img_info.kernel_load_addr = request;
|
|
request = img_info.img_load_addr;
|
|
#endif
|
|
|
|
/* This sys call will switch the CE1 channel to register usage */
|
|
ret = switch_ce_channel_buf(0);
|
|
|
|
if (ret)
|
|
return CMD_RET_FAILURE;
|
|
|
|
ret = qca_scm_auth_kernel(&kernel_img_info,
|
|
sizeof(kernel_img_info));
|
|
#ifndef CONFIG_IPQ_ELF_AUTH
|
|
memset((void *)mbn_ptr->signature_ptr, 0,(mbn_ptr->signature_size + mbn_ptr->cert_chain_size));
|
|
#else
|
|
memset((void *)kernel_img_info.kernel_load_addr, 0, img_info.img_offset);
|
|
#endif
|
|
if (ret) {
|
|
printf("Kernel image authentication failed \n");
|
|
BUG();
|
|
}
|
|
#ifdef CONFIG_IPQ_ROOTFS_AUTH
|
|
#ifdef CONFIG_IPQ_ELF_AUTH
|
|
if (authenticate_rootfs_elf(img_info.img_load_addr +
|
|
img_info.img_size) != CMD_RET_SUCCESS) {
|
|
printf("Rootfs elf image authentication failed\n");
|
|
BUG();
|
|
}
|
|
#else
|
|
/* Rootfs's header and certificate at end of kernel image, copy from
|
|
* there and pack with rootfs image and authenticate rootfs */
|
|
if (authenticate_rootfs(CONFIG_SYS_LOAD_ADDR) != CMD_RET_SUCCESS) {
|
|
printf("Rootfs image authentication failed\n");
|
|
BUG();
|
|
}
|
|
#endif
|
|
#endif
|
|
/*
|
|
* This sys call will switch the CE1 channel to ADM usage
|
|
* so that HLOS can use it.
|
|
*/
|
|
ret = switch_ce_channel_buf(1);
|
|
|
|
if (ret)
|
|
return CMD_RET_FAILURE;
|
|
|
|
dcache_enable();
|
|
|
|
ret = config_select(request, runcmd, sizeof(runcmd));
|
|
|
|
if (debug)
|
|
printf("%s", runcmd);
|
|
|
|
if (ret < 0 || run_command(runcmd, 0) != CMD_RET_SUCCESS) {
|
|
#ifdef CONFIG_QCA_MMC
|
|
mmc_initialize(gd->bd);
|
|
#endif
|
|
#ifdef CONFIG_USB_XHCI_IPQ
|
|
ipq_board_usb_init();
|
|
#endif
|
|
dcache_disable();
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
#ifndef CONFIG_QCA_APPSBL_DLOAD
|
|
reset_crashdump();
|
|
#endif
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
|
|
static int do_boot_unsignedimg(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
|
{
|
|
int ret;
|
|
char runcmd[256];
|
|
#ifdef CONFIG_QCA_MMC
|
|
block_dev_desc_t *blk_dev;
|
|
disk_partition_t disk_info;
|
|
unsigned int active_part = 0;
|
|
#endif
|
|
|
|
if (argc == 2 && strncmp(argv[1], "debug", 5) == 0)
|
|
debug = 1;
|
|
|
|
if ((ret = set_fs_bootargs(&ipq_fs_on_nand)))
|
|
return ret;
|
|
|
|
if (debug) {
|
|
run_command("printenv bootargs", 0);
|
|
printf("Booting from flash\n");
|
|
}
|
|
|
|
if (((sfi->flash_type == SMEM_BOOT_NAND_FLASH) ||
|
|
(sfi->flash_type == SMEM_BOOT_QSPI_NAND_FLASH))) {
|
|
if (debug) {
|
|
printf("Using nand device 0\n");
|
|
}
|
|
|
|
/*
|
|
* The kernel is in seperate partition
|
|
*/
|
|
if (sfi->rootfs.offset == 0xBAD0FF5E) {
|
|
printf(" bad offset of hlos");
|
|
return -1;
|
|
}
|
|
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"setenv mtdids nand0=nand0 && "
|
|
"setenv mtdparts mtdparts=nand0:0x%llx@0x%llx(fs),${msmparts} && "
|
|
"ubi part fs && "
|
|
"ubi read 0x%x kernel && ",
|
|
sfi->rootfs.size, sfi->rootfs.offset,
|
|
CONFIG_SYS_LOAD_ADDR);
|
|
|
|
} else if (((sfi->flash_type == SMEM_BOOT_SPI_FLASH) &&
|
|
(sfi->rootfs.offset != 0xBAD0FF5E)) ||
|
|
ipq_fs_on_nand) {
|
|
if (get_which_flash_param("rootfs") || ipq_fs_on_nand) {
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"nand device %d && "
|
|
"setenv mtdids nand%d=nand%d && "
|
|
"setenv mtdparts mtdparts=nand%d:0x%llx@0x%llx(fs),${msmparts} && "
|
|
"ubi part fs && "
|
|
"ubi read 0x%x kernel && ",
|
|
is_spi_nand_available(),
|
|
is_spi_nand_available(),
|
|
is_spi_nand_available(),
|
|
is_spi_nand_available(),
|
|
sfi->rootfs.size, sfi->rootfs.offset,
|
|
CONFIG_SYS_LOAD_ADDR);
|
|
} else {
|
|
/*
|
|
* Kernel is in a separate partition
|
|
*/
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"sf probe &&"
|
|
"sf read 0x%x 0x%x 0x%x && ",
|
|
CONFIG_SYS_LOAD_ADDR, (uint)sfi->hlos.offset, (uint)sfi->hlos.size);
|
|
}
|
|
#ifdef CONFIG_QCA_MMC
|
|
} else if ((sfi->flash_type == SMEM_BOOT_MMC_FLASH) ||
|
|
((sfi->flash_type == SMEM_BOOT_SPI_FLASH) &&
|
|
(sfi->rootfs.offset == 0xBAD0FF5E))) {
|
|
if (debug) {
|
|
printf("Using MMC device\n");
|
|
}
|
|
blk_dev = mmc_get_dev(host->dev_num);
|
|
if (smem_bootconfig_info() == 0) {
|
|
active_part = get_rootfs_active_partition();
|
|
if (active_part) {
|
|
ret = get_partition_info_efi_by_name(blk_dev,
|
|
"0:HLOS_1", &disk_info);
|
|
} else {
|
|
ret = get_partition_info_efi_by_name(blk_dev,
|
|
"0:HLOS", &disk_info);
|
|
}
|
|
} else {
|
|
ret = get_partition_info_efi_by_name(blk_dev,
|
|
"0:HLOS", &disk_info);
|
|
}
|
|
|
|
if (ret == 0) {
|
|
snprintf(runcmd, sizeof(runcmd), "mmc read 0x%x 0x%x 0x%x",
|
|
CONFIG_SYS_LOAD_ADDR,
|
|
(uint)disk_info.start, (uint)disk_info.size);
|
|
}
|
|
|
|
#endif /* CONFIG_QCA_MMC */
|
|
} else {
|
|
printf("Unsupported BOOT flash type\n");
|
|
return -1;
|
|
}
|
|
|
|
if (run_command(runcmd, 0) != CMD_RET_SUCCESS) {
|
|
#ifdef CONFIG_QCA_MMC
|
|
mmc_initialize(gd->bd);
|
|
#endif
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
dcache_enable();
|
|
|
|
setenv("mtdids", mtdids);
|
|
|
|
ret = genimg_get_format((void *)CONFIG_SYS_LOAD_ADDR);
|
|
if (ret == IMAGE_FORMAT_FIT) {
|
|
ret = config_select(CONFIG_SYS_LOAD_ADDR,
|
|
runcmd, sizeof(runcmd));
|
|
} else if (ret == IMAGE_FORMAT_LEGACY) {
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"bootm 0x%x\n", CONFIG_SYS_LOAD_ADDR);
|
|
} else {
|
|
ret = genimg_get_format((void *)CONFIG_SYS_LOAD_ADDR +
|
|
sizeof(mbn_header_t));
|
|
if (ret == IMAGE_FORMAT_FIT) {
|
|
ret = config_select((CONFIG_SYS_LOAD_ADDR
|
|
+ sizeof(mbn_header_t)),
|
|
runcmd, sizeof(runcmd));
|
|
} else if (ret == IMAGE_FORMAT_LEGACY) {
|
|
snprintf(runcmd, sizeof(runcmd),
|
|
"bootm 0x%x\n", (CONFIG_SYS_LOAD_ADDR +
|
|
sizeof(mbn_header_t)));
|
|
} else {
|
|
dcache_disable();
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
}
|
|
|
|
|
|
if (ret < 0 || run_command(runcmd, 0) != CMD_RET_SUCCESS) {
|
|
#ifdef CONFIG_USB_XHCI_IPQ
|
|
ipq_board_usb_init();
|
|
#endif
|
|
dcache_disable();
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
#ifndef CONFIG_QCA_APPSBL_DLOAD
|
|
reset_crashdump();
|
|
#endif
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
|
|
static int do_bootipq(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
|
{
|
|
int ret;
|
|
char buf = 0;
|
|
/*
|
|
* set fdt_high parameter so that u-boot will not load
|
|
* dtb above CONFIG_IPQ40XX_FDT_HIGH region.
|
|
*/
|
|
if (run_command("setenv fdt_high " MK_STR(CONFIG_IPQ_FDT_HIGH) "\n", 0)
|
|
!= CMD_RET_SUCCESS) {
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
ret = qca_scm_call(SCM_SVC_FUSE, QFPROM_IS_AUTHENTICATE_CMD, &buf, sizeof(char));
|
|
|
|
#ifdef CONFIG_IPQ9574_EDMA
|
|
aquantia_phy_reset_init_done();
|
|
#endif
|
|
/*
|
|
|| if atf is enable in env ,do_boot_signedimg is skip.
|
|
|| Note: This features currently support in ipq50XX.
|
|
*/
|
|
if (ret == 0 && buf == 1 && !getenv("atf")) {
|
|
ret = do_boot_signedimg(cmdtp, flag, argc, argv);
|
|
} else if (ret == 0 || ret == -EOPNOTSUPP) {
|
|
ret = do_boot_unsignedimg(cmdtp, flag, argc, argv);
|
|
}
|
|
|
|
if (ret == CMD_RET_FAILURE) {
|
|
#ifdef CONFIG_IPQ_ETH_INIT_DEFER
|
|
puts("\nNet: ");
|
|
eth_initialize();
|
|
#endif
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
U_BOOT_CMD(bootipq, 2, 0, do_bootipq,
|
|
"bootipq from flash device",
|
|
"bootipq [debug] - Load image(s) and boots the kernel\n");
|