예제 #1
0
파일: system.c 프로젝트: thehobn/ec
int system_run_image_copy(enum system_image_copy_t copy)
{
	uintptr_t base;
	uintptr_t init_addr;

	/* If system is already running the requested image, done */
	if (system_get_image_copy() == copy)
		return EC_SUCCESS;

	if (system_is_locked()) {
		/* System is locked, so disallow jumping between images unless
		 * this is the initial jump from RO to RW code. */

		/* Must currently be running the RO image */
		if (system_get_image_copy() != SYSTEM_IMAGE_RO)
			return EC_ERROR_ACCESS_DENIED;

		/* Target image must be RW image */
		if (copy != SYSTEM_IMAGE_RW)
			return EC_ERROR_ACCESS_DENIED;

		/* Jumping must still be enabled */
		if (disable_jump)
			return EC_ERROR_ACCESS_DENIED;
	}

	/* Load the appropriate reset vector */
	base = get_base(copy);
	if (base == 0xffffffff)
		return EC_ERROR_INVAL;

	/* TODO: (ML) jump to little FW for code ram architecture */
#ifdef CONFIG_CODERAM_ARCH
	init_addr = system_get_lfw_address(base);
#else
	/* Make sure the reset vector is inside the destination image */
	init_addr = *(uintptr_t *)(base + 4);
#ifndef EMU_BUILD
	if (init_addr < base || init_addr >= base + get_size(copy))
		return EC_ERROR_UNKNOWN;
#endif
#endif

	CPRINTS("Jumping to image %s", system_image_copy_t_to_string(copy));

	jump_to_image(init_addr);

	/* Should never get here */
	return EC_ERROR_UNKNOWN;
}
예제 #2
0
파일: system.c 프로젝트: longsleep/ec
static int command_sysjump(int argc, char **argv)
{
	uint32_t addr;
	char *e;

	if (argc < 2)
		return EC_ERROR_PARAM_COUNT;

	/* Handle named images */
	if (!strcasecmp(argv[1], "RO"))
		return system_run_image_copy(SYSTEM_IMAGE_RO);
	else if (!strcasecmp(argv[1], "RW") || !strcasecmp(argv[1], "A")) {
		/*
		 * TODO(crosbug.com/p/11149): remove "A" once all scripts are
		 * updated to use "RW".
		 */
		return system_run_image_copy(SYSTEM_IMAGE_RW);
	} else if (!strcasecmp(argv[1], "disable")) {
		system_disable_jump();
		return EC_SUCCESS;
	}

	/* Arbitrary jumps are only allowed on an unlocked system */
	if (system_is_locked())
		return EC_ERROR_ACCESS_DENIED;

	/* Check for arbitrary address */
	addr = strtoi(argv[1], &e, 0);
	if (*e)
		return EC_ERROR_PARAM1;

	ccprintf("Jumping to 0x%08x\n", addr);
	cflush();
	jump_to_image(addr);
	return EC_SUCCESS;
}
예제 #3
0
파일: start.c 프로젝트: projectara/bootrom
/**
 * @brief Stage 2 loader "C" entry point. Started from Stage 1
 * bootloader. Primary function is to load, validate, and start
 * executing a stage 3 image. Also will (when fully implemented)
 * perform startup negotiations with AP, cryptographic initialzations
 * and tests, module authentication, flash update, and other housekeeping.
 * Image load and validation are essntially identical to the crresponding
 * functions in stage 1, although different keys are used for signature
 * validation.
 *
 * @param none
 *
 * @returns Nothing. Will launch/restart image if successful, halt if not.
 */
