blob: b1b9b31a33a87d99a8b7f13556252e0f0f577580 [file] [log] [blame]
/*
* Copyright (C) 2015 Hardkernel Co,. Ltd
* Dongjin Kim <tobetter@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <linux/sizes.h>
#include <linux/string.h>
#include <usb/fastboot.h>
/* FIXME: Is block size always 512? */
#define bytes_to_lba(x) ((x) / 512)
#define gbytes_to_lba(x) ((x) * 1024 * 1024 * 2)
#define SZ_RESERVED (48 * SZ_1K + 512) /* BL1 + MBR */
#define SZ_BOOTLOADER (720 * SZ_1K)
#define SZ_BOOTMESSAGE (4 * SZ_1K)
static struct fbt_partition {
const char *name;
lbaint_t lba;
} partitions[] = {
{
.name = "-reserved",
.lba = bytes_to_lba(SZ_RESERVED)
}, {
.name = "bootloader",
.lba = bytes_to_lba(SZ_BOOTLOADER
- (SZ_RESERVED + SZ_BOOTMESSAGE))
}, {
.name = "bcb", /* Bootloader control block */
.lba = bytes_to_lba(SZ_BOOTMESSAGE)
}, {
.name = "env", /* "environment" */
.lba = bytes_to_lba(CONFIG_ENV_SIZE)
}, {
.name = "dtb", /* Device Tree */
.lba = bytes_to_lba(SZ_64K)
}, {
.name = "boot", /* Boot image */
.lba = bytes_to_lba(16 * SZ_1M)
}, {
.name = "recovery", /* Recovery Image */
.lba = bytes_to_lba(12 * SZ_1M)
}, {
.name = "logo", /* Logo */
.lba = bytes_to_lba(2 * SZ_1M)
}
};
static struct dos_partition {
const char *name;
int part;
u8 type;
lbaint_t lba;
} dos_partitions[] = {
{
.name = "cache",
.part = 2,
.type = 0x83,
.lba = bytes_to_lba(512 * SZ_1M),
}, {
.name = "system",
.part = 3,
.type = 0x83,
.lba = gbytes_to_lba(1),
}, {
.name = "userdata",
.part = 4,
.type = 0x83,
.lba = gbytes_to_lba(3),
}, {
.name = "vfat",
.part = 1,
.type = 0x0c,
.lba = -1,
},
};
static int n = 0;
static int valid_partition_number(int part)
{
return (1 <= part) && (part <= ARRAY_SIZE(dos_partitions));
}
/*
* Initiate dos partition index and return the first sector (lba)
*/
lbaint_t board_dos_partition_start(void)
{
int n;
lbaint_t next = 0;
for (n = 0 ; n < ARRAY_SIZE(partitions); n++)
next += partitions[n].lba;
return next;
}
/*
* Get the partition detail, partition number and its type, as well as
* return the number of sectors to allocate for the partition.
*/
lbaint_t board_dos_partition_next(int *part, u8 *type)
{
if (!valid_partition_number(n + 1))
return 0;
struct dos_partition *p = &dos_partitions[n++];
*part = p->part; /* partition number */
*type = p->type; /* partition type */
/* Use remained sectors for this partition */
if (p->lba == -1)
return -1;
return p->lba;
}
/*
* Return the partition name of given partiton number. Since DOS partition
* does not support name on its parition table, the partition names are
* predefined upon each partition number.
*/
char *board_dos_partition_name(int part, char* name)
{
int i;
if (!valid_partition_number(part))
return NULL;
for (i = 0; i < ARRAY_SIZE(dos_partitions); i++) {
/* Partition number is same with given to seek */
if (dos_partitions[i].part == part) {
strcpy(name, dos_partitions[i].name);
return name;
}
}
return NULL;
}
/*
* Initiate the fastboot partition entries with internal system partitions and
* DOS partition table.
*/
int board_partition_init(void)
{
struct mmc *mmc;
fastboot_ptentry ptn;
lbaint_t next = 0;
lbaint_t len;
int n = 0;
fastboot_flash_reset_ptn();
mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
for (n = 0 ; mmc && n < ARRAY_SIZE(partitions); n++) {
len = partitions[n].lba;
/* Skip to add the partition if start with '-', but move forward
* to next position as much as its size
*/
if (partitions[n].name[0] == '-') {
next += len;
continue;
}
/* 'env' partition contains U-boot's environment fields, it
* could be damaged by fastboot if its offset is invalid with
* defined by CONFIG_ENV_OFFSET.
*/
if (!strcmp(partitions[n].name, "env") &&
(bytes_to_lba(CONFIG_ENV_OFFSET) != next)) {
printf("WARNING!!: Invalid offset of 'env' partition,"
" it must be " LBAFU " but " LBAFU "\n",
next, (lbaint_t)bytes_to_lba(CONFIG_ENV_OFFSET));
}
if (len == 0)
len = mmc->block_dev.lba - next;
strncpy((char*)&ptn.name, partitions[n].name, sizeof(ptn.name));
ptn.start = next;
ptn.length = len;
/* Add the partition to fastboot partition entry table */
fastboot_flash_add_ptn(&ptn);
next += len;
}
fastboot_load_dos_partition();
return 0;
}
int board_fastboot_pre_flash(block_dev_desc_t *dev_desc, lbaint_t start,
void *buffer)
{
if (start == 0) {
/* MUST be trying to modify MBR, hence at least DOS partition
* table have to be kept. So buffer to flashing will be
* overwritten with exist partition table.
*/
u8 mbr[512];
if (dev_desc->block_read(dev_desc->dev, start, 1, mbr) != 1) {
printf("fastboot: can't read MBR from device %d\n",
dev_desc->dev);
return -EIO;
}
memcpy(buffer + 0x1be, &mbr[0x1be], 512 - 0x1be);
}
return 0;
}