mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-24 20:54:24 +08:00
Merge branch 'master' of git://git.denx.de/u-boot-mmc
This commit is contained in:
commit
638b3e8342
10
README
10
README
@ -1534,6 +1534,16 @@ The following options need to be configured:
|
||||
CONFIG_SH_MMCIF_CLK
|
||||
Define the clock frequency for MMCIF
|
||||
|
||||
CONFIG_GENERIC_MMC
|
||||
Enable the generic MMC driver
|
||||
|
||||
CONFIG_SUPPORT_EMMC_BOOT
|
||||
Enable some additional features of the eMMC boot partitions.
|
||||
|
||||
CONFIG_SUPPORT_EMMC_RPMB
|
||||
Enable the commands for reading, writing and programming the
|
||||
key for the Replay Protection Memory Block partition in eMMC.
|
||||
|
||||
- USB Device Firmware Update (DFU) class support:
|
||||
CONFIG_DFU_FUNCTION
|
||||
This enables the USB portion of the DFU USB class
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/arch/mmc_host_def.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <i2c.h>
|
||||
@ -214,3 +215,9 @@ int board_eth_init(bd_t *bis)
|
||||
return rv;
|
||||
}
|
||||
#endif /* CONFIG_DRIVER_TI_CPSW */
|
||||
#if defined(CONFIG_GENERIC_MMC) && !defined(CONFIG_SPL_BUILD)
|
||||
int board_mmc_init(bd_t *bis)
|
||||
{
|
||||
return omap_mmc_init(1, 0, 0, -1, -1);
|
||||
}
|
||||
#endif
|
||||
|
@ -33,15 +33,8 @@ static int confirm_prog(void)
|
||||
"what you are doing!\n"
|
||||
"\nReally perform this fuse programming? <y/N>\n");
|
||||
|
||||
if (getc() == 'y') {
|
||||
int c;
|
||||
|
||||
putc('y');
|
||||
c = getc();
|
||||
putc('\n');
|
||||
if (c == '\r')
|
||||
return 1;
|
||||
}
|
||||
if (confirm_yesno())
|
||||
return 1;
|
||||
|
||||
puts("Fuse programming aborted\n");
|
||||
return 0;
|
||||
|
875
common/cmd_mmc.c
875
common/cmd_mmc.c
@ -71,12 +71,6 @@ U_BOOT_CMD(
|
||||
);
|
||||
#else /* !CONFIG_GENERIC_MMC */
|
||||
|
||||
enum mmc_state {
|
||||
MMC_INVALID,
|
||||
MMC_READ,
|
||||
MMC_WRITE,
|
||||
MMC_ERASE,
|
||||
};
|
||||
static void print_mmcinfo(struct mmc *mmc)
|
||||
{
|
||||
printf("Device: %s\n", mmc->cfg->name);
|
||||
@ -98,7 +92,18 @@ static void print_mmcinfo(struct mmc *mmc)
|
||||
|
||||
printf("Bus Width: %d-bit\n", mmc->bus_width);
|
||||
}
|
||||
|
||||
static struct mmc *init_mmc_device(int dev)
|
||||
{
|
||||
struct mmc *mmc;
|
||||
mmc = find_mmc_device(dev);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", dev);
|
||||
return NULL;
|
||||
}
|
||||
if (mmc_init(mmc))
|
||||
return NULL;
|
||||
return mmc;
|
||||
}
|
||||
static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct mmc *mmc;
|
||||
@ -112,351 +117,537 @@ static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
}
|
||||
}
|
||||
|
||||
mmc = find_mmc_device(curr_device);
|
||||
mmc = init_mmc_device(curr_device);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (mmc) {
|
||||
mmc_init(mmc);
|
||||
|
||||
print_mmcinfo(mmc);
|
||||
return 0;
|
||||
} else {
|
||||
printf("no mmc device at slot %x\n", curr_device);
|
||||
return 1;
|
||||
}
|
||||
print_mmcinfo(mmc);
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
mmcinfo, 1, 0, do_mmcinfo,
|
||||
"display MMC info",
|
||||
"- display info of the current MMC device"
|
||||
);
|
||||
#ifdef CONFIG_SUPPORT_EMMC_RPMB
|
||||
static int confirm_key_prog(void)
|
||||
{
|
||||
puts("Warning: Programming authentication key can be done only once !\n"
|
||||
" Use this command only if you are sure of what you are doing,\n"
|
||||
"Really perform the key programming? <y/N> ");
|
||||
if (confirm_yesno())
|
||||
return 1;
|
||||
|
||||
puts("Authentication key programming aborted\n");
|
||||
return 0;
|
||||
}
|
||||
static int do_mmcrpmb_key(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
void *key_addr;
|
||||
struct mmc *mmc = find_mmc_device(curr_device);
|
||||
|
||||
if (argc != 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
key_addr = (void *)simple_strtoul(argv[1], NULL, 16);
|
||||
if (!confirm_key_prog())
|
||||
return CMD_RET_FAILURE;
|
||||
if (mmc_rpmb_set_key(mmc, key_addr)) {
|
||||
printf("ERROR - Key already programmed ?\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
static int do_mmcrpmb_read(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
u16 blk, cnt;
|
||||
void *addr;
|
||||
int n;
|
||||
void *key_addr = NULL;
|
||||
struct mmc *mmc = find_mmc_device(curr_device);
|
||||
|
||||
if (argc < 4)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
addr = (void *)simple_strtoul(argv[1], NULL, 16);
|
||||
blk = simple_strtoul(argv[2], NULL, 16);
|
||||
cnt = simple_strtoul(argv[3], NULL, 16);
|
||||
|
||||
if (argc == 5)
|
||||
key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
|
||||
|
||||
printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ",
|
||||
curr_device, blk, cnt);
|
||||
n = mmc_rpmb_read(mmc, addr, blk, cnt, key_addr);
|
||||
|
||||
printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
|
||||
if (n != cnt)
|
||||
return CMD_RET_FAILURE;
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
static int do_mmcrpmb_write(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
u16 blk, cnt;
|
||||
void *addr;
|
||||
int n;
|
||||
void *key_addr;
|
||||
struct mmc *mmc = find_mmc_device(curr_device);
|
||||
|
||||
if (argc != 5)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
addr = (void *)simple_strtoul(argv[1], NULL, 16);
|
||||
blk = simple_strtoul(argv[2], NULL, 16);
|
||||
cnt = simple_strtoul(argv[3], NULL, 16);
|
||||
key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
|
||||
|
||||
printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ",
|
||||
curr_device, blk, cnt);
|
||||
n = mmc_rpmb_write(mmc, addr, blk, cnt, key_addr);
|
||||
|
||||
printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
|
||||
if (n != cnt)
|
||||
return CMD_RET_FAILURE;
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
static int do_mmcrpmb_counter(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
unsigned long counter;
|
||||
struct mmc *mmc = find_mmc_device(curr_device);
|
||||
|
||||
if (mmc_rpmb_get_counter(mmc, &counter))
|
||||
return CMD_RET_FAILURE;
|
||||
printf("RPMB Write counter= %lx\n", counter);
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static cmd_tbl_t cmd_rpmb[] = {
|
||||
U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""),
|
||||
U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""),
|
||||
U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""),
|
||||
U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""),
|
||||
};
|
||||
|
||||
static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
cmd_tbl_t *cp;
|
||||
struct mmc *mmc;
|
||||
char original_part;
|
||||
int ret;
|
||||
|
||||
cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb));
|
||||
|
||||
/* Drop the rpmb subcommand */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (cp == NULL || argc > cp->maxargs)
|
||||
return CMD_RET_USAGE;
|
||||
if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
|
||||
return CMD_RET_SUCCESS;
|
||||
|
||||
mmc = init_mmc_device(curr_device);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (!(mmc->version & MMC_VERSION_MMC)) {
|
||||
printf("It is not a EMMC device\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
if (mmc->version < MMC_VERSION_4_41) {
|
||||
printf("RPMB not supported before version 4.41\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
/* Switch to the RPMB partition */
|
||||
original_part = mmc->part_num;
|
||||
if (mmc->part_num != MMC_PART_RPMB) {
|
||||
if (mmc_switch_part(curr_device, MMC_PART_RPMB) != 0)
|
||||
return CMD_RET_FAILURE;
|
||||
mmc->part_num = MMC_PART_RPMB;
|
||||
}
|
||||
ret = cp->cmd(cmdtp, flag, argc, argv);
|
||||
|
||||
/* Return to original partition */
|
||||
if (mmc->part_num != original_part) {
|
||||
if (mmc_switch_part(curr_device, original_part) != 0)
|
||||
return CMD_RET_FAILURE;
|
||||
mmc->part_num = original_part;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
struct mmc *mmc;
|
||||
u32 blk, cnt, n;
|
||||
void *addr;
|
||||
|
||||
if (argc != 4)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
addr = (void *)simple_strtoul(argv[1], NULL, 16);
|
||||
blk = simple_strtoul(argv[2], NULL, 16);
|
||||
cnt = simple_strtoul(argv[3], NULL, 16);
|
||||
|
||||
mmc = init_mmc_device(curr_device);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
printf("\nMMC read: dev # %d, block # %d, count %d ... ",
|
||||
curr_device, blk, cnt);
|
||||
|
||||
n = mmc->block_dev.block_read(curr_device, blk, cnt, addr);
|
||||
/* flush cache after read */
|
||||
flush_cache((ulong)addr, cnt * 512); /* FIXME */
|
||||
printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
|
||||
|
||||
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
|
||||
}
|
||||
static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
struct mmc *mmc;
|
||||
u32 blk, cnt, n;
|
||||
void *addr;
|
||||
|
||||
if (argc != 4)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
addr = (void *)simple_strtoul(argv[1], NULL, 16);
|
||||
blk = simple_strtoul(argv[2], NULL, 16);
|
||||
cnt = simple_strtoul(argv[3], NULL, 16);
|
||||
|
||||
mmc = init_mmc_device(curr_device);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
printf("\nMMC write: dev # %d, block # %d, count %d ... ",
|
||||
curr_device, blk, cnt);
|
||||
|
||||
if (mmc_getwp(mmc) == 1) {
|
||||
printf("Error: card is write protected!\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
n = mmc->block_dev.block_write(curr_device, blk, cnt, addr);
|
||||
printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
|
||||
|
||||
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
|
||||
}
|
||||
static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
struct mmc *mmc;
|
||||
u32 blk, cnt, n;
|
||||
|
||||
if (argc != 3)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
blk = simple_strtoul(argv[1], NULL, 16);
|
||||
cnt = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
mmc = init_mmc_device(curr_device);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
printf("\nMMC erase: dev # %d, block # %d, count %d ... ",
|
||||
curr_device, blk, cnt);
|
||||
|
||||
if (mmc_getwp(mmc) == 1) {
|
||||
printf("Error: card is write protected!\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
n = mmc->block_dev.block_erase(curr_device, blk, cnt);
|
||||
printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
|
||||
|
||||
return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
|
||||
}
|
||||
static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
struct mmc *mmc;
|
||||
|
||||
mmc = find_mmc_device(curr_device);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", curr_device);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
mmc->has_init = 0;
|
||||
|
||||
if (mmc_init(mmc))
|
||||
return CMD_RET_FAILURE;
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
static int do_mmc_part(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
block_dev_desc_t *mmc_dev;
|
||||
struct mmc *mmc;
|
||||
|
||||
mmc = init_mmc_device(curr_device);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
mmc_dev = mmc_get_dev(curr_device);
|
||||
if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
|
||||
print_part(mmc_dev);
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
puts("get mmc type error!\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
int dev, part = -1, ret;
|
||||
struct mmc *mmc;
|
||||
|
||||
if (argc == 1) {
|
||||
dev = curr_device;
|
||||
} else if (argc == 2) {
|
||||
dev = simple_strtoul(argv[1], NULL, 10);
|
||||
} else if (argc == 3) {
|
||||
dev = (int)simple_strtoul(argv[1], NULL, 10);
|
||||
part = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
if (part > PART_ACCESS_MASK) {
|
||||
printf("#part_num shouldn't be larger than %d\n",
|
||||
PART_ACCESS_MASK);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
mmc = init_mmc_device(dev);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (part != -1) {
|
||||
ret = mmc_select_hwpart(dev, part);
|
||||
printf("switch to partitions #%d, %s\n",
|
||||
part, (!ret) ? "OK" : "ERROR");
|
||||
if (ret)
|
||||
return 1;
|
||||
}
|
||||
curr_device = dev;
|
||||
if (mmc->part_config == MMCPART_NOAVAILABLE)
|
||||
printf("mmc%d is current device\n", curr_device);
|
||||
else
|
||||
printf("mmc%d(part %d) is current device\n",
|
||||
curr_device, mmc->part_num);
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
static int do_mmc_list(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
print_mmc_devices('\n');
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
#ifdef CONFIG_SUPPORT_EMMC_BOOT
|
||||
static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
int dev;
|
||||
struct mmc *mmc;
|
||||
u8 width, reset, mode;
|
||||
|
||||
if (argc != 5)
|
||||
return CMD_RET_USAGE;
|
||||
dev = simple_strtoul(argv[1], NULL, 10);
|
||||
width = simple_strtoul(argv[2], NULL, 10);
|
||||
reset = simple_strtoul(argv[3], NULL, 10);
|
||||
mode = simple_strtoul(argv[4], NULL, 10);
|
||||
|
||||
mmc = init_mmc_device(dev);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
puts("BOOT_BUS_WIDTH only exists on eMMC\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
/* acknowledge to be sent during boot operation */
|
||||
return mmc_set_boot_bus_width(mmc, width, reset, mode);
|
||||
}
|
||||
static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
int dev;
|
||||
struct mmc *mmc;
|
||||
u32 bootsize, rpmbsize;
|
||||
|
||||
if (argc != 4)
|
||||
return CMD_RET_USAGE;
|
||||
dev = simple_strtoul(argv[1], NULL, 10);
|
||||
bootsize = simple_strtoul(argv[2], NULL, 10);
|
||||
rpmbsize = simple_strtoul(argv[3], NULL, 10);
|
||||
|
||||
mmc = init_mmc_device(dev);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
printf("It is not a EMMC device\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) {
|
||||
printf("EMMC boot partition Size change Failed.\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
printf("EMMC boot partition Size %d MB\n", bootsize);
|
||||
printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
int dev;
|
||||
struct mmc *mmc;
|
||||
u8 ack, part_num, access;
|
||||
|
||||
if (argc != 5)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
dev = simple_strtoul(argv[1], NULL, 10);
|
||||
ack = simple_strtoul(argv[2], NULL, 10);
|
||||
part_num = simple_strtoul(argv[3], NULL, 10);
|
||||
access = simple_strtoul(argv[4], NULL, 10);
|
||||
|
||||
mmc = init_mmc_device(dev);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
puts("PARTITION_CONFIG only exists on eMMC\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
/* acknowledge to be sent during boot operation */
|
||||
return mmc_set_part_conf(mmc, ack, part_num, access);
|
||||
}
|
||||
static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
int dev;
|
||||
struct mmc *mmc;
|
||||
u8 enable;
|
||||
|
||||
/*
|
||||
* Set the RST_n_ENABLE bit of RST_n_FUNCTION
|
||||
* The only valid values are 0x0, 0x1 and 0x2 and writing
|
||||
* a value of 0x1 or 0x2 sets the value permanently.
|
||||
*/
|
||||
if (argc != 3)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
dev = simple_strtoul(argv[1], NULL, 10);
|
||||
enable = simple_strtoul(argv[2], NULL, 10);
|
||||
|
||||
if (enable > 2 || enable < 0) {
|
||||
puts("Invalid RST_n_ENABLE value\n");
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
mmc = init_mmc_device(dev);
|
||||
if (!mmc)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
puts("RST_n_FUNCTION only exists on eMMC\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
return mmc_set_rst_n_function(mmc, enable);
|
||||
}
|
||||
#endif
|
||||
static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
struct mmc *mmc;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (argc != 2)
|
||||
return CMD_RET_USAGE;
|
||||
val = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
mmc = find_mmc_device(curr_device);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", curr_device);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
ret = mmc_set_dsr(mmc, val);
|
||||
printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
|
||||
if (!ret) {
|
||||
mmc->has_init = 0;
|
||||
if (mmc_init(mmc))
|
||||
return CMD_RET_FAILURE;
|
||||
else
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cmd_tbl_t cmd_mmc[] = {
|
||||
U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
|
||||
U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
|
||||
U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
|
||||
U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
|
||||
U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
|
||||
U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""),
|
||||
U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
|
||||
U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
|
||||
#ifdef CONFIG_SUPPORT_EMMC_BOOT
|
||||
U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
|
||||
U_BOOT_CMD_MKENT(bootpart-resize, 3, 0, do_mmc_boot_resize, "", ""),
|
||||
U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""),
|
||||
U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""),
|
||||
#endif
|
||||
#ifdef CONFIG_SUPPORT_EMMC_RPMB
|
||||
U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""),
|
||||
#endif
|
||||
U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""),
|
||||
};
|
||||
|
||||
static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
enum mmc_state state;
|
||||
cmd_tbl_t *cp;
|
||||
|
||||
if (argc < 2)
|
||||
cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc));
|
||||
|
||||
/* Drop the mmc command */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (cp == NULL || argc > cp->maxargs)
|
||||
return CMD_RET_USAGE;
|
||||
if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
|
||||
return CMD_RET_SUCCESS;
|
||||
|
||||
if (curr_device < 0) {
|
||||
if (get_mmc_num() > 0)
|
||||
if (get_mmc_num() > 0) {
|
||||
curr_device = 0;
|
||||
else {
|
||||
} else {
|
||||
puts("No MMC device available\n");
|
||||
return 1;
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "rescan") == 0) {
|
||||
struct mmc *mmc;
|
||||
|
||||
if (argc != 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
mmc = find_mmc_device(curr_device);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", curr_device);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mmc->has_init = 0;
|
||||
|
||||
if (mmc_init(mmc))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "part") == 0) {
|
||||
block_dev_desc_t *mmc_dev;
|
||||
struct mmc *mmc;
|
||||
|
||||
if (argc != 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
mmc = find_mmc_device(curr_device);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", curr_device);
|
||||
return 1;
|
||||
}
|
||||
mmc_init(mmc);
|
||||
mmc_dev = mmc_get_dev(curr_device);
|
||||
if (mmc_dev != NULL &&
|
||||
mmc_dev->type != DEV_TYPE_UNKNOWN) {
|
||||
print_part(mmc_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
puts("get mmc type error!\n");
|
||||
return 1;
|
||||
} else if (strcmp(argv[1], "list") == 0) {
|
||||
if (argc != 2)
|
||||
return CMD_RET_USAGE;
|
||||
print_mmc_devices('\n');
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "dev") == 0) {
|
||||
int dev, part = -1;
|
||||
struct mmc *mmc;
|
||||
|
||||
if (argc == 2)
|
||||
dev = curr_device;
|
||||
else if (argc == 3)
|
||||
dev = simple_strtoul(argv[2], NULL, 10);
|
||||
else if (argc == 4) {
|
||||
dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
part = (int)simple_strtoul(argv[3], NULL, 10);
|
||||
if (part > PART_ACCESS_MASK) {
|
||||
printf("#part_num shouldn't be larger"
|
||||
" than %d\n", PART_ACCESS_MASK);
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
mmc = find_mmc_device(dev);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mmc_init(mmc);
|
||||
if (part != -1) {
|
||||
int ret;
|
||||
if (mmc->part_config == MMCPART_NOAVAILABLE) {
|
||||
printf("Card doesn't support part_switch\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (part != mmc->part_num) {
|
||||
ret = mmc_switch_part(dev, part);
|
||||
if (!ret)
|
||||
mmc->part_num = part;
|
||||
|
||||
printf("switch to partitions #%d, %s\n",
|
||||
part, (!ret) ? "OK" : "ERROR");
|
||||
}
|
||||
}
|
||||
curr_device = dev;
|
||||
if (mmc->part_config == MMCPART_NOAVAILABLE)
|
||||
printf("mmc%d is current device\n", curr_device);
|
||||
else
|
||||
printf("mmc%d(part %d) is current device\n",
|
||||
curr_device, mmc->part_num);
|
||||
|
||||
return 0;
|
||||
#ifdef CONFIG_SUPPORT_EMMC_BOOT
|
||||
} else if (strcmp(argv[1], "partconf") == 0) {
|
||||
int dev;
|
||||
struct mmc *mmc;
|
||||
u8 ack, part_num, access;
|
||||
|
||||
if (argc == 6) {
|
||||
dev = simple_strtoul(argv[2], NULL, 10);
|
||||
ack = simple_strtoul(argv[3], NULL, 10);
|
||||
part_num = simple_strtoul(argv[4], NULL, 10);
|
||||
access = simple_strtoul(argv[5], NULL, 10);
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
mmc = find_mmc_device(dev);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
puts("PARTITION_CONFIG only exists on eMMC\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* acknowledge to be sent during boot operation */
|
||||
return mmc_set_part_conf(mmc, ack, part_num, access);
|
||||
} else if (strcmp(argv[1], "bootbus") == 0) {
|
||||
int dev;
|
||||
struct mmc *mmc;
|
||||
u8 width, reset, mode;
|
||||
|
||||
if (argc == 6) {
|
||||
dev = simple_strtoul(argv[2], NULL, 10);
|
||||
width = simple_strtoul(argv[3], NULL, 10);
|
||||
reset = simple_strtoul(argv[4], NULL, 10);
|
||||
mode = simple_strtoul(argv[5], NULL, 10);
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
mmc = find_mmc_device(dev);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
puts("BOOT_BUS_WIDTH only exists on eMMC\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* acknowledge to be sent during boot operation */
|
||||
return mmc_set_boot_bus_width(mmc, width, reset, mode);
|
||||
} else if (strcmp(argv[1], "bootpart-resize") == 0) {
|
||||
int dev;
|
||||
struct mmc *mmc;
|
||||
u32 bootsize, rpmbsize;
|
||||
|
||||
if (argc == 5) {
|
||||
dev = simple_strtoul(argv[2], NULL, 10);
|
||||
bootsize = simple_strtoul(argv[3], NULL, 10);
|
||||
rpmbsize = simple_strtoul(argv[4], NULL, 10);
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
mmc = find_mmc_device(dev);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
printf("It is not a EMMC device\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (0 == mmc_boot_partition_size_change(mmc,
|
||||
bootsize, rpmbsize)) {
|
||||
printf("EMMC boot partition Size %d MB\n", bootsize);
|
||||
printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
|
||||
return 0;
|
||||
} else {
|
||||
printf("EMMC boot partition Size change Failed.\n");
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(argv[1], "rst-function") == 0) {
|
||||
/*
|
||||
* Set the RST_n_ENABLE bit of RST_n_FUNCTION
|
||||
* The only valid values are 0x0, 0x1 and 0x2 and writing
|
||||
* a value of 0x1 or 0x2 sets the value permanently.
|
||||
*/
|
||||
int dev;
|
||||
struct mmc *mmc;
|
||||
u8 enable;
|
||||
|
||||
if (argc == 4) {
|
||||
dev = simple_strtoul(argv[2], NULL, 10);
|
||||
enable = simple_strtoul(argv[3], NULL, 10);
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (enable > 2 || enable < 0) {
|
||||
puts("Invalid RST_n_ENABLE value\n");
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
mmc = find_mmc_device(dev);
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
puts("RST_n_FUNCTION only exists on eMMC\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return mmc_set_rst_n_function(mmc, enable);
|
||||
#endif /* CONFIG_SUPPORT_EMMC_BOOT */
|
||||
}
|
||||
|
||||
else if (argc == 3 && strcmp(argv[1], "setdsr") == 0) {
|
||||
struct mmc *mmc = find_mmc_device(curr_device);
|
||||
u32 val = simple_strtoul(argv[2], NULL, 16);
|
||||
int ret;
|
||||
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", curr_device);
|
||||
return 1;
|
||||
}
|
||||
ret = mmc_set_dsr(mmc, val);
|
||||
printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
|
||||
if (!ret) {
|
||||
mmc->has_init = 0;
|
||||
if (mmc_init(mmc))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
state = MMC_INVALID;
|
||||
if (argc == 5 && strcmp(argv[1], "read") == 0)
|
||||
state = MMC_READ;
|
||||
else if (argc == 5 && strcmp(argv[1], "write") == 0)
|
||||
state = MMC_WRITE;
|
||||
else if (argc == 4 && strcmp(argv[1], "erase") == 0)
|
||||
state = MMC_ERASE;
|
||||
|
||||
if (state != MMC_INVALID) {
|
||||
struct mmc *mmc = find_mmc_device(curr_device);
|
||||
int idx = 2;
|
||||
u32 blk, cnt, n;
|
||||
void *addr;
|
||||
|
||||
if (state != MMC_ERASE) {
|
||||
addr = (void *)simple_strtoul(argv[idx], NULL, 16);
|
||||
++idx;
|
||||
} else
|
||||
addr = NULL;
|
||||
blk = simple_strtoul(argv[idx], NULL, 16);
|
||||
cnt = simple_strtoul(argv[idx + 1], NULL, 16);
|
||||
|
||||
if (!mmc) {
|
||||
printf("no mmc device at slot %x\n", curr_device);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\nMMC %s: dev # %d, block # %d, count %d ... ",
|
||||
argv[1], curr_device, blk, cnt);
|
||||
|
||||
mmc_init(mmc);
|
||||
|
||||
if ((state == MMC_WRITE || state == MMC_ERASE)) {
|
||||
if (mmc_getwp(mmc) == 1) {
|
||||
printf("Error: card is write protected!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case MMC_READ:
|
||||
n = mmc->block_dev.block_read(curr_device, blk,
|
||||
cnt, addr);
|
||||
/* flush cache after read */
|
||||
flush_cache((ulong)addr, cnt * 512); /* FIXME */
|
||||
break;
|
||||
case MMC_WRITE:
|
||||
n = mmc->block_dev.block_write(curr_device, blk,
|
||||
cnt, addr);
|
||||
break;
|
||||
case MMC_ERASE:
|
||||
n = mmc->block_dev.block_erase(curr_device, blk, cnt);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
printf("%d blocks %s: %s\n",
|
||||
n, argv[1], (n == cnt) ? "OK" : "ERROR");
|
||||
return (n == cnt) ? 0 : 1;
|
||||
}
|
||||
|
||||
return CMD_RET_USAGE;
|
||||
return cp->cmd(cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
mmc, 6, 1, do_mmcops,
|
||||
mmc, 7, 1, do_mmcops,
|
||||
"MMC sub system",
|
||||
"read addr blk# cnt\n"
|
||||
"info - display info of the current MMC device\n"
|
||||
"mmc read addr blk# cnt\n"
|
||||
"mmc write addr blk# cnt\n"
|
||||
"mmc erase blk# cnt\n"
|
||||
"mmc rescan\n"
|
||||
@ -474,6 +665,20 @@ U_BOOT_CMD(
|
||||
" - Change the RST_n_FUNCTION field of the specified device\n"
|
||||
" WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
|
||||
#endif
|
||||
"mmc setdsr - set DSR register value\n"
|
||||
#ifdef CONFIG_SUPPORT_EMMC_RPMB
|
||||
"mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n"
|
||||
"mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n"
|
||||
"mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n"
|
||||
"mmc rpmb counter - read the value of the write counter\n"
|
||||
#endif
|
||||
"mmc setdsr <value> - set DSR register value\n"
|
||||
);
|
||||
|
||||
/* Old command kept for compatibility. Same as 'mmc info' */
|
||||
U_BOOT_CMD(
|
||||
mmcinfo, 1, 0, do_mmcinfo,
|
||||
"display MMC info",
|
||||
"- display info of the current MMC device"
|
||||
);
|
||||
|
||||
#endif /* !CONFIG_GENERIC_MMC */
|
||||
|
@ -605,22 +605,16 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
opts.spread = spread;
|
||||
|
||||
if (scrub) {
|
||||
if (!scrub_yes)
|
||||
puts(scrub_warn);
|
||||
|
||||
if (scrub_yes)
|
||||
if (scrub_yes) {
|
||||
opts.scrub = 1;
|
||||
else if (getc() == 'y') {
|
||||
puts("y");
|
||||
if (getc() == '\r')
|
||||
} else {
|
||||
puts(scrub_warn);
|
||||
if (confirm_yesno()) {
|
||||
opts.scrub = 1;
|
||||
else {
|
||||
} else {
|
||||
puts("scrub aborted\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
puts("scrub aborted\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ret = nand_erase_opts(nand, &opts);
|
||||
|
@ -158,21 +158,9 @@ int do_otp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
lowup(half + count - 1), page + (half + count - 1) / 2,
|
||||
half + count
|
||||
);
|
||||
|
||||
i = 0;
|
||||
while (1) {
|
||||
if (tstc()) {
|
||||
const char exp_ans[] = "YES\r";
|
||||
char c;
|
||||
putc(c = getc());
|
||||
if (exp_ans[i++] != c) {
|
||||
printf(" Aborting\n");
|
||||
return 1;
|
||||
} else if (!exp_ans[i]) {
|
||||
puts("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!confirm_yesno()) {
|
||||
printf(" Aborting\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ int do_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
U_BOOT_CMD(
|
||||
part, 5, 1, do_part,
|
||||
"disk partition related commands",
|
||||
"uuid <interface> <dev>:<part>\n"
|
||||
"part uuid <interface> <dev>:<part>\n"
|
||||
" - print partition UUID\n"
|
||||
"part uuid <interface> <dev>:<part> <varname>\n"
|
||||
" - set environment variable to partition UUID\n"
|
||||
|
@ -537,7 +537,33 @@ int ctrlc(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Reads user's confirmation.
|
||||
Returns 1 if user's input is "y", "Y", "yes" or "YES"
|
||||
*/
|
||||
int confirm_yesno(void)
|
||||
{
|
||||
int i;
|
||||
char str_input[5];
|
||||
|
||||
/* Flush input */
|
||||
while (tstc())
|
||||
getc();
|
||||
i = 0;
|
||||
while (i < sizeof(str_input)) {
|
||||
str_input[i] = getc();
|
||||
putc(str_input[i]);
|
||||
if (str_input[i] == '\r')
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
putc('\n');
|
||||
if (strncmp(str_input, "y\r", 2) == 0 ||
|
||||
strncmp(str_input, "Y\r", 2) == 0 ||
|
||||
strncmp(str_input, "yes\r", 4) == 0 ||
|
||||
strncmp(str_input, "YES\r", 4) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
/* pass 1 to disable ctrlc() checking, 0 to enable.
|
||||
* returns previous state
|
||||
*/
|
||||
|
78
disk/part.c
78
disk/part.c
@ -22,6 +22,7 @@
|
||||
struct block_drvr {
|
||||
char *name;
|
||||
block_dev_desc_t* (*get_dev)(int dev);
|
||||
int (*select_hwpart)(int dev_num, int hwpart);
|
||||
};
|
||||
|
||||
static const struct block_drvr block_drvr[] = {
|
||||
@ -38,7 +39,11 @@ static const struct block_drvr block_drvr[] = {
|
||||
{ .name = "usb", .get_dev = usb_stor_get_dev, },
|
||||
#endif
|
||||
#if defined(CONFIG_MMC)
|
||||
{ .name = "mmc", .get_dev = mmc_get_dev, },
|
||||
{
|
||||
.name = "mmc",
|
||||
.get_dev = mmc_get_dev,
|
||||
.select_hwpart = mmc_select_hwpart,
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_SYSTEMACE)
|
||||
{ .name = "ace", .get_dev = systemace_get_dev, },
|
||||
@ -52,11 +57,13 @@ static const struct block_drvr block_drvr[] = {
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef HAVE_BLOCK_DEVICE
|
||||
block_dev_desc_t *get_dev(const char *ifname, int dev)
|
||||
block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
|
||||
{
|
||||
const struct block_drvr *drvr = block_drvr;
|
||||
block_dev_desc_t* (*reloc_get_dev)(int dev);
|
||||
int (*select_hwpart)(int dev_num, int hwpart);
|
||||
char *name;
|
||||
int ret;
|
||||
|
||||
if (!ifname)
|
||||
return NULL;
|
||||
@ -68,17 +75,41 @@ block_dev_desc_t *get_dev(const char *ifname, int dev)
|
||||
while (drvr->name) {
|
||||
name = drvr->name;
|
||||
reloc_get_dev = drvr->get_dev;
|
||||
select_hwpart = drvr->select_hwpart;
|
||||
#ifdef CONFIG_NEEDS_MANUAL_RELOC
|
||||
name += gd->reloc_off;
|
||||
reloc_get_dev += gd->reloc_off;
|
||||
if (select_hwpart)
|
||||
select_hwpart += gd->reloc_off;
|
||||
#endif
|
||||
if (strncmp(ifname, name, strlen(name)) == 0)
|
||||
return reloc_get_dev(dev);
|
||||
if (strncmp(ifname, name, strlen(name)) == 0) {
|
||||
block_dev_desc_t *dev_desc = reloc_get_dev(dev);
|
||||
if (!dev_desc)
|
||||
return NULL;
|
||||
if (hwpart == -1)
|
||||
return dev_desc;
|
||||
if (!select_hwpart)
|
||||
return NULL;
|
||||
ret = select_hwpart(dev_desc->dev, hwpart);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
return dev_desc;
|
||||
}
|
||||
drvr++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
block_dev_desc_t *get_dev(const char *ifname, int dev)
|
||||
{
|
||||
return get_dev_hwpart(ifname, dev, -1);
|
||||
}
|
||||
#else
|
||||
block_dev_desc_t *get_dev_hwpart(const char *ifname, int dev, int hwpart)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
block_dev_desc_t *get_dev(const char *ifname, int dev)
|
||||
{
|
||||
return NULL;
|
||||
@ -413,25 +444,52 @@ int get_partition_info(block_dev_desc_t *dev_desc, int part
|
||||
return -1;
|
||||
}
|
||||
|
||||
int get_device(const char *ifname, const char *dev_str,
|
||||
int get_device(const char *ifname, const char *dev_hwpart_str,
|
||||
block_dev_desc_t **dev_desc)
|
||||
{
|
||||
char *ep;
|
||||
int dev;
|
||||
char *dup_str = NULL;
|
||||
const char *dev_str, *hwpart_str;
|
||||
int dev, hwpart;
|
||||
|
||||
hwpart_str = strchr(dev_hwpart_str, '.');
|
||||
if (hwpart_str) {
|
||||
dup_str = strdup(dev_hwpart_str);
|
||||
dup_str[hwpart_str - dev_hwpart_str] = 0;
|
||||
dev_str = dup_str;
|
||||
hwpart_str++;
|
||||
} else {
|
||||
dev_str = dev_hwpart_str;
|
||||
hwpart = -1;
|
||||
}
|
||||
|
||||
dev = simple_strtoul(dev_str, &ep, 16);
|
||||
if (*ep) {
|
||||
printf("** Bad device specification %s %s **\n",
|
||||
ifname, dev_str);
|
||||
return -1;
|
||||
dev = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*dev_desc = get_dev(ifname, dev);
|
||||
if (hwpart_str) {
|
||||
hwpart = simple_strtoul(hwpart_str, &ep, 16);
|
||||
if (*ep) {
|
||||
printf("** Bad HW partition specification %s %s **\n",
|
||||
ifname, hwpart_str);
|
||||
dev = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
*dev_desc = get_dev_hwpart(ifname, dev, hwpart);
|
||||
if (!(*dev_desc) || ((*dev_desc)->type == DEV_TYPE_UNKNOWN)) {
|
||||
printf("** Bad device %s %s **\n", ifname, dev_str);
|
||||
return -1;
|
||||
printf("** Bad device %s %s **\n", ifname, dev_hwpart_str);
|
||||
dev = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(dup_str);
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ obj-$(CONFIG_DWMMC) += dw_mmc.o
|
||||
obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
|
||||
obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
|
||||
obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
|
||||
obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
|
||||
else
|
||||
|
@ -174,7 +174,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
|
||||
int timeout;
|
||||
struct fsl_esdhc_cfg *cfg = mmc->priv;
|
||||
struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base;
|
||||
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
||||
|
||||
uint wml_value;
|
||||
|
||||
wml_value = data->blocksize/4;
|
||||
@ -184,12 +184,15 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
|
||||
wml_value = WML_RD_WML_MAX_VAL;
|
||||
|
||||
esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value);
|
||||
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
||||
esdhc_write32(®s->dsaddr, (u32)data->dest);
|
||||
#endif
|
||||
} else {
|
||||
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
||||
flush_dcache_range((ulong)data->src,
|
||||
(ulong)data->src+data->blocks
|
||||
*data->blocksize);
|
||||
|
||||
#endif
|
||||
if (wml_value > WML_WR_WML_MAX)
|
||||
wml_value = WML_WR_WML_MAX_VAL;
|
||||
if ((esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL) == 0) {
|
||||
@ -199,19 +202,10 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
|
||||
|
||||
esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK,
|
||||
wml_value << 16);
|
||||
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
||||
esdhc_write32(®s->dsaddr, (u32)data->src);
|
||||
#endif
|
||||
}
|
||||
#else /* CONFIG_SYS_FSL_ESDHC_USE_PIO */
|
||||
if (!(data->flags & MMC_DATA_READ)) {
|
||||
if ((esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL) == 0) {
|
||||
printf("\nThe SD card is locked. "
|
||||
"Can not write to a locked card.\n\n");
|
||||
return TIMEOUT;
|
||||
}
|
||||
esdhc_write32(®s->dsaddr, (u32)data->src);
|
||||
} else
|
||||
esdhc_write32(®s->dsaddr, (u32)data->dest);
|
||||
#endif /* CONFIG_SYS_FSL_ESDHC_USE_PIO */
|
||||
|
||||
esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize);
|
||||
|
||||
@ -388,9 +382,10 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
|
||||
goto out;
|
||||
}
|
||||
} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
|
||||
#endif
|
||||
|
||||
if (data->flags & MMC_DATA_READ)
|
||||
check_and_invalidate_dcache_range(cmd, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -150,6 +150,8 @@ int mmc_send_status(struct mmc *mmc, int timeout)
|
||||
#endif
|
||||
return TIMEOUT;
|
||||
}
|
||||
if (cmd.response[0] & MMC_STATUS_SWITCH_ERROR)
|
||||
return SWITCH_ERR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -501,7 +503,7 @@ static int mmc_change_freq(struct mmc *mmc)
|
||||
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
return err == SWITCH_ERR ? 0 : err;
|
||||
|
||||
/* Now check to see that it worked */
|
||||
err = mmc_send_ext_csd(mmc, ext_csd);
|
||||
@ -550,6 +552,32 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmc_select_hwpart(int dev_num, int hwpart)
|
||||
{
|
||||
struct mmc *mmc = find_mmc_device(dev_num);
|
||||
int ret;
|
||||
|
||||
if (!mmc)
|
||||
return -1;
|
||||
|
||||
if (mmc->part_num == hwpart)
|
||||
return 0;
|
||||
|
||||
if (mmc->part_config == MMCPART_NOAVAILABLE) {
|
||||
printf("Card doesn't support part_switch\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mmc_switch_part(dev_num, hwpart);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
mmc->part_num = hwpart;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mmc_switch_part(int dev_num, unsigned int part_num)
|
||||
{
|
||||
struct mmc *mmc = find_mmc_device(dev_num);
|
||||
@ -1310,10 +1338,13 @@ static int mmc_complete_init(struct mmc *mmc)
|
||||
int mmc_init(struct mmc *mmc)
|
||||
{
|
||||
int err = IN_PROGRESS;
|
||||
unsigned start = get_timer(0);
|
||||
unsigned start;
|
||||
|
||||
if (mmc->has_init)
|
||||
return 0;
|
||||
|
||||
start = get_timer(0);
|
||||
|
||||
if (!mmc->init_in_progress)
|
||||
err = mmc_start_init(mmc);
|
||||
|
||||
|
323
drivers/mmc/rpmb.c
Normal file
323
drivers/mmc/rpmb.c
Normal file
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright 2014, Staubli Faverges
|
||||
* Pierre Aubert
|
||||
*
|
||||
* eMMC- Replay Protected Memory Block
|
||||
* According to JEDEC Standard No. 84-A441
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <mmc.h>
|
||||
#include <sha256.h>
|
||||
#include "mmc_private.h"
|
||||
|
||||
/* Request codes */
|
||||
#define RPMB_REQ_KEY 1
|
||||
#define RPMB_REQ_WCOUNTER 2
|
||||
#define RPMB_REQ_WRITE_DATA 3
|
||||
#define RPMB_REQ_READ_DATA 4
|
||||
#define RPMB_REQ_STATUS 5
|
||||
|
||||
/* Response code */
|
||||
#define RPMB_RESP_KEY 0x0100
|
||||
#define RPMB_RESP_WCOUNTER 0x0200
|
||||
#define RPMB_RESP_WRITE_DATA 0x0300
|
||||
#define RPMB_RESP_READ_DATA 0x0400
|
||||
|
||||
/* Error codes */
|
||||
#define RPMB_OK 0
|
||||
#define RPMB_ERR_GENERAL 1
|
||||
#define RPMB_ERR_AUTH 2
|
||||
#define RPMB_ERR_COUNTER 3
|
||||
#define RPMB_ERR_ADDRESS 4
|
||||
#define RPMB_ERR_WRITE 5
|
||||
#define RPMB_ERR_READ 6
|
||||
#define RPMB_ERR_KEY 7
|
||||
#define RPMB_ERR_CNT_EXPIRED 0x80
|
||||
#define RPMB_ERR_MSK 0x7
|
||||
|
||||
/* Sizes of RPMB data frame */
|
||||
#define RPMB_SZ_STUFF 196
|
||||
#define RPMB_SZ_MAC 32
|
||||
#define RPMB_SZ_DATA 256
|
||||
#define RPMB_SZ_NONCE 16
|
||||
|
||||
#define SHA256_BLOCK_SIZE 64
|
||||
|
||||
/* Error messages */
|
||||
static const char * const rpmb_err_msg[] = {
|
||||
"",
|
||||
"General failure",
|
||||
"Authentication failure",
|
||||
"Counter failure",
|
||||
"Address failure",
|
||||
"Write failure",
|
||||
"Read failure",
|
||||
"Authentication key not yet programmed",
|
||||
};
|
||||
|
||||
|
||||
/* Structure of RPMB data frame. */
|
||||
struct s_rpmb {
|
||||
unsigned char stuff[RPMB_SZ_STUFF];
|
||||
unsigned char mac[RPMB_SZ_MAC];
|
||||
unsigned char data[RPMB_SZ_DATA];
|
||||
unsigned char nonce[RPMB_SZ_NONCE];
|
||||
unsigned long write_counter;
|
||||
unsigned short address;
|
||||
unsigned short block_count;
|
||||
unsigned short result;
|
||||
unsigned short request;
|
||||
};
|
||||
|
||||
static int mmc_set_blockcount(struct mmc *mmc, unsigned int blockcount,
|
||||
bool is_rel_write)
|
||||
{
|
||||
struct mmc_cmd cmd = {0};
|
||||
|
||||
cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
|
||||
cmd.cmdarg = blockcount & 0x0000FFFF;
|
||||
if (is_rel_write)
|
||||
cmd.cmdarg |= 1 << 31;
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
|
||||
return mmc_send_cmd(mmc, &cmd, NULL);
|
||||
}
|
||||
static int mmc_rpmb_request(struct mmc *mmc, const struct s_rpmb *s,
|
||||
unsigned int count, bool is_rel_write)
|
||||
{
|
||||
struct mmc_cmd cmd = {0};
|
||||
struct mmc_data data;
|
||||
int ret;
|
||||
|
||||
ret = mmc_set_blockcount(mmc, count, is_rel_write);
|
||||
if (ret) {
|
||||
#ifdef CONFIG_MMC_RPMB_TRACE
|
||||
printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
|
||||
cmd.cmdarg = 0;
|
||||
cmd.resp_type = MMC_RSP_R1b;
|
||||
|
||||
data.src = (const char *)s;
|
||||
data.blocks = 1;
|
||||
data.blocksize = MMC_MAX_BLOCK_LEN;
|
||||
data.flags = MMC_DATA_WRITE;
|
||||
|
||||
ret = mmc_send_cmd(mmc, &cmd, &data);
|
||||
if (ret) {
|
||||
#ifdef CONFIG_MMC_RPMB_TRACE
|
||||
printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int mmc_rpmb_response(struct mmc *mmc, struct s_rpmb *s,
|
||||
unsigned short expected)
|
||||
{
|
||||
struct mmc_cmd cmd = {0};
|
||||
struct mmc_data data;
|
||||
int ret;
|
||||
|
||||
ret = mmc_set_blockcount(mmc, 1, false);
|
||||
if (ret) {
|
||||
#ifdef CONFIG_MMC_RPMB_TRACE
|
||||
printf("%s:mmc_set_blockcount-> %d\n", __func__, ret);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
|
||||
cmd.cmdarg = 0;
|
||||
cmd.resp_type = MMC_RSP_R1;
|
||||
|
||||
data.dest = (char *)s;
|
||||
data.blocks = 1;
|
||||
data.blocksize = MMC_MAX_BLOCK_LEN;
|
||||
data.flags = MMC_DATA_READ;
|
||||
|
||||
ret = mmc_send_cmd(mmc, &cmd, &data);
|
||||
if (ret) {
|
||||
#ifdef CONFIG_MMC_RPMB_TRACE
|
||||
printf("%s:mmc_send_cmd-> %d\n", __func__, ret);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
/* Check the response and the status */
|
||||
if (be16_to_cpu(s->request) != expected) {
|
||||
#ifdef CONFIG_MMC_RPMB_TRACE
|
||||
printf("%s:response= %x\n", __func__,
|
||||
be16_to_cpu(s->request));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
ret = be16_to_cpu(s->result);
|
||||
if (ret) {
|
||||
printf("%s %s\n", rpmb_err_msg[ret & RPMB_ERR_MSK],
|
||||
(ret & RPMB_ERR_CNT_EXPIRED) ?
|
||||
"Write counter has expired" : "");
|
||||
}
|
||||
|
||||
/* Return the status of the command */
|
||||
return ret;
|
||||
}
|
||||
static int mmc_rpmb_status(struct mmc *mmc, unsigned short expected)
|
||||
{
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_STATUS);
|
||||
if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
|
||||
return -1;
|
||||
|
||||
/* Read the result */
|
||||
return mmc_rpmb_response(mmc, rpmb_frame, expected);
|
||||
}
|
||||
static void rpmb_hmac(unsigned char *key, unsigned char *buff, int len,
|
||||
unsigned char *output)
|
||||
{
|
||||
sha256_context ctx;
|
||||
int i;
|
||||
unsigned char k_ipad[SHA256_BLOCK_SIZE];
|
||||
unsigned char k_opad[SHA256_BLOCK_SIZE];
|
||||
|
||||
sha256_starts(&ctx);
|
||||
|
||||
/* According to RFC 4634, the HMAC transform looks like:
|
||||
SHA(K XOR opad, SHA(K XOR ipad, text))
|
||||
|
||||
where K is an n byte key.
|
||||
ipad is the byte 0x36 repeated blocksize times
|
||||
opad is the byte 0x5c repeated blocksize times
|
||||
and text is the data being protected.
|
||||
*/
|
||||
|
||||
for (i = 0; i < RPMB_SZ_MAC; i++) {
|
||||
k_ipad[i] = key[i] ^ 0x36;
|
||||
k_opad[i] = key[i] ^ 0x5c;
|
||||
}
|
||||
/* remaining pad bytes are '\0' XOR'd with ipad and opad values */
|
||||
for ( ; i < SHA256_BLOCK_SIZE; i++) {
|
||||
k_ipad[i] = 0x36;
|
||||
k_opad[i] = 0x5c;
|
||||
}
|
||||
sha256_update(&ctx, k_ipad, SHA256_BLOCK_SIZE);
|
||||
sha256_update(&ctx, buff, len);
|
||||
sha256_finish(&ctx, output);
|
||||
|
||||
/* Init context for second pass */
|
||||
sha256_starts(&ctx);
|
||||
|
||||
/* start with outer pad */
|
||||
sha256_update(&ctx, k_opad, SHA256_BLOCK_SIZE);
|
||||
|
||||
/* then results of 1st hash */
|
||||
sha256_update(&ctx, output, RPMB_SZ_MAC);
|
||||
|
||||
/* finish up 2nd pass */
|
||||
sha256_finish(&ctx, output);
|
||||
}
|
||||
int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *pcounter)
|
||||
{
|
||||
int ret;
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
|
||||
/* Fill the request */
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_WCOUNTER);
|
||||
if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
|
||||
return -1;
|
||||
|
||||
/* Read the result */
|
||||
ret = mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_WCOUNTER);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*pcounter = be32_to_cpu(rpmb_frame->write_counter);
|
||||
return 0;
|
||||
}
|
||||
int mmc_rpmb_set_key(struct mmc *mmc, void *key)
|
||||
{
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
/* Fill the request */
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_KEY);
|
||||
memcpy(rpmb_frame->mac, key, RPMB_SZ_MAC);
|
||||
|
||||
if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
|
||||
return -1;
|
||||
|
||||
/* read the operation status */
|
||||
return mmc_rpmb_status(mmc, RPMB_RESP_KEY);
|
||||
}
|
||||
int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
|
||||
unsigned short cnt, unsigned char *key)
|
||||
{
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
/* Fill the request */
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
rpmb_frame->address = cpu_to_be16(blk + i);
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_READ_DATA);
|
||||
if (mmc_rpmb_request(mmc, rpmb_frame, 1, false))
|
||||
break;
|
||||
|
||||
/* Read the result */
|
||||
if (mmc_rpmb_response(mmc, rpmb_frame, RPMB_RESP_READ_DATA))
|
||||
break;
|
||||
|
||||
/* Check the HMAC if key is provided */
|
||||
if (key) {
|
||||
unsigned char ret_hmac[RPMB_SZ_MAC];
|
||||
|
||||
rpmb_hmac(key, rpmb_frame->data, 284, ret_hmac);
|
||||
if (memcmp(ret_hmac, rpmb_frame->mac, RPMB_SZ_MAC)) {
|
||||
printf("MAC error on block #%d\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Copy data */
|
||||
memcpy(addr + i * RPMB_SZ_DATA, rpmb_frame->data, RPMB_SZ_DATA);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
|
||||
unsigned short cnt, unsigned char *key)
|
||||
{
|
||||
ALLOC_CACHE_ALIGN_BUFFER(struct s_rpmb, rpmb_frame, 1);
|
||||
unsigned long wcount;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (mmc_rpmb_get_counter(mmc, &wcount)) {
|
||||
printf("Cannot read RPMB write counter\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fill the request */
|
||||
memset(rpmb_frame, 0, sizeof(struct s_rpmb));
|
||||
memcpy(rpmb_frame->data, addr + i * RPMB_SZ_DATA, RPMB_SZ_DATA);
|
||||
rpmb_frame->address = cpu_to_be16(blk + i);
|
||||
rpmb_frame->block_count = cpu_to_be16(1);
|
||||
rpmb_frame->write_counter = cpu_to_be32(wcount);
|
||||
rpmb_frame->request = cpu_to_be16(RPMB_REQ_WRITE_DATA);
|
||||
/* Computes HMAC */
|
||||
rpmb_hmac(key, rpmb_frame->data, 284, rpmb_frame->mac);
|
||||
|
||||
if (mmc_rpmb_request(mmc, rpmb_frame, 1, true))
|
||||
break;
|
||||
|
||||
/* Get status */
|
||||
if (mmc_rpmb_status(mmc, RPMB_RESP_WRITE_DATA))
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
@ -836,7 +836,7 @@ int ctrlc (void);
|
||||
int had_ctrlc (void); /* have we had a Control-C since last clear? */
|
||||
void clear_ctrlc (void); /* clear the Control-C condition */
|
||||
int disable_ctrlc (int); /* 1 to disable, 0 to enable Control-C detect */
|
||||
|
||||
int confirm_yesno(void); /* 1 if input is "y", "Y", "yes" or "YES" */
|
||||
/*
|
||||
* STDIO based functions (can always be used)
|
||||
*/
|
||||
|
@ -109,7 +109,7 @@
|
||||
|
||||
#undef CONFIG_ENV_IS_NOWHERE
|
||||
#define CONFIG_ENV_IS_IN_MMC
|
||||
#define CONFIG_SYS_MMC_ENV_DEV 1
|
||||
#define CONFIG_SYS_MMC_ENV_DEV 0
|
||||
#define CONFIG_SYS_MMC_ENV_PART 2
|
||||
#define CONFIG_ENV_OFFSET 0x40000 /* TODO: Adresse definieren */
|
||||
#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
|
||||
|
@ -237,7 +237,7 @@
|
||||
#elif defined(CONFIG_EMMC_BOOT)
|
||||
#undef CONFIG_ENV_IS_NOWHERE
|
||||
#define CONFIG_ENV_IS_IN_MMC
|
||||
#define CONFIG_SYS_MMC_ENV_DEV 1
|
||||
#define CONFIG_SYS_MMC_ENV_DEV 0
|
||||
#define CONFIG_SYS_MMC_ENV_PART 2
|
||||
#define CONFIG_ENV_OFFSET 0x40000 /* TODO: Adresse definieren */
|
||||
#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
|
||||
|
@ -54,6 +54,7 @@
|
||||
#define COMM_ERR -18 /* Communications Error */
|
||||
#define TIMEOUT -19
|
||||
#define IN_PROGRESS -20 /* operation is in progress */
|
||||
#define SWITCH_ERR -21 /* Card reports failure to switch mode */
|
||||
|
||||
#define MMC_CMD_GO_IDLE_STATE 0
|
||||
#define MMC_CMD_SEND_OP_COND 1
|
||||
@ -70,6 +71,7 @@
|
||||
#define MMC_CMD_SET_BLOCKLEN 16
|
||||
#define MMC_CMD_READ_SINGLE_BLOCK 17
|
||||
#define MMC_CMD_READ_MULTIPLE_BLOCK 18
|
||||
#define MMC_CMD_SET_BLOCK_COUNT 23
|
||||
#define MMC_CMD_WRITE_SINGLE_BLOCK 24
|
||||
#define MMC_CMD_WRITE_MULTIPLE_BLOCK 25
|
||||
#define MMC_CMD_ERASE_GROUP_START 35
|
||||
@ -109,6 +111,7 @@
|
||||
#define SECURE_ERASE 0x80000000
|
||||
|
||||
#define MMC_STATUS_MASK (~0x0206BF7F)
|
||||
#define MMC_STATUS_SWITCH_ERROR (1 << 7)
|
||||
#define MMC_STATUS_RDY_FOR_DATA (1 << 8)
|
||||
#define MMC_STATUS_CURR_STATE (0xf << 9)
|
||||
#define MMC_STATUS_ERROR (1 << 19)
|
||||
@ -225,6 +228,7 @@
|
||||
* boot partitions (2), general purpose partitions (4) in MMC v4.4.
|
||||
*/
|
||||
#define MMC_NUM_BOOT_PARTITION 2
|
||||
#define MMC_PART_RPMB 3 /* RPMB partition number */
|
||||
|
||||
struct mmc_cid {
|
||||
unsigned long psn;
|
||||
@ -336,7 +340,13 @@ int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access);
|
||||
int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode);
|
||||
/* Function to modify the RST_n_FUNCTION field of EXT_CSD */
|
||||
int mmc_set_rst_n_function(struct mmc *mmc, u8 enable);
|
||||
|
||||
/* Functions to read / write the RPMB partition */
|
||||
int mmc_rpmb_set_key(struct mmc *mmc, void *key);
|
||||
int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *counter);
|
||||
int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
|
||||
unsigned short cnt, unsigned char *key);
|
||||
int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
|
||||
unsigned short cnt, unsigned char *key);
|
||||
/**
|
||||
* Start device initialization and return immediately; it does not block on
|
||||
* polling OCR (operation condition register) status. Then you should call
|
||||
|
@ -103,6 +103,7 @@ block_dev_desc_t* sata_get_dev(int dev);
|
||||
block_dev_desc_t* scsi_get_dev(int dev);
|
||||
block_dev_desc_t* usb_stor_get_dev(int dev);
|
||||
block_dev_desc_t* mmc_get_dev(int dev);
|
||||
int mmc_select_hwpart(int dev_num, int hwpart);
|
||||
block_dev_desc_t* systemace_get_dev(int dev);
|
||||
block_dev_desc_t* mg_disk_get_dev(int dev);
|
||||
block_dev_desc_t *host_get_dev(int dev);
|
||||
@ -126,6 +127,7 @@ static inline block_dev_desc_t* sata_get_dev(int dev) { return NULL; }
|
||||
static inline block_dev_desc_t* scsi_get_dev(int dev) { return NULL; }
|
||||
static inline block_dev_desc_t* usb_stor_get_dev(int dev) { return NULL; }
|
||||
static inline block_dev_desc_t* mmc_get_dev(int dev) { return NULL; }
|
||||
static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; }
|
||||
static inline block_dev_desc_t* systemace_get_dev(int dev) { return NULL; }
|
||||
static inline block_dev_desc_t* mg_disk_get_dev(int dev) { return NULL; }
|
||||
static inline block_dev_desc_t *host_get_dev(int dev) { return NULL; }
|
||||
|
@ -35,6 +35,7 @@ obj-y += net_utils.o
|
||||
obj-$(CONFIG_PHYSMEM) += physmem.o
|
||||
obj-y += qsort.o
|
||||
obj-$(CONFIG_SHA1) += sha1.o
|
||||
obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o
|
||||
obj-$(CONFIG_SHA256) += sha256.o
|
||||
obj-y += strmhz.o
|
||||
obj-$(CONFIG_TPM) += tpm.o
|
||||
|
Loading…
Reference in New Issue
Block a user