/*
 * Default implementation for bl1_plat_handle_post_image_load(). This function
 * populates the default arguments to BL2. The BL2 memory layout structure
 * is allocated and the calculated layout is populated in arg1 to BL2.
 */
int bl1_plat_handle_post_image_load(unsigned int image_id)
{
	meminfo_t *bl2_tzram_layout;
	meminfo_t *bl1_tzram_layout;
	image_desc_t *image_desc;
	entry_point_info_t *ep_info;

	if (image_id != BL2_IMAGE_ID)
		return 0;

	/* Get the image descriptor */
	image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
	assert(image_desc != NULL);

	/* Get the entry point info */
	ep_info = &image_desc->ep_info;

	/* Find out how much free trusted ram remains after BL1 load */
	bl1_tzram_layout = bl1_plat_sec_mem_layout();

	/*
	 * Create a new layout of memory for BL2 as seen by BL1 i.e.
	 * tell it the amount of total and free memory available.
	 * This layout is created at the first free address visible
	 * to BL2. BL2 will read the memory layout before using its
	 * memory for other purposes.
	 */
	bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->total_base;

	bl1_calc_bl2_mem_layout(bl1_tzram_layout, bl2_tzram_layout);

	ep_info->args.arg1 = (uintptr_t)bl2_tzram_layout;

	VERBOSE("BL1: BL2 memory layout address = %p\n",
		(void *) bl2_tzram_layout);
	return 0;
}
/*******************************************************************************
 * Function to perform late architectural and platform specific initialization.
 * It also locates and loads the BL2 raw binary image in the trusted DRAM. Only
 * called by the primary cpu after a cold boot.
 * TODO: Add support for alternative image load mechanism e.g using virtio/elf
 * loader etc.
  ******************************************************************************/
void bl1_main(void)
{
	unsigned long sctlr_el3 = read_sctlr();
	unsigned long bl2_base;
	unsigned int load_type = TOP_LOAD, spsr;
	meminfo *bl1_tzram_layout;
	meminfo *bl2_tzram_layout = 0x0;

	/*
	 * Ensure that MMU/Caches and coherency are turned on
	 */
	assert(sctlr_el3 | SCTLR_M_BIT);
	assert(sctlr_el3 | SCTLR_C_BIT);
	assert(sctlr_el3 | SCTLR_I_BIT);

	/* Perform remaining generic architectural setup from EL3 */
	bl1_arch_setup();

	/* Perform platform setup in BL1. */
	bl1_platform_setup();

	/* Announce our arrival */
	printf(FIRMWARE_WELCOME_STR);
	printf("Built : %s, %s\n\r", __TIME__, __DATE__);

	/*
	 * Find out how much free trusted ram remains after BL1 load
	 * & load the BL2 image at its top
	 */
	bl1_tzram_layout = bl1_plat_sec_mem_layout();
	bl2_base = load_image(bl1_tzram_layout,
			      (const char *) BL2_IMAGE_NAME,
			      load_type, BL2_BASE);

	/*
	 * Create a new layout of memory for BL2 as seen by BL1 i.e.
	 * tell it the amount of total and free memory available.
	 * This layout is created at the first free address visible
	 * to BL2. BL2 will read the memory layout before using its
	 * memory for other purposes.
	 */
	bl2_tzram_layout = (meminfo *) bl1_tzram_layout->free_base;
	init_bl2_mem_layout(bl1_tzram_layout,
			    bl2_tzram_layout,
			    load_type,
			    bl2_base);

	if (bl2_base) {
		bl1_arch_next_el_setup();
		spsr = make_spsr(MODE_EL1, MODE_SP_ELX, MODE_RW_64);
		printf("Booting trusted firmware boot loader stage 2\n\r");
#if DEBUG
		printf("BL2 address = 0x%llx \n\r", (unsigned long long) bl2_base);
		printf("BL2 cpsr = 0x%x \n\r", spsr);
		printf("BL2 memory layout address = 0x%llx \n\r",
		       (unsigned long long) bl2_tzram_layout);
#endif
		run_image(bl2_base, spsr, SECURE, bl2_tzram_layout, 0);
	}

	/*
	 * TODO: print failure to load BL2 but also add a tzwdog timer
	 * which will reset the system eventually.
	 */
	printf("Failed to load boot loader stage 2 (BL2) firmware.\n\r");
	return;
}