blob: 07cede0d3fa840db065e0856343078c7fc5117a8 [file] [log] [blame] [edit]
/*
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* *
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.
* *
You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* *
Description:
*/
#include <common.h>
#include <malloc.h>
#include <linux/err.h>
#include <partition_table.h>
#include <libfdt.h>
#include <asm/arch/bl31_apis.h>
#include <asm/arch/secure_apb.h>
extern int is_dtb_encrypt(unsigned char *buffer);
extern int check_valid_dts(unsigned char *buffer, unsigned char **dts);
#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;
bool dynamic_partition = false;
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;
}
int get_partition_from_zircon(struct partitions *parts, uint32_t num_parts) {
if (num_parts > 0)
{
part_table = (struct partitions *)malloc(sizeof(struct partitions)*num_parts);
if (!part_table) {
printk("%s part_table alloc _err\n",__func__);
return -1;
}
memset(part_table, 0, sizeof(struct partitions)*num_parts);
parts_total_num = num_parts;
int i;
for (i = 0; i < num_parts; i++){
memcpy(part_table[i].name, parts[i].name, strlen(parts[i].name));
part_table[i].size = parts[i].size;
part_table[i].mask_flags = parts[i].mask_flags;
printf("%02d:%10s\t%016llx %01x\n", i, part_table[i].name, part_table[i].size, part_table[i].mask_flags);
}
return 0;
}
return -1;
}
int get_partition_from_dts(unsigned char *buffer)
{
unsigned char *dt_addr = buffer;
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;
ret = check_valid_dts(buffer, &dt_addr);
printf("%s() %d: ret %d\n",__func__, __LINE__, ret);
if ( ret < 0 )
goto _err;
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);
if (!parts_num)
goto _err;
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);
}
dynamic_partition = false;
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;
printf("set has_boot_slot = 1\n");
}
else if (strcmp(uname, "boot") == 0) {
has_boot_slot = 0;
printf("set has_boot_slot = 0\n");
}
if (strcmp(uname, "system_a") == 0)
has_system_slot = 1;
else if (strcmp(uname, "system") == 0)
has_system_slot = 0;
if (strcmp(uname, "super") == 0) {
dynamic_partition = true;
printf("enable dynamic_partition\n");
}
}
return 0;
_err:
if (part_table != NULL) {
free(part_table);
part_table = NULL;
}
return ret;
}