summaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
Diffstat (limited to 'commands')
-rw-r--r--commands/Kconfig20
-rw-r--r--commands/Makefile2
-rw-r--r--commands/mmc.c196
-rw-r--r--commands/mmc_extcsd.c6
-rw-r--r--commands/of_diff.c108
5 files changed, 328 insertions, 4 deletions
diff --git a/commands/Kconfig b/commands/Kconfig
index 298e0fb9e9..0189b4715b 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -233,6 +233,17 @@ config CMD_VERSION
barebox 2014.05.0-00142-gb289373 #177 Mon May 12 20:35:55 CEST 2014
+config CMD_MMC
+ tristate
+ prompt "mmc command allowing to set enhanced area"
+ depends on MCI
+ help
+ Configure mmc cards similar to the userspace mmc utility. Compared to
+ mmc_extcsd it works on a higher abstraction level.
+
+ Currently only the enh_area subcommand is implemented to configure
+ the "Enhanced Area" of an mmc device.
+
config CMD_MMC_EXTCSD
tristate
prompt "read/write eMMC ext. CSD register"
@@ -2012,6 +2023,13 @@ config CMD_LSMOD
help
List loaded barebox modules.
+config CMD_OF_DIFF
+ tristate
+ select OFTREE
+ prompt "of_diff"
+ help
+ Compare two device tree files against each other.
+
config CMD_OF_DUMP
tristate
select OFTREE
@@ -2156,7 +2174,7 @@ config CMD_SEED
config CMD_UBSAN
tristate "ubsan"
- depends on UBSAN && COMMAND_SUPPORT
+ depends on UBSAN
help
This is a test command for the undefined behavior sanitizer.
It triggers various undefined behavior, and detect it.
diff --git a/commands/Makefile b/commands/Makefile
index ebdc437e55..2f0980185c 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_CMD_LED_TRIGGER) += trigger.o
obj-$(CONFIG_CMD_USB) += usb.o
obj-$(CONFIG_CMD_TIME) += time.o
obj-$(CONFIG_CMD_OFTREE) += oftree.o
+obj-$(CONFIG_CMD_OF_DIFF) += of_diff.o
obj-$(CONFIG_CMD_OF_PROPERTY) += of_property.o
obj-$(CONFIG_CMD_OF_NODE) += of_node.o
obj-$(CONFIG_CMD_OF_DUMP) += of_dump.o
@@ -120,6 +121,7 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o
obj-$(CONFIG_CMD_BOOTCHOOSER) += bootchooser.o
obj-$(CONFIG_CMD_DHRYSTONE) += dhrystone.o
obj-$(CONFIG_CMD_SPD_DECODE) += spd_decode.o
+obj-$(CONFIG_CMD_MMC) += mmc.o
obj-$(CONFIG_CMD_MMC_EXTCSD) += mmc_extcsd.o
obj-$(CONFIG_CMD_NAND_BITFLIP) += nand-bitflip.o
obj-$(CONFIG_CMD_SEED) += seed.o
diff --git a/commands/mmc.c b/commands/mmc.c
new file mode 100644
index 0000000000..c696e7b881
--- /dev/null
+++ b/commands/mmc.c
@@ -0,0 +1,196 @@
+#include <command.h>
+#include <mci.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+
+static int mmc_enh_area_setmax(struct mci *mci, u8 *ext_csd)
+{
+ unsigned i;
+ struct {
+ unsigned index;
+ unsigned value;
+ } regval[] = {
+ {
+ .index = EXT_CSD_ERASE_GROUP_DEF,
+ .value = 1,
+ }, {
+ .index = EXT_CSD_ENH_START_ADDR,
+ .value = 0,
+ }, {
+ .index = EXT_CSD_ENH_START_ADDR + 1,
+ .value = 0,
+ }, {
+ .index = EXT_CSD_ENH_START_ADDR + 2,
+ .value = 0,
+ }, {
+ .index = EXT_CSD_ENH_START_ADDR + 3,
+ .value = 0,
+ }, {
+ .index = EXT_CSD_ENH_SIZE_MULT,
+ .value = ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT],
+ }, {
+ .index = EXT_CSD_ENH_SIZE_MULT + 1,
+ .value = ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT + 1],
+ }, {
+ .index = EXT_CSD_ENH_SIZE_MULT + 2,
+ .value = ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT + 2],
+ }, {
+ .index = EXT_CSD_PARTITIONS_ATTRIBUTE,
+ .value = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] | EXT_CSD_ENH_USR_MASK,
+ }
+ };
+
+ for (i = 0; i < ARRAY_SIZE(regval); ++i) {
+ int ret = mci_switch(mci, regval[i].index, regval[i].value);
+ if (ret) {
+ printf("Failure to write to register %u", regval[i].index);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int mmc_partitioning_complete(struct mci *mci)
+{
+ int ret;
+
+ ret = mci_switch(mci, EXT_CSD_PARTITION_SETTING_COMPLETED, 1);
+ if (ret)
+ printf("Failure to write to EXT_CSD_PARTITION_SETTING_COMPLETED\n");
+
+ return ret;
+}
+
+static u8 *mci_get_ext_csd(struct mci *mci)
+{
+ u8 *ext_csd;
+ int ret;
+
+ ext_csd = xmalloc(512);
+
+ ret = mci_send_ext_csd(mci, ext_csd);
+ if (ret) {
+ printf("Failure to read EXT_CSD register\n");
+ free(ext_csd);
+ return ERR_PTR(-EIO);
+ }
+
+ return ext_csd;
+}
+
+/* enh_area [-c] /dev/mmcX */
+static int do_mmc_enh_area(int argc, char *argv[])
+{
+ const char *devpath;
+ struct mci *mci;
+ u8 *ext_csd;
+ int set_completed = 0;
+ int opt;
+ int ret;
+
+ while ((opt = getopt(argc, argv, "c")) > 0) {
+ switch (opt) {
+ case 'c':
+ set_completed = 1;
+ break;
+ }
+ }
+
+ if (argc - optind != 1) {
+ printf("Usage: mmc enh_area [-c] /dev/mmcX\n");
+ return COMMAND_ERROR_USAGE;
+ }
+
+ devpath = argv[optind];
+
+ mci = mci_get_device_by_devpath(devpath);
+ if (!mci) {
+ printf("Failure to open %s as mci device\n", devpath);
+ return COMMAND_ERROR;
+ }
+
+ ext_csd = mci_get_ext_csd(mci);
+ if (IS_ERR(ext_csd))
+ return COMMAND_ERROR;
+
+ if (!(ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & EXT_CSD_ENH_ATTRIBUTE_EN_MASK)) {
+ printf("Device doesn't support enhanced area\n");
+ goto error;
+ }
+
+ if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED]) {
+ printf("Partitioning already finalized\n");
+ goto error;
+ }
+
+ ret = mmc_enh_area_setmax(mci, ext_csd);
+ if (ret)
+ goto error;
+
+ free(ext_csd);
+
+ if (set_completed) {
+ ret = mmc_partitioning_complete(mci);
+ if (ret)
+ return COMMAND_ERROR;
+ printf("Now power cycle the device to let it reconfigure itself.\n");
+ }
+
+ return COMMAND_SUCCESS;
+
+error:
+ free(ext_csd);
+ return COMMAND_ERROR;
+}
+
+static struct {
+ const char *cmd;
+ int (*func)(int argc, char *argv[]);
+} mmc_subcmds[] = {
+ {
+ .cmd = "enh_area",
+ .func = do_mmc_enh_area,
+ }
+};
+
+static int do_mmc(int argc, char *argv[])
+{
+ size_t i;
+ int (*func)(int argc, char *argv[]) = NULL;
+
+ if (argc < 2) {
+ printf("mmc: required subcommand missing\n");
+ return 1;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(mmc_subcmds); ++i) {
+ if (strcmp(mmc_subcmds[i].cmd, argv[1]) == 0) {
+ func = mmc_subcmds[i].func;
+ break;
+ }
+ }
+
+ if (func) {
+ return func(argc - 1, argv + 1);
+ } else {
+ printf("mmc: subcommand \"%s\" not found\n", argv[1]);
+ return COMMAND_ERROR_USAGE;
+ }
+}
+
+BAREBOX_CMD_HELP_START(mmc)
+BAREBOX_CMD_HELP_TEXT("Modifies mmc properties.")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("The subcommand enh_area creates an enhanced area of")
+BAREBOX_CMD_HELP_TEXT("maximal size.")
+BAREBOX_CMD_HELP_TEXT("Note, with -c this is an irreversible action.")
+BAREBOX_CMD_HELP_OPT("-c", "complete partitioning")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(mmc)
+ .cmd = do_mmc,
+ BAREBOX_CMD_OPTS("enh_area [-c] /dev/mmcX")
+ BAREBOX_CMD_HELP(cmd_mmc_help)
+BAREBOX_CMD_END
diff --git a/commands/mmc_extcsd.c b/commands/mmc_extcsd.c
index ad8e9ad19f..4f566bc805 100644
--- a/commands/mmc_extcsd.c
+++ b/commands/mmc_extcsd.c
@@ -2373,7 +2373,7 @@ static int do_mmc_extcsd(int argc, char *argv[])
u8 *dst;
int retval = 0;
int opt;
- char *devname;
+ char *devpath;
int index = 0;
int value = 0;
int write_operation = 0;
@@ -2411,9 +2411,9 @@ static int do_mmc_extcsd(int argc, char *argv[])
if (optind == argc)
return COMMAND_ERROR_USAGE;
- devname = argv[optind];
+ devpath = argv[optind];
- mci = mci_get_device_by_name(devpath_to_name(devname));
+ mci = mci_get_device_by_devpath(devpath);
if (mci == NULL) {
retval = -ENOENT;
goto error;
diff --git a/commands/of_diff.c b/commands/of_diff.c
new file mode 100644
index 0000000000..8ef006dea8
--- /dev/null
+++ b/commands/of_diff.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * of_diff.c - compare device tree files
+ *
+ * Copyright (c) 2019 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ */
+
+#include <common.h>
+#include <fs.h>
+#include <libfile.h>
+#include <of.h>
+#include <command.h>
+#include <malloc.h>
+#include <complete.h>
+#include <errno.h>
+#include <linux/err.h>
+
+static struct device_node *get_tree(const char *filename, struct device_node *root)
+{
+ struct device_node *node;
+ void *fdt;
+ size_t size;
+ int ret;
+
+ if (!strcmp(filename, "-")) {
+ node = of_get_root_node();
+ if (!node)
+ return ERR_PTR(-ENOENT);
+
+ return of_copy_node(NULL, node);
+ }
+
+ if (!strcmp(filename, "+")) {
+ node = of_get_root_node();
+ if (!node)
+ return ERR_PTR(-ENOENT);
+
+ node = of_copy_node(NULL, root);
+
+ of_fix_tree(node);
+
+ return node;
+ }
+
+ ret = read_file_2(filename, &size, &fdt, FILESIZE_MAX);
+ if (ret)
+ return ERR_PTR(ret);
+
+ node = of_unflatten_dtb(fdt);
+
+ free(fdt);
+
+ return node;
+}
+
+static int do_of_diff(int argc, char *argv[])
+{
+ int ret = 0;
+ struct device_node *a, *b, *root;
+
+ if (argc < 3)
+ return COMMAND_ERROR_USAGE;
+
+ root = of_get_root_node();
+ a = get_tree(argv[1], root);
+ b = get_tree(argv[2], root);
+
+ if (IS_ERR(a)) {
+ printf("Cannot read %s: %s\n", argv[1], strerrorp(a));
+ ret = COMMAND_ERROR;
+ a = NULL;
+ goto out;
+ }
+
+ if (IS_ERR(b)) {
+ printf("Cannot read %s: %s\n", argv[2], strerrorp(b));
+ ret = COMMAND_ERROR;
+ b = NULL;
+ goto out;
+ }
+
+ of_diff(a, b, 0);
+
+ ret = 0;
+out:
+ if (a && a != root)
+ of_delete_node(a);
+ if (b && b != root)
+ of_delete_node(b);
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(of_diff)
+BAREBOX_CMD_HELP_TEXT("This command prints a diff between two given device trees.")
+BAREBOX_CMD_HELP_TEXT("The device trees are given as dtb files or:")
+BAREBOX_CMD_HELP_TEXT("'-' to compare against the barebox live tree, or")
+BAREBOX_CMD_HELP_TEXT("'+' to compare against the fixed barebox live tree")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(of_diff)
+ .cmd = do_of_diff,
+ BAREBOX_CMD_DESC("diff device trees")
+ BAREBOX_CMD_OPTS("<a> <b>")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_HELP(cmd_of_diff_help)
+BAREBOX_CMD_END