blob: 4cc9e5d31202b9f1037aff99999af2d17ecbb639 [file] [log] [blame] [edit]
/*
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <fsl_fastboot.h>
#include <linux/stat.h>
#include <linux/types.h>
#include <common.h>
#include <g_dnl.h>
#include <mmc.h>
#include "bcb.h"
#define ALIGN_BYTES 64 /*armv7 cache line need 64 bytes aligned */
static ulong get_block_size(char *ifname, int dev)
{
struct blk_desc *dev_desc = NULL;
dev_desc = blk_get_dev(ifname, dev);
if (dev_desc == NULL) {
printf("Block device %s %d not supported\n", ifname, dev);
return 0;
}
return dev_desc->blksz;
}
static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
char *ep;
struct blk_desc *dev_desc = NULL;
int dev;
int part = 0;
disk_partition_t part_info;
ulong offset = 0u;
ulong limit = 0u;
void *addr;
uint blk;
uint cnt;
if (argc != 6) {
cmd_usage(cmdtp);
return 1;
}
dev = (int)simple_strtoul(argv[2], &ep, 16);
if (*ep) {
if (*ep != ':') {
printf("Invalid block device %s\n", argv[2]);
return 1;
}
part = (int)simple_strtoul(++ep, NULL, 16);
}
dev_desc = blk_get_dev(argv[1], dev);
if (dev_desc == NULL) {
printf("Block device %s %d not supported\n", argv[1], dev);
return 1;
}
addr = (void *)simple_strtoul(argv[3], NULL, 16);
blk = simple_strtoul(argv[4], NULL, 16);
cnt = simple_strtoul(argv[5], NULL, 16);
if (part != 0) {
if (part_get_info(dev_desc, part, &part_info)) {
printf("Cannot find partition %d\n", part);
return 1;
}
offset = part_info.start;
limit = part_info.size;
} else {
/* Largest address not available in block_dev_desc_t. */
limit = ~0;
}
if (cnt + blk > limit) {
printf("Write out of range\n");
return 1;
}
if (dev_desc->block_write(dev_desc, offset + blk, cnt, addr) != cnt) {
printf("Error writing blocks\n");
return 1;
}
return 0;
}
U_BOOT_CMD(
write, 6, 0, do_write,
"write binary data to a partition",
"<interface> <dev[:part]> addr blk# cnt"
);
int bcb_rw_block(bool bread, char **ppblock,
uint *pblksize, char *pblock_write, uint offset, uint size)
{
int ret;
char *argv[6];
char addr_str[20];
char cnt_str[8];
char devpart_str[8];
char block_begin_str[8];
ulong blk_size = 0;
uint blk_begin = 0;
uint blk_end = 0;
uint block_cnt = 0;
char *p_block = NULL;
unsigned int mmc_id;
if (bread && ((ppblock == NULL) || (pblksize == NULL)))
return -1;
if (!bread && (pblock_write == NULL))
return -1;
mmc_id = mmc_get_env_dev();
blk_size = get_block_size("mmc", mmc_id);
if (blk_size == 0) {
printf("bcb_rw_block, get_block_size return 0\n");
return -1;
}
blk_begin = offset/blk_size;
blk_end = (offset + size)/blk_size;
block_cnt = 1 + (blk_end - blk_begin);
sprintf(devpart_str, "0x%x:0x%x", mmc_id,
fastboot_flash_find_index(FASTBOOT_PARTITION_MISC));
sprintf(block_begin_str, "0x%x", blk_begin);
sprintf(cnt_str, "0x%x", block_cnt);
argv[0] = "rw"; /* not care */
argv[1] = "mmc";
argv[2] = devpart_str;
argv[3] = addr_str;
argv[4] = block_begin_str;
argv[5] = cnt_str;
if (bread) {
p_block = (char *)memalign(ALIGN_BYTES, blk_size * block_cnt);
if (NULL == p_block) {
printf("bcb_rw_block, memalign %d bytes failed\n",
(int)(blk_size * block_cnt));
return -1;
}
sprintf(addr_str, "0x%x", (unsigned int)(uintptr_t)p_block);
ret = do_raw_read(NULL, 0, 6, argv);
if (ret) {
free(p_block);
printf("do_raw_read failed, ret %d\n", ret);
return -1;
}
*ppblock = p_block;
*pblksize = (uint)blk_size;
} else {
sprintf(addr_str, "0x%x", (unsigned int)(uintptr_t)pblock_write);
ret = do_write(NULL, 0, 6, argv);
if (ret) {
printf("do_write failed, ret %d\n", ret);
return -1;
}
}
return 0;
}