Remove concept of top/bottom image loading

This concept is no longer required since we now support loading of
images at fixed addresses only.

The image loader now automatically detects the position of the image
inside the current memory layout and updates the layout such that
memory fragmentation is minimised.

The 'attr' field of the meminfo data structure, which used to hold
the bottom/top loading information, has been removed. Also the 'next'
field has been removed as it wasn't used anywhere.

The 'init_bl2_mem_layout()' function has been moved out of common
code and put in BL1-specific code. It has also been renamed into
'bl1_init_bl2_mem_layout'.

Fixes ARM-software/tf-issues#109

Change-Id: I3f54642ce7b763d5ee3b047ad0ab59eabbcf916d
This commit is contained in:
Sandrine Bailleux 2014-06-24 14:02:34 +01:00
parent 5e0f9bde13
commit 8f55dfb4ba
9 changed files with 174 additions and 293 deletions

View File

@ -65,6 +65,38 @@ static void __dead2 bl1_run_bl2(entry_point_info_t *bl2_ep)
bl2_ep->args.arg7);
}
/*******************************************************************************
* The next function has a weak definition. Platform specific code can override
* it if it wishes to.
******************************************************************************/
#pragma weak bl1_init_bl2_mem_layout
/*******************************************************************************
* Function that takes a memory layout into which BL2 has been loaded and
* populates a new memory layout for BL2 that ensures that BL1's data sections
* resident in secure RAM are not visible to BL2.
******************************************************************************/
void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
meminfo_t *bl2_mem_layout)
{
const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
assert(bl1_mem_layout != NULL);
assert(bl2_mem_layout != NULL);
/* Check that BL1's memory is lying outside of the free memory */
assert((BL1_RAM_LIMIT <= bl1_mem_layout->free_base) ||
(BL1_RAM_BASE >= bl1_mem_layout->free_base + bl1_mem_layout->free_size));
/* Remove BL1 RW data from the scope of memory visible to BL2 */
*bl2_mem_layout = *bl1_mem_layout;
reserve_mem(&bl2_mem_layout->total_base,
&bl2_mem_layout->total_size,
BL1_RAM_BASE,
bl1_size);
flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t));
}
/*******************************************************************************
* Function to perform late architectural and platform specific initialization.
@ -78,7 +110,6 @@ void bl1_main(void)
#if DEBUG
unsigned long sctlr_el3 = read_sctlr_el3();
#endif
unsigned int load_type = TOP_LOAD;
image_info_t bl2_image_info = { {0} };
entry_point_info_t bl2_ep = { {0} };
meminfo_t *bl1_tzram_layout;
@ -105,17 +136,15 @@ void bl1_main(void)
SET_PARAM_HEAD(&bl2_image_info, PARAM_IMAGE_BINARY, VERSION_1, 0);
SET_PARAM_HEAD(&bl2_ep, PARAM_EP, VERSION_1, 0);
/*
* Find out how much free trusted ram remains after BL1 load
* & load the BL2 image at its top
*/
/* Find out how much free trusted ram remains after BL1 load */
bl1_tzram_layout = bl1_plat_sec_mem_layout();
/* Load the BL2 image */
err = load_image(bl1_tzram_layout,
(const char *) BL2_IMAGE_NAME,
load_type,
BL2_BASE,
&bl2_image_info,
&bl2_ep);
BL2_IMAGE_NAME,
BL2_BASE,
&bl2_image_info,
&bl2_ep);
if (err) {
/*
* TODO: print failure to load BL2 but also add a tzwdog timer
@ -132,10 +161,7 @@ void bl1_main(void)
* memory for other purposes.
*/
bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->free_base;
init_bl2_mem_layout(bl1_tzram_layout,
bl2_tzram_layout,
load_type,
bl2_image_info.image_base);
bl1_init_bl2_mem_layout(bl1_tzram_layout, bl2_tzram_layout);
bl1_plat_set_bl2_ep_info(&bl2_image_info, &bl2_ep);
bl2_ep.args.arg1 = (unsigned long)bl2_tzram_layout;

View File

@ -31,6 +31,15 @@
#ifndef __BL1_PRIVATE_H__
#define __BL1_PRIVATE_H__
/*******************************************************************************
* Declarations of linker defined symbols which will tell us where BL1 lives
* in Trusted RAM
******************************************************************************/
extern uint64_t __BL1_RAM_START__;
extern uint64_t __BL1_RAM_END__;
#define BL1_RAM_BASE (uint64_t)(&__BL1_RAM_START__)
#define BL1_RAM_LIMIT (uint64_t)(&__BL1_RAM_END__)
/******************************************
* Function prototypes
*****************************************/

View File

@ -41,15 +41,13 @@
/*******************************************************************************
* The only thing to do in BL2 is to load further images and pass control to
* BL31. The memory occupied by BL2 will be reclaimed by BL3_x stages. BL2 runs
* entirely in S-EL1. Since arm standard c libraries are not PIC, printf et al
* are not available. We rely on assertions to signal error conditions
* BL3-1. The memory occupied by BL2 will be reclaimed by BL3-x stages. BL2 runs
* entirely in S-EL1.
******************************************************************************/
void bl2_main(void)
{
meminfo_t *bl2_tzram_layout;
bl31_params_t *bl2_to_bl31_params;
unsigned int bl2_load, bl31_load;
entry_point_info_t *bl31_ep_info;
meminfo_t bl32_mem_info;
meminfo_t bl33_mem_info;
@ -76,18 +74,9 @@ void bl2_main(void)
/* Set the X0 parameter to bl31 */
bl31_ep_info->args.arg0 = (unsigned long)bl2_to_bl31_params;
/*
* Load BL31. BL1 tells BL2 whether it has been TOP or BOTTOM loaded.
* To avoid fragmentation of trusted SRAM memory, BL31 is always
* loaded opposite to BL2. This allows BL31 to reclaim BL2 memory
* while maintaining its free space in one contiguous chunk.
*/
bl2_load = bl2_tzram_layout->attr & LOAD_MASK;
assert((bl2_load == TOP_LOAD) || (bl2_load == BOT_LOAD));
bl31_load = (bl2_load == TOP_LOAD) ? BOT_LOAD : TOP_LOAD;
/* Load the BL3-1 image */
e = load_image(bl2_tzram_layout,
BL31_IMAGE_NAME,
bl31_load,
BL31_BASE,
bl2_to_bl31_params->bl31_image_info,
bl31_ep_info);
@ -106,7 +95,6 @@ void bl2_main(void)
/* Load the BL33 image in non-secure memory provided by the platform */
e = load_image(&bl33_mem_info,
BL33_IMAGE_NAME,
BOT_LOAD,
plat_get_ns_image_entrypoint(),
bl2_to_bl31_params->bl33_image_info,
bl2_to_bl31_params->bl33_ep_info);
@ -133,7 +121,6 @@ void bl2_main(void)
bl2_plat_get_bl32_meminfo(&bl32_mem_info);
e = load_image(&bl32_mem_info,
BL32_IMAGE_NAME,
bl32_mem_info.attr & LOAD_MASK,
BL32_BASE,
bl2_to_bl31_params->bl32_image_info,
bl2_to_bl31_params->bl32_ep_info);

View File

@ -33,10 +33,9 @@
#include <assert.h>
#include <bl_common.h>
#include <debug.h>
#include <errno.h>
#include <io_storage.h>
#include <platform.h>
#include <errno.h>
#include <stdio.h>
unsigned long page_align(unsigned long value, unsigned dir)
{
@ -72,43 +71,76 @@ void change_security_state(unsigned int target_security_state)
write_scr(scr);
}
/*******************************************************************************
* The next function has a weak definition. Platform specific code can override
* it if it wishes to.
******************************************************************************/
#pragma weak init_bl2_mem_layout
/*******************************************************************************
* Function that takes a memory layout into which BL2 has been either top or
* bottom loaded along with the address where BL2 has been loaded in it. Using
* this information, it populates bl2_mem_layout to tell BL2 how much memory
* it has access to and how much is available for use.
******************************************************************************/
void init_bl2_mem_layout(meminfo_t *bl1_mem_layout,
meminfo_t *bl2_mem_layout,
unsigned int load_type,
unsigned long bl2_base)
/******************************************************************************
* Determine whether the memory region delimited by 'addr' and 'size' is free,
* given the extents of free memory.
* Return 1 if it is free, 0 otherwise.
*****************************************************************************/
static int is_mem_free(uint64_t free_base, size_t free_size,
uint64_t addr, size_t size)
{
unsigned tmp;
return (addr >= free_base) && (addr + size <= free_base + free_size);
}
if (load_type == BOT_LOAD) {
bl2_mem_layout->total_base = bl2_base;
tmp = bl1_mem_layout->free_base - bl2_base;
bl2_mem_layout->total_size = bl1_mem_layout->free_size + tmp;
/******************************************************************************
* Inside a given memory region, determine whether a sub-region of memory is
* closer from the top or the bottom of the encompassing region. Return the
* size of the smallest chunk of free memory surrounding the sub-region in
* 'small_chunk_size'.
*****************************************************************************/
static unsigned int choose_mem_pos(uint64_t mem_start, uint64_t mem_end,
uint64_t submem_start, uint64_t submem_end,
size_t *small_chunk_size)
{
size_t top_chunk_size, bottom_chunk_size;
assert(mem_start <= submem_start);
assert(submem_start <= submem_end);
assert(submem_end <= mem_end);
assert(small_chunk_size != NULL);
top_chunk_size = mem_end - submem_end;
bottom_chunk_size = submem_start - mem_start;
if (top_chunk_size < bottom_chunk_size) {
*small_chunk_size = top_chunk_size;
return TOP;
} else {
bl2_mem_layout->total_base = bl1_mem_layout->free_base;
tmp = bl1_mem_layout->total_base + bl1_mem_layout->total_size;
bl2_mem_layout->total_size = tmp - bl1_mem_layout->free_base;
*small_chunk_size = bottom_chunk_size;
return BOTTOM;
}
}
bl2_mem_layout->free_base = bl1_mem_layout->free_base;
bl2_mem_layout->free_size = bl1_mem_layout->free_size;
bl2_mem_layout->attr = load_type;
/******************************************************************************
* Reserve the memory region delimited by 'addr' and 'size'. The extents of free
* memory are passed in 'free_base' and 'free_size' and they will be updated to
* reflect the memory usage.
* The caller must ensure the memory to reserve is free.
*****************************************************************************/
void reserve_mem(uint64_t *free_base, size_t *free_size,
uint64_t addr, size_t size)
{
size_t discard_size;
size_t reserved_size;
unsigned int pos;
flush_dcache_range((unsigned long) bl2_mem_layout, sizeof(meminfo_t));
return;
assert(free_base != NULL);
assert(free_size != NULL);
assert(is_mem_free(*free_base, *free_size, addr, size));
pos = choose_mem_pos(*free_base, *free_base + *free_size,
addr, addr + size,
&discard_size);
reserved_size = size + discard_size;
*free_size -= reserved_size;
if (pos == BOTTOM)
*free_base = addr + size;
INFO("Reserved %u bytes (discarded %u bytes %s)\n",
reserved_size, discard_size,
pos == TOP ? "above" : "below");
}
static void dump_load_info(unsigned long image_load_addr,
@ -170,34 +202,32 @@ unsigned long image_size(const char *image_name)
return image_size;
}
/*******************************************************************************
* Generic function to load an image into the trusted RAM,
* given a name, extents of free memory & whether the image should be loaded at
* the bottom or top of the free memory. It updates the memory layout if the
* load is successful. It also updates the image information and the entry point
* information in the params passed. The caller might pass a NULL pointer for
* the entry point if it is not interested in this information, e.g. because
* the image just needs to be loaded in memory but won't ever be executed.
* Generic function to load an image at a specific address given a name and
* extents of free memory. It updates the memory layout if the load is
* successful, as well as the image information and the entry point information.
* The caller might pass a NULL pointer for the entry point if it is not
* interested in this information, e.g. because the image just needs to be
* loaded in memory but won't ever be executed.
* Returns 0 on success, a negative error code otherwise.
******************************************************************************/
int load_image(meminfo_t *mem_layout,
const char *image_name,
unsigned int load_type,
unsigned long fixed_addr,
image_info_t *image_data,
entry_point_info_t *entry_point_info)
const char *image_name,
uint64_t image_base,
image_info_t *image_data,
entry_point_info_t *entry_point_info)
{
uintptr_t dev_handle;
uintptr_t image_handle;
uintptr_t image_spec;
unsigned long temp_image_base = 0;
unsigned long image_base = 0;
long offset = 0;
size_t image_size = 0;
size_t bytes_read = 0;
size_t image_size;
size_t bytes_read;
int io_result = IO_FAIL;
assert(mem_layout != NULL);
assert(image_name != NULL);
assert(image_data != NULL);
assert(image_data->h.version >= VERSION_1);
/* Obtain a reference to the image by querying the platform layer */
@ -216,6 +246,8 @@ int load_image(meminfo_t *mem_layout,
return io_result;
}
INFO("Loading file '%s' at address 0x%lx\n", image_name, image_base);
/* Find the size of the image */
io_result = io_size(image_handle, &image_size);
if ((io_result != IO_SUCCESS) || (image_size == 0)) {
@ -224,170 +256,14 @@ int load_image(meminfo_t *mem_layout,
goto exit;
}
/* See if we have enough space */
if (image_size > mem_layout->free_size) {
WARN("Cannot load '%s' file: Not enough space.\n",
image_name);
dump_load_info(0, image_size, mem_layout);
goto exit;
}
switch (load_type) {
case TOP_LOAD:
/* Load the image in the top of free memory */
temp_image_base = mem_layout->free_base + mem_layout->free_size;
temp_image_base -= image_size;
/* Page align base address and check whether the image still fits */
image_base = page_align(temp_image_base, DOWN);
assert(image_base <= temp_image_base);
if (image_base < mem_layout->free_base) {
WARN("Cannot load '%s' file: Not enough space.\n",
image_name);
/* Check that the memory where the image will be loaded is free */
if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
image_base, image_size)) {
WARN("Failed to reserve memory: 0x%lx - 0x%lx\n",
image_base, image_base + image_size);
dump_load_info(image_base, image_size, mem_layout);
io_result = -ENOMEM;
goto exit;
}
/* Calculate the amount of extra memory used due to alignment */
offset = temp_image_base - image_base;
break;
case BOT_LOAD:
/* Load the BL2 image in the bottom of free memory */
temp_image_base = mem_layout->free_base;
image_base = page_align(temp_image_base, UP);
assert(image_base >= temp_image_base);
/* Page align base address and check whether the image still fits */
if (image_base + image_size >
mem_layout->free_base + mem_layout->free_size) {
WARN("Cannot load '%s' file: Not enough space.\n",
image_name);
dump_load_info(image_base, image_size, mem_layout);
io_result = -ENOMEM;
goto exit;
}
/* Calculate the amount of extra memory used due to alignment */
offset = image_base - temp_image_base;
break;
default:
assert(0);
}
/*
* Some images must be loaded at a fixed address, not a dynamic one.
*
* This has been implemented as a hack on top of the existing dynamic
* loading mechanism, for the time being. If the 'fixed_addr' function
* argument is different from zero, then it will force the load address.
* So we still have this principle of top/bottom loading but the code
* determining the load address is bypassed and the load address is
* forced to the fixed one.
*
* This can result in quite a lot of wasted space because we still use
* 1 sole meminfo structure to represent the extents of free memory,
* where we should use some sort of linked list.
*
* E.g. we want to load BL2 at address 0x04020000, the resulting memory
* layout should look as follows:
* ------------ 0x04040000
* | | <- Free space (1)
* |----------|
* | BL2 |
* |----------| 0x04020000
* | | <- Free space (2)
* |----------|
* | BL1 |
* ------------ 0x04000000
*
* But in the current hacky implementation, we'll need to specify
* whether BL2 is loaded at the top or bottom of the free memory.
* E.g. if BL2 is considered as top-loaded, the meminfo structure
* will give the following view of the memory, hiding the chunk of
* free memory above BL2:
* ------------ 0x04040000
* | |
* | |
* | BL2 |
* |----------| 0x04020000
* | | <- Free space (2)
* |----------|
* | BL1 |
* ------------ 0x04000000
*/
if (fixed_addr != 0) {
/* Load the image at the given address. */
image_base = fixed_addr;
/* Check whether the image fits. */
if ((image_base < mem_layout->free_base) ||
(image_base + image_size >
mem_layout->free_base + mem_layout->free_size)) {
WARN("Cannot load '%s' file: Not enough space.\n",
image_name);
dump_load_info(image_base, image_size, mem_layout);
io_result = -ENOMEM;
goto exit;
}
/* Check whether the fixed load address is page-aligned. */
if (!is_page_aligned(image_base)) {
WARN("Cannot load '%s' file at unaligned address 0x%lx\n",
image_name, fixed_addr);
io_result = -ENOMEM;
goto exit;
}
/*
* Calculate the amount of extra memory used due to fixed
* loading.
*/
if (load_type == TOP_LOAD) {
unsigned long max_addr, space_used;
/*
* ------------ max_addr
* | /wasted/ | | offset
* |..........|..............................
* | image | | image_flen
* |----------| fixed_addr
* | |
* | |
* ------------ total_base
*/
max_addr = mem_layout->total_base + mem_layout->total_size;
/*
* Compute the amount of memory used by the image.
* Corresponds to all space above the image load
* address.
*/
space_used = max_addr - fixed_addr;
/*
* Calculate the amount of wasted memory within the
* amount of memory used by the image.
*/
offset = space_used - image_size;
} else /* BOT_LOAD */
/*
* ------------
* | |
* | |
* |----------|
* | image |
* |..........| fixed_addr
* | /wasted/ | | offset
* ------------ total_base
*/
offset = fixed_addr - mem_layout->total_base;
}
/* We have enough space so load the image now */
@ -398,6 +274,14 @@ int load_image(meminfo_t *mem_layout,
goto exit;
}
/*
* Update the memory usage info.
* This is done after the actual loading so that it is not updated when
* the load is unsuccessful.
*/
reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
image_base, image_size);
image_data->image_base = image_base;
image_data->image_size = image_size;
@ -405,18 +289,13 @@ int load_image(meminfo_t *mem_layout,
entry_point_info->pc = image_base;
/*
* File has been successfully loaded. Update the free memory
* data structure & flush the contents of the TZRAM so that
* the next EL can see it.
* File has been successfully loaded.
* Flush the image in TZRAM so that the next EL can see it.
*/
/* Update the memory contents */
flush_dcache_range(image_base, image_size);
mem_layout->free_size -= image_size + offset;
/* Update the base of free memory since its moved up */
if (load_type == BOT_LOAD)
mem_layout->free_base += offset + image_size;
INFO("File '%s' loaded: 0x%lx - 0x%lx\n", image_name, image_base,
image_base + image_size);
exit:
io_close(image_handle);

View File

@ -511,7 +511,7 @@ warm boot. For each CPU, BL1 is responsible for the following tasks:
the platform to decide where it wants to place the `meminfo` structure for
BL2.
BL1 implements the `init_bl2_mem_layout()` function to populate the
BL1 implements the `bl1_init_bl2_mem_layout()` function to populate the
BL2 `meminfo` structure. The platform may override this implementation, for
example if the platform wants to restrict the amount of memory visible to
BL2. Details of how to do this are given below.
@ -574,7 +574,7 @@ its own use.
This function helps fulfill requirement 3 above.
### Function : init_bl2_mem_layout() [optional]
### Function : bl1_init_bl2_mem_layout() [optional]
Argument : meminfo *, meminfo *, unsigned int, unsigned long
Return : void

View File

@ -38,15 +38,11 @@
#define DOWN 0
/*******************************************************************************
* Constants for loading images. When BLx wants to load BLy, it looks at a
* meminfo structure to find the extents of free memory. Then depending upon
* how it has been configured, it can either load BLy at the top or bottom of
* the free memory. These constants indicate the choice.
* TODO: Make this configurable while building the trusted firmware.
******************************************************************************/
#define TOP_LOAD 0x1
#define BOT_LOAD !TOP_LOAD
#define LOAD_MASK (1 << 0)
* Constants to identify the location of a memory region in a given memory
* layout.
******************************************************************************/
#define TOP 0x1
#define BOTTOM !TOP
/******************************************************************************
* Opcode passed in x0 to tell next EL that we want to run an image.
@ -97,18 +93,17 @@
#include <cdefs.h> /* For __dead2 */
#include <cassert.h>
#include <stdint.h>
#include <stddef.h>
/*******************************************************************************
* Structure used for telling the next BL how much of a particular type of
* memory is available for its use and how much is already used.
******************************************************************************/
typedef struct meminfo {
unsigned long total_base;
long total_size;
unsigned long free_base;
long free_size;
unsigned long attr;
unsigned long next;
uint64_t total_base;
size_t total_size;
uint64_t free_base;
size_t free_size;
} meminfo_t;
typedef struct aapcs64_params {
@ -209,14 +204,16 @@ CASSERT(sizeof(unsigned long) ==
unsigned long page_align(unsigned long, unsigned);
void change_security_state(unsigned int);
unsigned long image_size(const char *);
int load_image(meminfo_t *,
const char *,
unsigned int,
unsigned long,
image_info_t *,
entry_point_info_t *);
int load_image(meminfo_t *mem_layout,
const char *image_name,
uint64_t image_base,
image_info_t *image_data,
entry_point_info_t *entry_point_info);
extern const char build_message[];
void reserve_mem(uint64_t *free_base, size_t *free_size,
uint64_t addr, size_t size);
#endif /*__ASSEMBLY__*/
#endif /* __BL_COMMON_H__ */

View File

@ -90,10 +90,8 @@ void bl1_plat_set_bl2_ep_info(struct image_info *image,
/*******************************************************************************
* Optional BL1 functions (may be overridden)
******************************************************************************/
void init_bl2_mem_layout(struct meminfo *,
struct meminfo *,
unsigned int,
unsigned long);
void bl1_init_bl2_mem_layout(const struct meminfo *bl1_mem_layout,
struct meminfo *bl2_mem_layout);
/*******************************************************************************
* Mandatory BL2 functions

View File

@ -35,6 +35,7 @@
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include "../../bl1/bl1_private.h"
#include "fvp_def.h"
#include "fvp_private.h"
@ -45,9 +46,6 @@
extern unsigned long __COHERENT_RAM_START__;
extern unsigned long __COHERENT_RAM_END__;
extern unsigned long __BL1_RAM_START__;
extern unsigned long __BL1_RAM_END__;
/*
* The next 2 constants identify the extents of the coherent memory region.
* These addresses are used by the MMU setup code and therefore they must be
@ -58,10 +56,6 @@ extern unsigned long __BL1_RAM_END__;
#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
#define BL1_RAM_BASE (unsigned long)(&__BL1_RAM_START__)
#define BL1_RAM_LIMIT (unsigned long)(&__BL1_RAM_END__)
/* Data structure which holds the extents of the trusted SRAM for BL1*/
static meminfo_t bl1_tzram_layout;

View File

@ -171,12 +171,7 @@ void bl2_early_platform_setup(meminfo_t *mem_layout)
console_init(PL011_UART0_BASE);
/* Setup the BL2 memory layout */
bl2_tzram_layout.total_base = mem_layout->total_base;
bl2_tzram_layout.total_size = mem_layout->total_size;
bl2_tzram_layout.free_base = mem_layout->free_base;
bl2_tzram_layout.free_size = mem_layout->free_size;
bl2_tzram_layout.attr = mem_layout->attr;
bl2_tzram_layout.next = 0;
bl2_tzram_layout = *mem_layout;
/* Initialize the platform config for future decision making */
fvp_config_setup();
@ -276,8 +271,6 @@ void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo)
(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
bl32_meminfo->free_size =
(TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE;
bl32_meminfo->attr = BOT_LOAD;
bl32_meminfo->next = 0;
}
@ -290,6 +283,4 @@ void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
bl33_meminfo->total_size = DRAM_SIZE - DRAM1_SEC_SIZE;
bl33_meminfo->free_base = DRAM_BASE;
bl33_meminfo->free_size = DRAM_SIZE - DRAM1_SEC_SIZE;
bl33_meminfo->attr = 0;
bl33_meminfo->attr = 0;
}