170 lines
3.6 KiB
C
170 lines
3.6 KiB
C
/*
|
|
* 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 (blk_dwrite(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;
|
|
}
|