blob: 8e6888f8ecbde497c75c5cff2510b3f635731b8a [file] [log] [blame]
/*
* Copyright (c) 2018 The Fuchsia Authors
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common.h>
#include <linux/mtd/partitions.h>
#include <nand.h>
#include <part.h>
#include <emmc_storage.h>
#include <zircon/zircon.h>
#define PDEV_VID_GOOGLE 3
#define PDEV_PID_ASTRO 3
#define NVRAM_LENGTH (8 * 1024)
const char* BOOTLOADER_VERSION = "zircon-bootloader=0.10";
static const zbi_cpu_config_t cpu_config = {
.cluster_count = 1,
.clusters = {
{
.cpu_count = 4,
},
},
};
static const zbi_mem_range_t mem_config[] = {
{
.type = ZBI_MEM_RANGE_RAM,
.length = 0x60000000, // 1.5 GB
},
{
.type = ZBI_MEM_RANGE_PERIPHERAL,
.paddr = 0xf5800000,
.length = 0x0a800000,
},
// secmon_reserved:linux,secmon
{
.type = ZBI_MEM_RANGE_RESERVED,
.paddr = 0x05000000,
.length = 0x2400000,
},
// logo_reserved:linux,meson-fb
{
.type = ZBI_MEM_RANGE_RESERVED,
.paddr = 0x5f800000,
.length = 0x800000,
},
};
static const dcfg_simple_t uart_driver = {
.mmio_phys = 0xff803000,
.irq = 225,
};
static const dcfg_arm_gicv2_driver_t gicv2_driver = {
.mmio_phys = 0xffc00000,
.gicd_offset = 0x1000,
.gicc_offset = 0x2000,
.gich_offset = 0x4000,
.gicv_offset = 0x6000,
.ipi_base = 5,
};
static const dcfg_arm_psci_driver_t psci_driver = {
.use_hvc = false,
.reboot_args = { 1, 0, 0 },
.reboot_bootloader_args = { 4, 0, 0 },
.reboot_recovery_args = { 2, 0, 0 },
};
static const dcfg_arm_generic_timer_driver_t timer_driver = {
.irq_phys = 30,
};
static const zbi_platform_id_t platform_id = {
.vid = PDEV_VID_GOOGLE,
.pid = PDEV_PID_ASTRO,
.board_name = "astro",
};
enum {
PART_TPL,
PART_FTS,
PART_FACTORY,
PART_ZIRCON_B,
PART_ZIRCON_A,
PART_ZIRCON_R,
PART_FVM,
PART_SYS_CONFIG,
PART_MIGRATION,
PART_COUNT,
};
#define RECOVERY_SIZE (16 * 1024 * 1024)
#define SYS_CONFIG_SIZE (1 * 1024 * 1024)
#define MIGRATION_SIZE (3 * 1024 * 1024)
static zbi_partition_map_t partition_map = {
// .block_count filled in below
// .block_size filled in below
.guid = {},
.partition_count = PART_COUNT,
.partitions = {
{
.type_guid = GUID_BOOTLOADER_VALUE,
.name = "tpl",
},
{
.name = "fts",
},
{
.name = "factory",
},
{
.type_guid = GUID_ZIRCON_R_VALUE,
.name = "zircon-r",
},
{
.type_guid = GUID_ZIRCON_A_VALUE,
.name = "zircon-a",
},
{
.type_guid = GUID_ZIRCON_B_VALUE,
.name = "zircon-b",
},
{
.type_guid = GUID_FVM_VALUE,
.name = "fvm",
},
{
.type_guid = GUID_SYS_CONFIG_VALUE,
.name = "sys-config",
},
{
.name = "migration",
},
},
};
extern struct mtd_partition *get_aml_mtd_partition(void);
extern int get_aml_partition_count(void);
static void add_partition_map(zbi_header_t* zbi) {
struct mtd_partition* tpl_part = NULL;
struct mtd_partition* fts_part = NULL;
struct mtd_partition* factory_part = NULL;
struct mtd_partition* recovery_part = NULL;
struct mtd_partition* boot_part = NULL;
struct mtd_partition* system_part = NULL;
struct mtd_partition* partitions = get_aml_mtd_partition();
int partition_count = get_aml_partition_count();
int i;
for (i = 0; i < partition_count; i++) {
struct mtd_partition* part = &partitions[i];
if (!strcmp("tpl", part->name)) {
tpl_part = part;
} else if (!strcmp("fts", part->name)) {
fts_part = part;
} else if (!strcmp("factory", part->name)) {
factory_part = part;
} else if (!strcmp("recovery", part->name)) {
recovery_part = part;
} else if (!strcmp("boot", part->name)) {
boot_part = part;
} else if (!strcmp("system", part->name)) {
system_part = part;
}
}
if (!tpl_part) {
printf("could not find tpl partition\n");
return;
}
if (!fts_part) {
printf("could not find fts partition\n");
return;
}
if (!factory_part) {
printf("could not find factory partition\n");
return;
}
if (!recovery_part) {
printf("could not find recovery partition\n");
return;
}
if (!boot_part) {
printf("could not find boot partition\n");
return;
}
if (!system_part) {
printf("could not find system partition\n");
return;
}
uint32_t block_size = nand_info[1].writesize;
uint64_t total_size = nand_info[1].size;
partition_map.block_size = block_size;
partition_map.block_count = total_size / block_size;
// map tpl partition to BOOTLOADER
partition_map.partitions[PART_TPL].first_block = tpl_part->offset / block_size;
partition_map.partitions[PART_TPL].last_block =
((tpl_part->offset + tpl_part->size) / block_size) - 1;
// map fts partition to "fts"
partition_map.partitions[PART_FTS].first_block = fts_part->offset / block_size;
partition_map.partitions[PART_FTS].last_block =
((fts_part->offset + fts_part->size) / block_size) - 1;
// map factory partition to "factory"
partition_map.partitions[PART_FACTORY].first_block = factory_part->offset / block_size;
partition_map.partitions[PART_FACTORY].last_block =
((factory_part->offset + factory_part->size) / block_size) - 1;
// map recovery partition to ZIRCON_B
partition_map.partitions[PART_ZIRCON_B].first_block = recovery_part->offset / block_size;
partition_map.partitions[PART_ZIRCON_B].last_block =
((recovery_part->offset + recovery_part->size) / block_size) - 1;
// map boot partition to ZIRCON_A
partition_map.partitions[PART_ZIRCON_A].first_block = boot_part->offset / block_size;
partition_map.partitions[PART_ZIRCON_A].last_block =
((boot_part->offset + boot_part->size) / block_size) - 1;
// ZIRCON_R partition at start of system
partition_map.partitions[PART_ZIRCON_R].first_block = system_part->offset / block_size;
partition_map.partitions[PART_ZIRCON_R].last_block =
partition_map.partitions[PART_ZIRCON_R].first_block +
(RECOVERY_SIZE / block_size) - 1;
// FVM follows ZIRCON_R
partition_map.partitions[PART_FVM].first_block =
partition_map.partitions[PART_ZIRCON_R].last_block + 1;
partition_map.partitions[PART_FVM].last_block =
((total_size - SYS_CONFIG_SIZE - MIGRATION_SIZE) / block_size) - 1;
// SYS_CONFIG follows FVM
partition_map.partitions[PART_SYS_CONFIG].first_block =
partition_map.partitions[PART_FVM].last_block + 1;
partition_map.partitions[PART_SYS_CONFIG].last_block =
partition_map.partitions[PART_SYS_CONFIG].first_block +
(SYS_CONFIG_SIZE / block_size) - 1;
// MIGRATION follows SYS_CONFIG
partition_map.partitions[PART_MIGRATION].first_block =
partition_map.partitions[PART_SYS_CONFIG].last_block + 1;
partition_map.partitions[PART_MIGRATION].last_block =
partition_map.partitions[PART_MIGRATION].first_block +
(MIGRATION_SIZE / block_size) - 1;
printf("Zircon partitions:\n");
for (i = 0; i < PART_COUNT; i++) {
printf(" 0x%016llx - 0x%016llx : %s\n",
partition_map.partitions[i].first_block * block_size,
(partition_map.partitions[i].last_block + 1) * block_size,
partition_map.partitions[i].name);
}
zircon_append_boot_item(zbi, ZBI_TYPE_DRV_PARTITION_MAP, 0, &partition_map,
sizeof(zbi_partition_map_t) +
partition_map.partition_count * sizeof(zbi_partition_t));
}
int zircon_preboot(zbi_header_t* zbi) {
// add CPU configuration
zircon_append_boot_item(zbi, ZBI_TYPE_CPU_CONFIG, 0, &cpu_config,
sizeof(zbi_cpu_config_t) +
sizeof(zbi_cpu_cluster_t) * cpu_config.cluster_count);
// allocate crashlog save area before 0x5f800000-0x60000000 reserved area
zbi_nvram_t nvram;
nvram.base = 0x5f800000 - NVRAM_LENGTH;
nvram.length = NVRAM_LENGTH;
zircon_append_boot_item(zbi, ZBI_TYPE_NVRAM, 0, &nvram, sizeof(nvram));
// add memory configuration
zircon_append_boot_item(zbi, ZBI_TYPE_MEM_CONFIG, 0, &mem_config, sizeof(mem_config));
// add kernel drivers
zircon_append_boot_item(zbi, ZBI_TYPE_KERNEL_DRIVER, KDRV_AMLOGIC_UART, &uart_driver,
sizeof(uart_driver));
zircon_append_boot_item(zbi, ZBI_TYPE_KERNEL_DRIVER, KDRV_ARM_GIC_V2, &gicv2_driver,
sizeof(gicv2_driver));
zircon_append_boot_item(zbi, ZBI_TYPE_KERNEL_DRIVER, KDRV_ARM_PSCI, &psci_driver,
sizeof(psci_driver));
zircon_append_boot_item(zbi, ZBI_TYPE_KERNEL_DRIVER, KDRV_ARM_GENERIC_TIMER, &timer_driver,
sizeof(timer_driver));
zircon_append_boot_item(zbi, ZBI_TYPE_CMDLINE, 0, BOOTLOADER_VERSION, strlen(BOOTLOADER_VERSION) + 1);
// add platform ID
zircon_append_boot_item(zbi, ZBI_TYPE_PLATFORM_ID, 0, &platform_id, sizeof(platform_id));
add_partition_map(zbi);
return 0;
}