blob: df04a2d4db7a68812e82b57631a19b66a8185261 [file] [log] [blame] [edit]
#include <common.h>
#include <malloc.h>
#include <linux/err.h>
#include <partition_table.h>
#include <libfdt.h>
#include <asm/arch/bl31_apis.h>
extern int is_dtb_encrypt(unsigned char *buffer);
#ifdef CONFIG_MULTI_DTB
extern unsigned long get_multi_dt_entry(unsigned long fdt_addr);
#endif
struct partitions_data{
int nr;
struct partitions *parts;
};
struct partitions *part_table = NULL;
static int parts_total_num;
int has_boot_slot = 0;
int has_system_slot = 0;
int get_partitions_table(struct partitions **table)
{
int ret = 0;
if (part_table && parts_total_num) {
*table = part_table;
ret = parts_total_num;
}
return ret;
}
int get_partition_count(void)
{
return parts_total_num;
}
struct partitions *get_partitions(void)
{
return part_table;
}
void free_partitions(void)
{
if (part_table)
free(part_table);
part_table = NULL;
}
/*
return 0 if dts is valid
other value are falure.
*/
int check_valid_dts(unsigned char *buffer)
{
int ret = -__LINE__;
char *dt_addr;
/* fixme, a work around way */
/* for google project, we don`t define CONFIG_DTB_MEM_ADDR
* in arch/arm/include/asm/arch-g12a/cpu.h */
unsigned char *sbuffer = (unsigned char *)getenv_hex("loadaddr", 0x100000);
//unsigned char *sbuffer = (unsigned char *)getenv_hex("loadaddr", CONFIG_DTB_MEM_ADDR + 0x100000);
/* g12a merge to trunk, use trunk code */
//unsigned char *sbuffer = (unsigned char *)0x1000000;
if (is_dtb_encrypt(buffer)) {
memcpy(sbuffer, buffer, AML_DTB_IMG_MAX_SZ);
flush_cache((unsigned long)sbuffer, AML_DTB_IMG_MAX_SZ);
ret = aml_sec_boot_check(AML_D_P_IMG_DECRYPT, (long unsigned)sbuffer, AML_DTB_IMG_MAX_SZ, 0);
if (ret) {
printf("\n %s() %d: Decrypt dtb: Sig Check %d\n", __func__, __LINE__, ret);
return -__LINE__;
}
memcpy(buffer, sbuffer, AML_DTB_IMG_MAX_SZ);
}
#ifdef CONFIG_MULTI_DTB
dt_addr = (char *)get_multi_dt_entry((unsigned long)buffer);
#else
dt_addr = (char *)buffer;
#endif
printf("start dts,buffer=%p,dt_addr=%p\n", buffer, dt_addr);
ret = fdt_check_header(dt_addr);
if ( ret < 0 )
printf("%s: %s\n",__func__,fdt_strerror(ret));
/* fixme, is it 0 when ok? */
return ret;
}
int get_partition_from_dts(unsigned char *buffer)
{
char *dt_addr;
int nodeoffset,poffset=0;
int *parts_num;
char propname[8];
const uint32_t *phandle;
const char *uname;
const char *usize;
const char *umask;
int index;
int ret = -1;
if ( buffer == NULL)
goto _err;
//TODO need enable check_valid_dts if encrypt dtb
#if 0
ret = check_valid_dts(buffer);
printf("%s() %d: ret %d\n",__func__, __LINE__, ret);
if ( ret < 0 )
{
printf("%s() %d: ret %d\n",__func__, __LINE__, ret);
goto _err;
}
#endif
#ifdef CONFIG_MULTI_DTB
dt_addr = (char *)get_multi_dt_entry((unsigned long)buffer);
#else
dt_addr = (char *)buffer;
#endif
nodeoffset = fdt_path_offset(dt_addr, "/partitions");
if (nodeoffset < 0)
{
printf("%s: not find /partitions node %s.\n",__func__,fdt_strerror(nodeoffset));
ret = -1;
goto _err;
}
parts_num = (int *)fdt_getprop(dt_addr, nodeoffset, "parts", NULL);
printf("parts: %d\n",be32_to_cpup((u32*)parts_num));
if (parts_num > 0)
{
part_table = (struct partitions *)malloc(sizeof(struct partitions)*(be32_to_cpup((u32*)parts_num)));
if (!part_table) {
printk("%s part_table alloc _err\n",__func__);
//kfree(data);
return -1;
}
memset(part_table, 0, sizeof(struct partitions)*(be32_to_cpup((u32*)parts_num)));
parts_total_num = be32_to_cpup((u32*)parts_num);
}
for (index = 0; index < be32_to_cpup((u32*)parts_num); index++)
{
sprintf(propname,"part-%d", index);
phandle = fdt_getprop(dt_addr, nodeoffset, propname, NULL);
if (!phandle) {
printf("don't find match part-%d\n",index);
goto _err;
}
if (phandle) {
poffset = fdt_node_offset_by_phandle(dt_addr, be32_to_cpup((u32*)phandle));
if (!poffset) {
printf("%s:%d,can't find device node\n",__func__,__LINE__);
goto _err;
}
}
uname = fdt_getprop(dt_addr, poffset, "pname", NULL);
//printf("%s:%d uname: %s\n",__func__,__LINE__, uname);
/* a string but not */
usize = fdt_getprop(dt_addr, poffset, "size", NULL);
//printf("%s:%d size: 0x%x 0x%x\n",__func__,__LINE__, be32_to_cpup((u32*)usize), be32_to_cpup((((u32*)usize)+1)));
umask = fdt_getprop(dt_addr, poffset, "mask", NULL);
//printf("%s:%d mask: 0x%x\n",__func__,__LINE__, be32_to_cpup((u32*)umask));
/* fill parition table */
if (uname != NULL)
memcpy(part_table[index].name, uname, strlen(uname));
part_table[index].size = ((unsigned long)be32_to_cpup((u32*)usize) << 32) | (unsigned long)be32_to_cpup((((u32*)usize)+1));
part_table[index].mask_flags = be32_to_cpup((u32*)umask);
printf("%02d:%10s\t%016llx %01x\n", index, uname, part_table[index].size, part_table[index].mask_flags);
if (strcmp(uname, "boot_a") == 0)
has_boot_slot = 1;
if (strcmp(uname, "system_a") == 0)
has_system_slot = 1;
}
return 0;
_err:
if (part_table != NULL) {
free(part_table);
part_table = NULL;
}
return ret;
}