void bootrom_main(void) {
    int rc;
    /* TA-20 R/W data in bufRAM */
    uint32_t    boot_status = INIT_STATUS_OPERATING;
    bool        boot_from_spi = true;
    bool        fallback_boot_unipro = false;
    uint32_t    is_secure_image;
    secondstage_cfgdata *cfgdata;

    chip_init();

    dbginit();

    /* Ensure that we start each boot with an assumption of success */
    init_last_error();

    crypto_init();

    dbgprint("\nHello world from s2fw\n");

    if (!get_2ndstage_cfgdata(&cfgdata)) {
        dbgprint("found valid config data\n");
        if (cfgdata->use_fake_ims) {
            /**
             * We don't really need to handle all the efuses as boot ROM
             * does. But we do want to update the EPUID according to the
             * fake IMS. And the rest of the efuse handling do no harm
             * anyway.
             */
            if (efuse_init() != 0) {
                halt_and_catch_fire(boot_status);
            }
        }
    }

    uint8_t ims[TSB_ISAA_NUM_IMS_BYTES];
    tsb_get_ims(ims, TSB_ISAA_NUM_IMS_BYTES);
    key_generation(ims);

    chip_unipro_init();

    boot_control(&boot_from_spi);

    /* Advertise our boot status */
    chip_advertise_boot_status(boot_status);
    /* Advertise our initialization type */
    rc = chip_advertise_boot_type();
    if (rc) {
        halt_and_catch_fire(boot_status);
    }

    if (boot_from_spi) {
        dbgprint("Boot from SPIROM\n");

        spi_ops.init();

        /**
         * Call locate_ffff_element_on_storage to locate next stage FW.
         * Do not care about the image length here so pass NULL.
         */
        if (locate_ffff_element_on_storage(&spi_ops,
                                           FFFF_ELEMENT_STAGE_3_FW,
                                           NULL) == 0) {
            boot_status = INIT_STATUS_SPI_BOOT_STARTED;
            chip_advertise_boot_status(boot_status);
            if (!load_tftf_image(&spi_ops, &is_secure_image)) {
                spi_ops.finish(true, is_secure_image);
                if (is_secure_image) {
                    boot_status = INIT_STATUS_TRUSTED_SPI_FLASH_BOOT_FINISHED;
                    dbgprintx32("SPI Trusted: (",
                                merge_errno_with_boot_status(boot_status),
                                ")\n");
                } else {
                    boot_status = INIT_STATUS_UNTRUSTED_SPI_FLASH_BOOT_FINISHED;
                    dbgprintx32("SPI Untrusted: (",
                                merge_errno_with_boot_status(boot_status),
                                ")\n");

                    /*
                     *  Disable IMS, CMS access before starting untrusted image.
                     *  NB. JTAG continues to be not enabled at this point
                     */
                    efuse_rig_for_untrusted();
                }

                /* Log that we're starting the boot-from-SPIROM */
                chip_advertise_boot_status(merge_errno_with_boot_status(boot_status));
                /* TA-16 jump to SPI code (BOOTRET_o = 0 && SPIBOOT_N = 0) */
                jump_to_image();
            }
        }
        spi_ops.finish(false, false);

        /* Fallback to UniPro boot */
        boot_from_spi = false;
        fallback_boot_unipro = true;

        chip_clear_image_loading_ram();
    } else {
        /* (Not boot-from-spi, */
        fallback_boot_unipro = false;
    }

    if (greybus_init()) {
        set_last_error(BRE_BOU_GBCTRL_CPORT);
        halt_and_catch_fire(boot_status);
    }

    /* Boot-Over-UniPro...
     * We get here if directed to do so by the bootselector, or as a fallback
     * for a failed SPIROM boot.
     */
    if (!boot_from_spi) {
       /* Boot over Unipro */
        if (fallback_boot_unipro) {
            boot_status = merge_errno_with_boot_status(
                            INIT_STATUS_FALLLBACK_UNIPRO_BOOT_STARTED);
            dbgprintx32("Spi boot failed (", boot_status, "), ");
        } else {
            boot_status = INIT_STATUS_UNIPRO_BOOT_STARTED;
        }
        chip_advertise_boot_status(boot_status);
        dbgprintx32("Boot over UniPro (",
                    merge_errno_with_boot_status(boot_status),
                    ")\n");
        advertise_ready();
#if RUN_SPI_TEST
        spi_gb_init();
        dbgprint("Running in loop to perform as SPI over Greybus\n");
        while (1) {
            if (greybus_loop()) {
                dbgprint("ERROR in greuybus loop\n");
                halt_and_catch_fire(boot_status);
            }
        }
#endif
        dbgprint("Ready-poked; download-ready\n");
        if (greybus_ops.init() != 0) {
            halt_and_catch_fire(boot_status);
        }
        if (!load_tftf_image(&greybus_ops, &is_secure_image)) {
            if (greybus_ops.finish(true, is_secure_image) != 0) {
                halt_and_catch_fire(boot_status);
            }
            if (is_secure_image) {
                boot_status = fallback_boot_unipro ?
                    INIT_STATUS_FALLLBACK_TRUSTED_UNIPRO_BOOT_FINISHED :
                    INIT_STATUS_TRUSTED_UNIPRO_BOOT_FINISHED;
                dbgprintx32("UP Trusted: (",
                            merge_errno_with_boot_status(boot_status),
                            ")\n");
            } else {
                boot_status = fallback_boot_unipro ?
                    INIT_STATUS_FALLLBACK_UNTRUSTED_UNIPRO_BOOT_FINISHED :
                    INIT_STATUS_UNTRUSTED_UNIPRO_BOOT_FINISHED;
                dbgprintx32("UP Trusted: (",
                            merge_errno_with_boot_status(boot_status),
                            ")\n");

                /*
                 *  Disable IMS, CMS access before starting
                 * untrusted image
                 *  NB. JTAG continues to be not enabled at this point
                 */
                efuse_rig_for_untrusted();
            }

            /* Log that we're starting the boot-from-UniPro */
            chip_advertise_boot_status(boot_status);
            /* TA-17 jump to Workram code (BOOTRET_o = 0 && SPIM_BOOT_N = 1) */
            jump_to_image();
        }
        if (greybus_ops.finish(false, is_secure_image) != 0) {
            halt_and_catch_fire(boot_status);
        }
    }

    /* If we reach here, we didn't find an image to boot - stop while we're
     * ahead...
     */
    halt_and_catch_fire(boot_status);
}
예제 #4
0
int system_run_image_copy(enum system_image_copy_t copy)
{
	uintptr_t base;
	uintptr_t init_addr;
#ifdef CONFIG_REPLACE_LOADER_WITH_BSS_SLOW
	uint8_t *buf;
	uint32_t offset;
	uint32_t bytes_to_load;
	int rv;
#endif /* defined(CONFIG_REPLACE_LOADER_WITH_BSS_SLOW) */

	/* If system is already running the requested image, done */
	if (system_get_image_copy() == copy)
		return EC_SUCCESS;

	if (system_is_locked()) {
		/* System is locked, so disallow jumping between images unless
		 * this is the initial jump from RO to RW code. */

		/* Must currently be running the RO image */
		if (system_get_image_copy() != SYSTEM_IMAGE_RO)
			return EC_ERROR_ACCESS_DENIED;

		/* Target image must be RW image */
		if (copy != SYSTEM_IMAGE_RW)
			return EC_ERROR_ACCESS_DENIED;

		/* Jumping must still be enabled */
		if (disable_jump)
			return EC_ERROR_ACCESS_DENIED;
	}

	/* Load the appropriate reset vector */
	base = get_program_memory_addr(copy);
	if (base == 0xffffffff)
		return EC_ERROR_INVAL;

#ifdef CONFIG_EXTERNAL_STORAGE
#ifdef CONFIG_REPLACE_LOADER_WITH_BSS_SLOW
	/*
	 * We've used the region in which the loader resided as data space for
	 * the .bss.slow section.  Therefore, we need to reload the loader from
	 * the external storage back into program memory so that we can load a
	 * different image.
	 */
	buf = (uint8_t *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_LOADER_MEM_OFF);
	bytes_to_load = CONFIG_LOADER_SIZE;
	offset = CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_LOADER_STORAGE_OFF;

	rv = flash_read(offset, bytes_to_load, buf);
	if (rv)
		return rv;
#endif /* defined(CONFIG_REPLACE_LOADER_WITH_BSS_SLOW) */

	/* Jump to loader */
	init_addr = system_get_lfw_address();

	system_set_image_copy(copy);
#else
#ifdef CONFIG_FW_RESET_VECTOR
	/* Get reset vector */
	init_addr = system_get_fw_reset_vector(base);
#else
#if defined(CONFIG_RO_HEAD_ROOM)
	/* Skip any head room in the RO image */
	if (copy == SYSTEM_IMAGE_RO)
		/* Don't change base, though! */
		init_addr = *(uintptr_t *)(base + CONFIG_RO_HEAD_ROOM + 4);
	else
#endif
	init_addr = *(uintptr_t *)(base + 4);
#endif
#ifndef EMU_BUILD
	/* Make sure the reset vector is inside the destination image */
	if (init_addr < base || init_addr >= base + get_size(copy))
		return EC_ERROR_UNKNOWN;
#endif
#endif

	CPRINTS("Jumping to image %s", system_image_copy_t_to_string(copy));

	jump_to_image(init_addr);

	/* Should never get here */
	return EC_ERROR_UNKNOWN;
}