blob: fa27ad89e0853f38c30b1e5eb41771ceeaa19766 [file] [log] [blame]
/*
* Copyright (c) 2018 The Fuchsia Authors
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common.h>
#include <fs.h>
#include <version.h>
#include <zircon_uboot/zircon.h>
#define PDEV_VID_GOOGLE 3
#define PDEV_PID_SHERLOCK 5
#define NVRAM_LENGTH (8 * 1024)
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 = 0x80000000, // 2 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_SHERLOCK,
.board_name = "sherlock",
};
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 PUDDY_FACTORY_IF "mmc"
#define PUDDY_FACTORY_PART "1:5"
#define FACTORY_MAC_ADDR_BUFF_LEN 30
#define PUDDY_FACTORY_MACADDR_FILE "mac_addr"
#define FACTORY_MAC_ADDR_FILE_LEN 25
static int add_mac_addresses(zbi_header_t* zbi) {
char buffer[FACTORY_MAC_ADDR_BUFF_LEN];
u64 fullmac[2];
u8 mac_addr[6];
int len_read;
int mac_num, i;
if (fs_set_blk_dev(PUDDY_FACTORY_IF, PUDDY_FACTORY_PART,
FS_TYPE_EXT)) {
printf("set_blk_dev %s-%s failed.\n",
PUDDY_FACTORY_IF, PUDDY_FACTORY_PART);
return -1;
}
if (fs_read(PUDDY_FACTORY_MACADDR_FILE, buffer, 0,
FACTORY_MAC_ADDR_BUFF_LEN, &len_read)) {
printf("Failed to read Mac Addresses from Factory partition\n");
}
if (len_read != FACTORY_MAC_ADDR_FILE_LEN) {
printf("Factory MAC Addr File length (%d) incorrect.\n",
len_read);
return -1;
}
buffer[len_read] = '\0';
/*
* "buffer" should now contain two hex strings separated by \n,
* for a total of 25 bytes. Separate into 2 C strings and convert.
*/
buffer[len_read/2] = '\0';
fullmac[0] = simple_strtoull(buffer, NULL, 16);
fullmac[1] = simple_strtoull(&buffer[(len_read/2)+1], NULL, 16);
for (mac_num = 0; mac_num < ARRAY_SIZE(fullmac); mac_num++) {
for (i = ARRAY_SIZE(mac_addr)-1; i >= 0; i--) {
mac_addr[i] = (u8) (fullmac[mac_num] & 0xff);
fullmac[mac_num] >>= 8;
}
zircon_append_boot_item(zbi, ZBI_TYPE_DRV_MAC_ADDRESS, mac_num,
mac_addr, sizeof(mac_addr));
}
return 0;
}
static void add_board_info(zbi_header_t* zbi)
{
zbi_board_info_t board_info = {};
char* s;
if (((s = env_get("hw_id")) != NULL) && (*s != '\0')) {
uint32_t hw_id = simple_strtoul(s, NULL, 16);
board_info.revision = hw_id;
} else {
printf("Failed to retrieve Board Revision\n");
}
zircon_append_boot_item(zbi, ZBI_TYPE_DRV_BOARD_INFO, 0, &board_info,
sizeof(board_info));
}
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));
char uboot_ver[] = "bootloader.name=" U_BOOT_VERSION_STRING;
// Zircon's cmdline parameters cannot contain spaces so
// convert spaces in autogenerated U-boot version string
// to underscores.
// See zircon/docs/kernel_cmdline.md
int i;
int len = strlen(uboot_ver);
for (i = 0; i < len; i++) {
if (uboot_ver[i] == ' ') {
uboot_ver[i] = '_';
}
}
zircon_append_boot_item(zbi, ZBI_TYPE_CMDLINE, 0, uboot_ver, len + 1);
/* Add board-specific information */
add_board_info(zbi);
/* add platform ID */
zircon_append_boot_item(zbi, ZBI_TYPE_PLATFORM_ID, 0, &platform_id,
sizeof(platform_id));
int ret = add_mac_addresses(zbi);
if (ret < 0) {
printf("ERROR: unable to read MAC addresses from the"
" factory partition!\n");
}
return 0;
}