summaryrefslogtreecommitdiffstats
path: root/arch/sandbox
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sandbox')
-rw-r--r--arch/sandbox/Kconfig42
-rw-r--r--arch/sandbox/Makefile18
-rw-r--r--arch/sandbox/board/.gitignore2
-rw-r--r--arch/sandbox/board/Makefile8
-rw-r--r--arch/sandbox/board/barebox.lds.S4
-rw-r--r--arch/sandbox/board/board.c22
-rw-r--r--arch/sandbox/board/clock.c1
-rw-r--r--arch/sandbox/board/console.c4
-rw-r--r--arch/sandbox/board/dev-random.c2
-rw-r--r--arch/sandbox/board/devices.c11
-rw-r--r--arch/sandbox/board/dtb.c30
-rw-r--r--arch/sandbox/board/env/nv/autoboot1
-rw-r--r--arch/sandbox/board/hostfile.c165
-rw-r--r--arch/sandbox/board/led.c68
-rw-r--r--arch/sandbox/board/power.c99
-rw-r--r--arch/sandbox/board/poweroff.c42
-rw-r--r--arch/sandbox/board/stickypage.S29
-rw-r--r--arch/sandbox/board/watchdog.c77
-rw-r--r--arch/sandbox/configs/hosttools_defconfig2
-rw-r--r--arch/sandbox/configs/sandbox_defconfig53
-rw-r--r--arch/sandbox/configs/targettools_defconfig10
-rw-r--r--arch/sandbox/dts/.gitignore1
-rw-r--r--arch/sandbox/dts/Makefile8
-rw-r--r--arch/sandbox/dts/sandbox-state-example.dtsi50
-rw-r--r--arch/sandbox/dts/sandbox.dts123
-rw-r--r--arch/sandbox/dts/skeleton.dtsi13
-rw-r--r--arch/sandbox/include/asm/barebox.lds.h3
-rw-r--r--arch/sandbox/include/asm/bitsperlong.h2
-rw-r--r--arch/sandbox/include/asm/byteorder.h2
-rw-r--r--arch/sandbox/include/asm/common.h4
-rw-r--r--arch/sandbox/include/asm/debug_ll.h16
-rw-r--r--arch/sandbox/include/asm/dma.h30
-rw-r--r--arch/sandbox/include/asm/elf.h2
-rw-r--r--arch/sandbox/include/asm/io.h19
-rw-r--r--arch/sandbox/include/asm/linkage.h8
-rw-r--r--arch/sandbox/include/asm/mmu.h2
-rw-r--r--arch/sandbox/include/asm/posix_types.h2
-rw-r--r--arch/sandbox/include/asm/reset_source.h16
-rw-r--r--arch/sandbox/include/asm/sections.h2
-rw-r--r--arch/sandbox/include/asm/setjmp.h17
-rw-r--r--arch/sandbox/include/asm/string.h2
-rw-r--r--arch/sandbox/include/asm/swab.h2
-rw-r--r--arch/sandbox/include/asm/types.h2
-rw-r--r--arch/sandbox/include/asm/unaligned.h2
-rw-r--r--arch/sandbox/include/asm/word-at-a-time.h2
-rw-r--r--arch/sandbox/lib/Makefile2
-rw-r--r--arch/sandbox/lib/asm-offsets.c2
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/hostfile.h4
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/linux.h36
-rw-r--r--arch/sandbox/os/Makefile13
-rw-r--r--arch/sandbox/os/common.c191
-rw-r--r--arch/sandbox/os/libc_malloc.c28
-rw-r--r--arch/sandbox/os/sdl.c184
-rw-r--r--arch/sandbox/os/setjmp.c180
54 files changed, 1282 insertions, 378 deletions
diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index bced81f25e..3419b6e4f6 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
source "scripts/Kconfig.include"
config SANDBOX
@@ -9,30 +11,21 @@ config SANDBOX
select HAS_DMA
select BLOCK
select BLOCK_WRITE
+ select PARTITION
select PARTITION_DISK
+ select ARCH_HAS_STACK_DUMP if ASAN
+ select GENERIC_FIND_NEXT_BIT
+ select ARCH_HAS_SJLJ
+ select ARCH_HAS_CTRLC
+ select HAS_DEBUG_LL
+ select ARCH_DMA_DEFAULT_COHERENT
default y
config ARCH_TEXT_BASE
hex
default 0x00000000
-config LINUX
- bool
- default y
- select GENERIC_FIND_NEXT_BIT
-
-config SANDBOX_UNWIND
- bool
- default y
- select ARCH_HAS_STACK_DUMP
- depends on UBSAN || ASAN
-
-config SANDBOX_REEXEC
- prompt "exec(2) reset handler"
- def_bool y
- help
- The normal reset handler hangs barebox. On Linux, barebox
- instead can exec itself to simulate a reset.
+menu "Sandbox specific settings"
config PHYS_ADDR_T_64BIT
bool
@@ -50,5 +43,20 @@ config 64BIT
select ARCH_DMA_ADDR_T_64BIT
select PHYS_ADDR_T_64BIT
+config 32BIT
+ def_bool !64BIT
+
config SANDBOX_LINUX_I386
bool "32-bit x86 barebox" if CC_HAS_LINUX_I386_SUPPORT
+
+config SANDBOX_REEXEC
+ prompt "exec(2) reset handler"
+ def_bool y
+ help
+ The normal reset handler hangs barebox. On Linux, barebox
+ instead can exec itself to simulate a reset.
+
+config SDL
+ bool
+
+endmenu
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index 09112c3ba8..c2906c0b1c 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
KBUILD_DEFCONFIG := sandbox_defconfig
KBUILD_CPPFLAGS += -D__SANDBOX__ -fno-strict-aliasing -fvisibility=hidden
@@ -24,9 +26,13 @@ KBUILD_CFLAGS += -Dmalloc=barebox_malloc -Dcalloc=barebox_calloc \
-Dgetenv=barebox_getenv -Dprintf=barebox_printf \
-Dglob=barebox_glob -Dglobfree=barebox_globfree \
-Dioctl=barebox_ioctl -Dfstat=barebox_fstat \
+ -Dftruncate=barebox_ftruncate -Dasprintf=barebox_asprintf \
-Dopendir=barebox_opendir -Dreaddir=barebox_readdir \
-Dclosedir=barebox_closedir -Dreadlink=barebox_readlink \
- -Doptarg=barebox_optarg -Doptind=barebox_optind
+ -Doptarg=barebox_optarg -Doptind=barebox_optind \
+ -Dsetjmp=barebox_setjmp -Dlongjmp=barebox_longjmp \
+ -Dmkdir=barebox_mkdir -Ddirname=barebox_dirname \
+ -Dremove=barebox_remove -Dputchar=barebox_putchar
machdirs := $(patsubst %,arch/sandbox/mach-%/,$(machine-y))
@@ -36,12 +42,12 @@ archprepare: maketools
PHONY += maketools
-ifeq ($(CONFIG_DRIVER_VIDEO_SDL),y)
-SDL_LIBS := $(shell pkg-config sdl --libs)
+ifeq ($(CONFIG_SDL),y)
+SDL_LIBS := $(shell $(PKG_CONFIG) sdl2 --libs)
endif
ifeq ($(CONFIG_GPIO_LIBFTDI1),y)
-FTDI1_LIBS := $(shell pkg-config libftdi1 --libs)
+FTDI1_LIBS := $(shell $(PKG_CONFIG) libftdi1 --libs)
endif
ifeq ($(CONFIG_ASAN),y)
@@ -63,13 +69,15 @@ endif
BAREBOX_LDFLAGS += \
-Wl,-T,$(BAREBOX_LDS) \
-Wl,--whole-archive $(BAREBOX_OBJS) -Wl,--no-whole-archive \
- -lrt -lpthread $(SDL_LIBS) $(FTDI1_LIBS) \
+ -lrt -pthread $(SDL_LIBS) $(FTDI1_LIBS) \
$(SANITIZER_LIBS)
cmd_barebox__ = $(CC) -o $@ $(BAREBOX_LDFLAGS)
common-y += $(BOARD) arch/sandbox/os/ arch/sandbox/lib/
+KBUILD_IMAGE := barebox
+
common-$(CONFIG_OFTREE) += arch/sandbox/dts/
CLEAN_FILES += $(BOARD)/barebox.lds
diff --git a/arch/sandbox/board/.gitignore b/arch/sandbox/board/.gitignore
index d1165788c9..03987a7009 100644
--- a/arch/sandbox/board/.gitignore
+++ b/arch/sandbox/board/.gitignore
@@ -1 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
barebox.lds
diff --git a/arch/sandbox/board/Makefile b/arch/sandbox/board/Makefile
index 26f6cb1922..b4bab02163 100644
--- a/arch/sandbox/board/Makefile
+++ b/arch/sandbox/board/Makefile
@@ -1,10 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-y += board.o
obj-y += clock.o
obj-y += hostfile.o
obj-y += console.o
obj-y += devices.o
obj-y += dtb.o
-obj-y += poweroff.o
+obj-y += power.o
obj-y += dev-random.o
+obj-y += watchdog.o
+obj-$(CONFIG_LED) += led.o
extra-y += barebox.lds
+
+obj-y += stickypage.o
diff --git a/arch/sandbox/board/barebox.lds.S b/arch/sandbox/board/barebox.lds.S
index 7a5a8eb1e7..ab2801f3d2 100644
--- a/arch/sandbox/board/barebox.lds.S
+++ b/arch/sandbox/board/barebox.lds.S
@@ -1,4 +1,6 @@
-#include <asm-generic/barebox.lds.h>
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <asm/barebox.lds.h>
SECTIONS
{
diff --git a/arch/sandbox/board/board.c b/arch/sandbox/board/board.c
index 45b7c7deff..c8d1c99897 100644
--- a/arch/sandbox/board/board.c
+++ b/arch/sandbox/board/board.c
@@ -20,6 +20,7 @@
#include <mach/linux.h>
#include <init.h>
#include <errno.h>
+#include <deep-probe.h>
#include <fb.h>
struct fb_videomode mode = {
@@ -28,23 +29,23 @@ struct fb_videomode mode = {
.yres = 480,
};
-static struct device_d tap_device = {
+static struct device tap_device = {
.id = DEVICE_ID_DYNAMIC,
.name = "tap",
};
-static struct device_d sdl_device = {
+static struct device sdl_device = {
.id = DEVICE_ID_DYNAMIC,
.name = "sdlfb",
.platform_data = &mode,
};
-static struct device_d devrandom_device = {
+static struct device devrandom_device = {
.id = DEVICE_ID_DYNAMIC,
.name = "devrandom",
};
-static int devices_init(void)
+static int devices_init(struct device *dev)
{
platform_device_register(&tap_device);
@@ -61,4 +62,15 @@ static int devices_init(void)
return 0;
}
-device_initcall(devices_init);
+static struct of_device_id sandbox_dt_ids[] = {
+ { .compatible = "barebox,sandbox" },
+ { /* sentinel */ }
+};
+BAREBOX_DEEP_PROBE_ENABLE(sandbox_dt_ids);
+
+static struct driver sandbox_board_drv = {
+ .name = "sandbox-board",
+ .of_compatible = sandbox_dt_ids,
+ .probe = devices_init,
+};
+device_platform_driver(sandbox_board_drv);
diff --git a/arch/sandbox/board/clock.c b/arch/sandbox/board/clock.c
index b005e71633..1787fb5786 100644
--- a/arch/sandbox/board/clock.c
+++ b/arch/sandbox/board/clock.c
@@ -28,6 +28,7 @@ static struct clocksource cs = {
.read = linux_clocksource_read,
.mask = CLOCKSOURCE_MASK(32),
.shift = 10,
+ .priority = 80,
};
static int clocksource_init (void)
diff --git a/arch/sandbox/board/console.c b/arch/sandbox/board/console.c
index cea62d57b1..274ef67aef 100644
--- a/arch/sandbox/board/console.c
+++ b/arch/sandbox/board/console.c
@@ -21,10 +21,10 @@
int barebox_register_console(int stdinfd, int stdoutfd)
{
- struct device_d *dev;
+ struct device *dev;
struct linux_console_data *data;
- dev = xzalloc(sizeof(struct device_d) + sizeof(struct linux_console_data));
+ dev = xzalloc(sizeof(struct device) + sizeof(struct linux_console_data));
data = (struct linux_console_data *)(dev + 1);
diff --git a/arch/sandbox/board/dev-random.c b/arch/sandbox/board/dev-random.c
index 60295e9fce..b62e8cc0d7 100644
--- a/arch/sandbox/board/dev-random.c
+++ b/arch/sandbox/board/dev-random.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <mach/linux.h>
diff --git a/arch/sandbox/board/devices.c b/arch/sandbox/board/devices.c
index 72e62552a3..ecd24e9207 100644
--- a/arch/sandbox/board/devices.c
+++ b/arch/sandbox/board/devices.c
@@ -6,13 +6,15 @@
#include <common.h>
#include <driver.h>
-#include <mach/linux.h>
#include <init.h>
#include <mach/linux.h>
+#include <asm/io.h>
+
+unsigned char __pci_iobase[IO_SPACE_LIMIT];
static LIST_HEAD(sandbox_device_list);
-int sandbox_add_device(struct device_d *dev)
+int sandbox_add_device(struct device *dev)
{
list_add(&dev->list, &sandbox_device_list);
@@ -21,10 +23,7 @@ int sandbox_add_device(struct device_d *dev)
static int sandbox_device_init(void)
{
- struct device_d *dev, *tmp;
-
- barebox_set_model("barebox sandbox");
- barebox_set_hostname("barebox");
+ struct device *dev, *tmp;
list_for_each_entry_safe(dev, tmp, &sandbox_device_list, list) {
/* reset the list_head before registering for real */
diff --git a/arch/sandbox/board/dtb.c b/arch/sandbox/board/dtb.c
index d11bde0249..98d2e774b8 100644
--- a/arch/sandbox/board/dtb.c
+++ b/arch/sandbox/board/dtb.c
@@ -32,33 +32,13 @@ int barebox_register_dtb(const void *new_dtb)
return 0;
}
+extern char __dtb_sandbox_start[];
+
static int of_sandbox_init(void)
{
- struct device_node *root;
- int ret;
-
- if (dtb) {
- root = of_unflatten_dtb(dtb);
- } else {
- root = of_new_node(NULL, NULL);
-
- ret = of_property_write_u32(root, "#address-cells", 2);
- if (ret)
- return ret;
-
- ret = of_property_write_u32(root, "#size-cells", 2);
- if (ret)
- return ret;
- }
+ if (!dtb)
+ dtb = __dtb_sandbox_start;
- if (IS_ERR(root))
- return PTR_ERR(root);
-
- of_set_root_node(root);
- of_fix_tree(root);
- if (IS_ENABLED(CONFIG_OFDEVICE))
- of_probe();
-
- return 0;
+ return barebox_register_fdt(dtb);
}
core_initcall(of_sandbox_init);
diff --git a/arch/sandbox/board/env/nv/autoboot b/arch/sandbox/board/env/nv/autoboot
new file mode 100644
index 0000000000..f7d13fd046
--- /dev/null
+++ b/arch/sandbox/board/env/nv/autoboot
@@ -0,0 +1 @@
+abort
diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c
index 63530bd25e..7afad95b6d 100644
--- a/arch/sandbox/board/hostfile.c
+++ b/arch/sandbox/board/hostfile.c
@@ -24,10 +24,9 @@
#include <errno.h>
#include <linux/err.h>
#include <mach/hostfile.h>
+#include <featctrl.h>
#include <xfuncs.h>
-#include <linux/err.h>
-
struct hf_priv {
union {
struct block_device blk;
@@ -35,6 +34,7 @@ struct hf_priv {
};
const char *filename;
int fd;
+ struct feature_controller feat;
};
static ssize_t hf_read(struct hf_priv *priv, void *buf, size_t count, loff_t offset, ulong flags)
@@ -72,14 +72,14 @@ static struct cdev_operations hf_cdev_ops = {
.write = hf_cdev_write,
};
-static int hf_blk_read(struct block_device *blk, void *buf, int block, int num_blocks)
+static int hf_blk_read(struct block_device *blk, void *buf, sector_t block, blkcnt_t num_blocks)
{
ssize_t ret = hf_read(container_of(blk, struct hf_priv, blk), buf,
num_blocks << SECTOR_SHIFT, block << SECTOR_SHIFT, 0);
return ret > 0 ? 0 : ret;
}
-static int hf_blk_write(struct block_device *blk, const void *buf, int block, int num_blocks)
+static int hf_blk_write(struct block_device *blk, const void *buf, sector_t block, blkcnt_t num_blocks)
{
ssize_t ret = hf_write(container_of(blk, struct hf_priv, blk), buf,
num_blocks << SECTOR_SHIFT, block << SECTOR_SHIFT, 0);
@@ -91,32 +91,52 @@ static struct block_device_ops hf_blk_ops = {
.write = hf_blk_write,
};
-static void hf_info(struct device_d *dev)
+static void hf_info(struct device *dev)
{
struct hf_priv *priv = dev->priv;
printf("file: %s\n", priv->filename);
}
-static int hf_probe(struct device_d *dev)
+static int hostfile_feat_check(struct feature_controller *feat, int idx)
+{
+ struct hf_priv *priv = container_of(feat, struct hf_priv, feat);
+
+ return priv->fd >= 0 ? FEATCTRL_OKAY : FEATCTRL_GATED;
+}
+
+static int hf_probe(struct device *dev)
{
- struct device_node *np = dev->device_node;
+ struct device_node *np = dev->of_node;
struct hf_priv *priv = xzalloc(sizeof(*priv));
- struct resource *res;
struct cdev *cdev;
- bool is_blockdev;
- resource_size_t size;
+ bool is_featctrl = false, is_blockdev;
+ u64 reg[2];
int err;
- res = dev_get_resource(dev, IORESOURCE_MEM, 0);
- if (IS_ERR(res))
- return PTR_ERR(res);
-
- size = resource_size(res);
-
if (!np)
return -ENODEV;
+ dev->priv = priv;
+ priv->fd = -1;
+
+ if (IS_ENABLED(CONFIG_FEATURE_CONTROLLER) &&
+ of_property_read_bool(np, "barebox,feature-controller")) {
+ priv->feat.dev = dev;
+ priv->feat.check = hostfile_feat_check;
+
+ err = feature_controller_register(&priv->feat);
+ if (err)
+ return err;
+
+ is_featctrl = true;
+ }
+
+
+ err = of_property_read_u64_array(np, "reg", reg, ARRAY_SIZE(reg));
+ if (err)
+ return err;
+
of_property_read_u32(np, "barebox,fd", &priv->fd);
err = of_property_read_string(np, "barebox,filename",
@@ -124,42 +144,35 @@ static int hf_probe(struct device_d *dev)
if (err)
return err;
- if (!priv->fd)
- priv->fd = linux_open(priv->filename, true);
-
if (priv->fd < 0)
- return priv->fd;
+ return is_featctrl ? 0 : priv->fd;
dev->info = hf_info;
- dev->priv = priv;
is_blockdev = of_property_read_bool(np, "barebox,blockdev");
cdev = is_blockdev ? &priv->blk.cdev : &priv->cdev;
- cdev->device_node = np;
+ cdev_set_of_node(cdev, np);
if (is_blockdev) {
cdev->name = np->name;
priv->blk.dev = dev;
priv->blk.ops = &hf_blk_ops;
priv->blk.blockbits = SECTOR_SHIFT;
- priv->blk.num_blocks = size / SECTOR_SIZE;
+ priv->blk.num_blocks = reg[1] / SECTOR_SIZE;
+ priv->blk.type = BLK_TYPE_VIRTUAL;
err = blockdevice_register(&priv->blk);
if (err)
return err;
- err = parse_partition_table(&priv->blk);
- if (err)
- dev_warn(dev, "No partition table found\n");
-
dev_info(dev, "registered as block device\n");
} else {
cdev->name = np->name;
cdev->dev = dev;
cdev->ops = &hf_cdev_ops;
- cdev->size = size;
+ cdev->size = reg[1];
cdev->priv = priv;
err = devfs_create(cdev);
@@ -172,7 +185,7 @@ static int hf_probe(struct device_d *dev)
of_parse_partitions(cdev, np);
of_partitions_register_fixup(cdev);
- return 0;
+ return of_platform_populate(np, NULL, dev);
}
static __maybe_unused struct of_device_id hostfile_dt_ids[] = {
@@ -182,8 +195,9 @@ static __maybe_unused struct of_device_id hostfile_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, hostfile_dt_ids);
-static struct driver_d hf_drv = {
+static struct driver hf_drv = {
.name = "hostfile",
.of_compatible = DRV_OF_COMPAT(hostfile_dt_ids),
.probe = hf_probe,
@@ -194,37 +208,98 @@ static int of_hostfile_fixup(struct device_node *root, void *ctx)
{
struct hf_info *hf = ctx;
struct device_node *node;
- uint32_t reg[] = {
- hf->base >> 32,
- hf->base,
- hf->size >> 32,
- hf->size
- };
+ bool name_only = false;
int ret;
- node = of_new_node(root, hf->devname);
+ node = of_get_child_by_name(root, hf->devname);
+ if (node)
+ name_only = true;
+ else
+ node = of_new_node(root, hf->devname);
- ret = of_property_write_string(node, "compatible", hostfile_dt_ids->compatible);
+ ret = of_property_write_string(node, "barebox,filename", hf->filename);
if (ret)
return ret;
- ret = of_property_write_u32_array(node, "reg", reg, ARRAY_SIZE(reg));
+ if (name_only)
+ return 0;
+
+ ret = of_property_write_string(node, "compatible", hostfile_dt_ids->compatible);
if (ret)
return ret;
- ret = of_property_write_u32(node, "barebox,fd", hf->fd);
+ ret = of_property_write_bool(node, "barebox,blockdev", hf->is_blockdev);
if (ret)
return ret;
- ret = of_property_write_string(node, "barebox,filename", hf->filename);
-
- if (hf->is_blockdev)
- ret = of_property_write_bool(node, "barebox,blockdev", true);
+ ret = of_property_write_bool(node, "barebox,cdev", hf->is_cdev);
+ if (ret)
+ return ret;
- return ret;
+ return of_property_write_bool(node, "barebox,read-only", hf->is_readonly);
}
int barebox_register_filedev(struct hf_info *hf)
{
return of_register_fixup(of_hostfile_fixup, hf);
}
+
+static int of_hostfile_map_fixup(struct device_node *root, void *ctx)
+{
+ struct device_node *node;
+ int ret;
+
+ for_each_compatible_node_from(node, root, NULL, "barebox,stickypage") {
+ char *filename;
+
+ filename = linux_get_stickypage_path();
+ if (!filename) {
+ pr_err("error allocating stickypage\n");
+ continue;
+ }
+
+ of_property_write_string(node, "barebox,filename", filename);
+ of_property_write_string(node, "compatible", "barebox,hostfile");
+ }
+
+ for_each_compatible_node_from(node, root, NULL, "barebox,hostfile") {
+ struct hf_info hf = {};
+ uint64_t reg[2] = {};
+
+ hf.devname = node->name;
+
+ ret = of_property_read_string(node, "barebox,filename", &hf.filename);
+ if (ret) {
+ pr_err("skipping nameless hostfile %s\n", hf.devname);
+ continue;
+ }
+
+ hf.is_blockdev = of_property_read_bool(node, "barebox,blockdev");
+ hf.is_cdev = of_property_read_bool(node, "barebox,cdev");
+ hf.is_readonly = of_property_read_bool(node, "barebox,read-only");
+
+ of_property_read_u64_array(node, "reg", reg, ARRAY_SIZE(reg));
+
+ hf.base = reg[0];
+ hf.size = reg[1];
+
+ ret = linux_open_hostfile(&hf);
+ if (ret)
+ continue;
+
+ reg[0] = hf.base;
+ reg[1] = hf.size;
+
+ of_property_write_u64_array(node, "reg", reg, ARRAY_SIZE(reg));
+ of_property_write_bool(node, "barebox,blockdev", hf.is_blockdev);
+ of_property_write_u32(node, "barebox,fd", hf.fd);
+ }
+
+ return 0;
+}
+
+static int barebox_fixup_filedevs(void)
+{
+ return of_register_fixup(of_hostfile_map_fixup, NULL);
+}
+pure_initcall(barebox_fixup_filedevs);
diff --git a/arch/sandbox/board/led.c b/arch/sandbox/board/led.c
new file mode 100644
index 0000000000..ced7e82f99
--- /dev/null
+++ b/arch/sandbox/board/led.c
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <common.h>
+#include <init.h>
+#include <led.h>
+#include <mach/linux.h>
+#include <of.h>
+
+static struct sandbox_led {
+ struct led led;
+ bool active;
+} sandbox_led;
+
+static inline void terminal_puts(const char *s)
+{
+ linux_write(1, s, strlen(s));
+}
+
+static void sandbox_led_set(struct led *led, unsigned int brightness)
+{
+ terminal_puts("\x1b]2;barebox ");
+ while (brightness--)
+ terminal_puts(".");
+ terminal_puts("\a");
+
+ sandbox_led.active = true;
+}
+
+static int sandbox_led_of_probe(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ int ret;
+
+ if (sandbox_led.led.set)
+ return -EBUSY;
+
+ sandbox_led.led.name = xstrdup(np->name);
+ sandbox_led.led.max_value = 5;
+ sandbox_led.led.set = sandbox_led_set;
+
+ ret = led_register(&sandbox_led.led);
+ if (ret)
+ return ret;
+
+ led_of_parse_trigger(&sandbox_led.led, np);
+
+ return 0;
+}
+
+static void sandbox_led_of_remove(struct device *dev)
+{
+ if (sandbox_led.active)
+ sandbox_led_set(NULL, 0);
+}
+
+static struct of_device_id sandbox_led_of_ids[] = {
+ { .compatible = "barebox,sandbox-led", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sandbox_led_of_ids);
+
+static struct driver sandbox_led_of_driver = {
+ .name = "sandbox-led",
+ .probe = sandbox_led_of_probe,
+ .remove = sandbox_led_of_remove,
+ .of_compatible = sandbox_led_of_ids,
+};
+device_platform_driver(sandbox_led_of_driver);
diff --git a/arch/sandbox/board/power.c b/arch/sandbox/board/power.c
new file mode 100644
index 0000000000..8300c589c7
--- /dev/null
+++ b/arch/sandbox/board/power.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <driver.h>
+#include <poweroff.h>
+#include <restart.h>
+#include <mach/linux.h>
+#include <asm/reset_source.h>
+#include <linux/nvmem-consumer.h>
+
+struct sandbox_power {
+ struct restart_handler rst_hang, rst_reexec;
+ struct poweroff_handler poweroff;
+ struct nvmem_cell *reset_source_cell;
+};
+
+static void sandbox_poweroff(struct poweroff_handler *poweroff)
+{
+ struct sandbox_power *power = container_of(poweroff, struct sandbox_power, poweroff);
+
+ sandbox_save_reset_source(power->reset_source_cell, RESET_POR);
+
+ linux_exit();
+}
+
+static void sandbox_rst_hang(struct restart_handler *rst)
+{
+ linux_hang();
+}
+
+static void sandbox_rst_reexec(struct restart_handler *rst)
+{
+ struct sandbox_power *power = container_of(rst, struct sandbox_power, rst_reexec);
+
+ sandbox_save_reset_source(power->reset_source_cell, RESET_RST);
+
+ linux_reexec();
+}
+
+static int sandbox_power_probe(struct device *dev)
+{
+ struct sandbox_power *power = xzalloc(sizeof(*power));
+ size_t len;
+ u8 *rst;
+
+ power->poweroff = (struct poweroff_handler) {
+ .name = "exit",
+ .poweroff = sandbox_poweroff
+ };
+
+ poweroff_handler_register(&power->poweroff);
+
+ power->rst_hang = (struct restart_handler) {
+ .name = "hang",
+ .restart = sandbox_rst_hang
+ };
+
+ power->rst_reexec = (struct restart_handler) {
+ .name = "reexec", .priority = 200,
+ .restart = sandbox_rst_reexec,
+ };
+
+ restart_handler_register(&power->rst_hang);
+
+ if (IS_ENABLED(CONFIG_SANDBOX_REEXEC))
+ restart_handler_register(&power->rst_reexec);
+
+ power->reset_source_cell = of_nvmem_cell_get(dev->of_node,
+ "reset-source");
+ if (IS_ERR(power->reset_source_cell)) {
+ if (PTR_ERR(power->reset_source_cell) != -EPROBE_DEFER)
+ dev_warn(dev, "No reset source info available: %pe\n",
+ power->reset_source_cell);
+ power->reset_source_cell = NULL;
+ return 0;
+ }
+
+ rst = nvmem_cell_read(power->reset_source_cell, &len);
+ if (!IS_ERR(rst)) {
+ reset_source_set_prinst(*rst, RESET_SOURCE_DEFAULT_PRIORITY, 0);
+
+ free(rst);
+ }
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id sandbox_power_dt_ids[] = {
+ { .compatible = "barebox,sandbox-power" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sandbox_power_dt_ids);
+
+static struct driver sandbox_power_drv = {
+ .name = "sandbox-power",
+ .of_compatible = sandbox_power_dt_ids,
+ .probe = sandbox_power_probe,
+};
+coredevice_platform_driver(sandbox_power_drv);
diff --git a/arch/sandbox/board/poweroff.c b/arch/sandbox/board/poweroff.c
deleted file mode 100644
index 8ce739af72..0000000000
--- a/arch/sandbox/board/poweroff.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include <common.h>
-#include <init.h>
-#include <poweroff.h>
-#include <restart.h>
-#include <mach/linux.h>
-
-static void sandbox_poweroff(struct poweroff_handler *poweroff)
-{
- linux_exit();
-}
-
-static void sandbox_rst_hang(struct restart_handler *rst)
-{
- linux_hang();
-}
-
-static struct restart_handler rst_hang = {
- .name = "hang",
- .restart = sandbox_rst_hang
-};
-
-static void sandbox_rst_reexec(struct restart_handler *rst)
-{
- linux_reexec();
-}
-
-static struct restart_handler rst_reexec = {
- .name = "reexec", .priority = 200,
- .restart = sandbox_rst_reexec,
-};
-
-static int poweroff_register_feature(void)
-{
- poweroff_handler_register_fn(sandbox_poweroff);
- restart_handler_register(&rst_hang);
-
- if (IS_ENABLED(CONFIG_SANDBOX_REEXEC))
- restart_handler_register(&rst_reexec);
-
- return 0;
-}
-coredevice_initcall(poweroff_register_feature);
diff --git a/arch/sandbox/board/stickypage.S b/arch/sandbox/board/stickypage.S
new file mode 100644
index 0000000000..1d3861c373
--- /dev/null
+++ b/arch/sandbox/board/stickypage.S
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+.section .note.GNU-stack,"",%progbits
+.section .rodata.stickypage,"a"
+
+.globl stickypage;
+stickypage:
+
+/* nvmem */ .org 0x300
+.byte 0x01
+
+/* env */ .org 0x400
+.byte 0x79, 0xba, 0x8f, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.byte 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x69, 0x9c, 0x7f, 0x00, 0x00, 0x00, 0x00
+
+/* state */ .org 0xC00
+.byte 0xf3, 0xfd, 0x54, 0x23, 0x18, 0x00, 0x00, 0x00, 0xa6, 0x86, 0x3b, 0xaa, 0x00, 0x00, 0x08, 0x00
+.byte 0x19, 0x70, 0x3d, 0xbb, 0x64, 0x89, 0x3b, 0x31, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.byte 0xf3, 0xfd, 0x54, 0x23, 0x18, 0x00, 0x00, 0x00, 0xa6, 0x86, 0x3b, 0xaa, 0x00, 0x00, 0x08, 0x00
+.byte 0x19, 0x70, 0x3d, 0xbb, 0x64, 0x89, 0x3b, 0x31, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.byte 0xf3, 0xfd, 0x54, 0x23, 0x18, 0x00, 0x00, 0x00, 0xa6, 0x86, 0x3b, 0xaa, 0x00, 0x00, 0x08, 0x00
+.byte 0x19, 0x70, 0x3d, 0xbb, 0x64, 0x89, 0x3b, 0x31, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
+
+.fill 4096-(.-stickypage), 1, 0
+.size stickypage, 4096
diff --git a/arch/sandbox/board/watchdog.c b/arch/sandbox/board/watchdog.c
new file mode 100644
index 0000000000..074c96a8a9
--- /dev/null
+++ b/arch/sandbox/board/watchdog.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <errno.h>
+#include <driver.h>
+#include <mach/linux.h>
+#include <of.h>
+#include <watchdog.h>
+#include <linux/nvmem-consumer.h>
+#include <asm/reset_source.h>
+
+struct sandbox_watchdog {
+ struct watchdog wdd;
+ bool cant_disable :1;
+ struct nvmem_cell *reset_source_cell;
+};
+
+static inline struct sandbox_watchdog *to_sandbox_watchdog(struct watchdog *wdd)
+{
+ return container_of(wdd, struct sandbox_watchdog, wdd);
+}
+
+static int sandbox_watchdog_set_timeout(struct watchdog *wdd, unsigned int timeout)
+{
+ struct sandbox_watchdog *wd = to_sandbox_watchdog(wdd);
+
+ if (!timeout && wd->cant_disable)
+ return -ENOSYS;
+
+ if (timeout > wdd->timeout_max)
+ return -EINVAL;
+
+ sandbox_save_reset_source(wd->reset_source_cell, RESET_WDG);
+
+ linux_watchdog_set_timeout(timeout);
+ return 0;
+}
+
+static int sandbox_watchdog_probe(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct sandbox_watchdog *wd;
+ struct watchdog *wdd;
+
+ wd = xzalloc(sizeof(*wd));
+
+ wdd = &wd->wdd;
+ wdd->hwdev = dev;
+ wdd->set_timeout = sandbox_watchdog_set_timeout;
+ wdd->timeout_max = 1000;
+
+ wd->reset_source_cell = of_nvmem_cell_get(np, "reset-source");
+ if (IS_ERR(wd->reset_source_cell)) {
+ if (PTR_ERR(wd->reset_source_cell) != -EPROBE_DEFER)
+ dev_warn(dev, "No reset source info available: %pe\n",
+ wd->reset_source_cell);
+ wd->reset_source_cell = NULL;
+ }
+
+ wd->cant_disable = of_property_read_bool(np, "barebox,cant-disable");
+
+ return watchdog_register(wdd);
+}
+
+
+static __maybe_unused struct of_device_id sandbox_watchdog_dt_ids[] = {
+ { .compatible = "barebox,sandbox-watchdog" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sandbox_watchdog_dt_ids);
+
+static struct driver sandbox_watchdog_drv = {
+ .name = "sandbox-watchdog",
+ .of_compatible = sandbox_watchdog_dt_ids,
+ .probe = sandbox_watchdog_probe,
+};
+device_platform_driver(sandbox_watchdog_drv);
diff --git a/arch/sandbox/configs/hosttools_defconfig b/arch/sandbox/configs/hosttools_defconfig
index 72ec0fc462..0b62b648c7 100644
--- a/arch/sandbox/configs/hosttools_defconfig
+++ b/arch/sandbox/configs/hosttools_defconfig
@@ -2,6 +2,6 @@ CONFIG_IMD=y
CONFIG_COMPILE_HOST_TOOLS=y
CONFIG_ARCH_IMX_USBLOADER=y
CONFIG_MVEBU_HOSTTOOLS=y
-CONFIG_MXS_HOSTTOOLS=y
CONFIG_OMAP3_USB_LOADER=y
CONFIG_OMAP4_HOSTTOOL_USBBOOT=y
+CONFIG_RK_USB_LOADER=y
diff --git a/arch/sandbox/configs/sandbox_defconfig b/arch/sandbox/configs/sandbox_defconfig
index c343f053fa..1bb98c550c 100644
--- a/arch/sandbox/configs/sandbox_defconfig
+++ b/arch/sandbox/configs/sandbox_defconfig
@@ -1,21 +1,35 @@
+CONFIG_MALLOC_SIZE=0x1000000
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
-CONFIG_PARTITION=y
+CONFIG_CONSOLE_ALLOW_COLOR=y
+CONFIG_PARTITION_DISK_EFI=y
CONFIG_DEFAULT_COMPRESSION_GZIP=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW_REBOOT_MODE=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/sandbox/board/env"
+CONFIG_STATE=y
+CONFIG_STATE_CRYPTO=y
+CONFIG_RESET_SOURCE=y
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_IMD=y
CONFIG_CMD_MEMINFO=y
-# CONFIG_CMD_BOOTM is not set
+CONFIG_CMD_POLLER=y
+CONFIG_CMD_SLICE=y
CONFIG_CMD_GO=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADS=y
+CONFIG_CMD_LOADY=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_SAVES=y
CONFIG_CMD_UIMAGE=y
CONFIG_CMD_PARTITION=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_DEFAULTENV=y
+CONFIG_CMD_LOADENV=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
@@ -39,14 +53,18 @@ CONFIG_CMD_PING=y
CONFIG_CMD_TFTP=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_EDIT=y
+CONFIG_CMD_LOGIN=y
CONFIG_CMD_MENU=y
CONFIG_CMD_MENU_MANAGEMENT=y
CONFIG_CMD_MENUTREE=y
+CONFIG_CMD_PASSWD=y
CONFIG_CMD_SPLASH=y
+CONFIG_CMD_FBTEST=y
CONFIG_CMD_READLINE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_CRC=y
CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_MEMTEST=y
CONFIG_CMD_MM=y
CONFIG_CMD_DETECT=y
CONFIG_CMD_FLASH=y
@@ -56,18 +74,34 @@ CONFIG_CMD_LED=y
CONFIG_CMD_POWEROFF=y
CONFIG_CMD_SPI=y
CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_WD=y
CONFIG_CMD_2048=y
+CONFIG_CMD_KEYSTORE=y
+CONFIG_CMD_LINUX_EXEC=y
+CONFIG_CMD_OF_DIFF=y
CONFIG_CMD_OF_NODE=y
CONFIG_CMD_OF_PROPERTY=y
CONFIG_CMD_OF_DISPLAY_TIMINGS=y
+CONFIG_CMD_OF_FIXUP_STATUS=y
+CONFIG_CMD_OF_OVERLAY=y
CONFIG_CMD_OFTREE=y
CONFIG_CMD_TIME=y
+CONFIG_CMD_UPTIME=y
+CONFIG_CMD_STATE=y
+CONFIG_CMD_DHRYSTONE=y
CONFIG_CMD_SPD_DECODE=y
+CONFIG_CMD_SEED=y
CONFIG_NET=y
CONFIG_NET_NFS=y
CONFIG_NET_NETCONSOLE=y
+CONFIG_NET_SNTP=y
+CONFIG_NET_FASTBOOT=y
+CONFIG_FEATURE_CONTROLLER=y
CONFIG_OFDEVICE=y
+# CONFIG_FEATURE_CONTROLLER_FIXUP is not set
CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_OF_BAREBOX_ENV_IN_FS=y
+CONFIG_OF_OVERLAY_LIVE=y
CONFIG_DRIVER_NET_TAP=y
CONFIG_DRIVER_SPI_GPIO=y
CONFIG_I2C=y
@@ -76,6 +110,10 @@ CONFIG_MTD=y
CONFIG_MTD_M25P80=y
CONFIG_VIDEO=y
CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_MFD_SYSCON=y
+CONFIG_STATE_DRV=y
+CONFIG_UBOOTVAR=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_LED_GPIO_OF=y
@@ -84,9 +122,13 @@ CONFIG_LED_GPIO_BICOLOR=y
CONFIG_LED_TRIGGERS=y
CONFIG_EEPROM_AT25=y
CONFIG_EEPROM_AT24=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_POLLER=y
# CONFIG_PINCTRL is not set
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
+CONFIG_SYSCON_REBOOT_MODE=y
+CONFIG_NVMEM_REBOOT_MODE=y
CONFIG_FS_CRAMFS=y
CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
@@ -94,15 +136,19 @@ CONFIG_FS_NFS=y
CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
+CONFIG_FS_JFFS2=y
CONFIG_FS_BPKFS=y
CONFIG_FS_UIMAGEFS=y
+CONFIG_FS_PSTORE=y
+CONFIG_FS_PSTORE_CONSOLE=y
CONFIG_FS_SQUASHFS=y
+CONFIG_FS_UBOOTVARFS=y
CONFIG_BZLIB=y
CONFIG_LZ4_DECOMPRESS=y
CONFIG_XZ_DECOMPRESS=y
+CONFIG_BASE64=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_BMP=y
-CONFIG_PNG=y
CONFIG_FONT_8x16=y
CONFIG_FONT_7x14=y
CONFIG_FONT_MINI_4x6=y
@@ -112,4 +158,3 @@ CONFIG_BAREBOX_LOGO_240=y
CONFIG_BAREBOX_LOGO_320=y
CONFIG_BAREBOX_LOGO_400=y
CONFIG_BAREBOX_LOGO_640=y
-CONFIG_DIGEST_HMAC_GENERIC=y
diff --git a/arch/sandbox/configs/targettools_defconfig b/arch/sandbox/configs/targettools_defconfig
new file mode 100644
index 0000000000..22845def61
--- /dev/null
+++ b/arch/sandbox/configs/targettools_defconfig
@@ -0,0 +1,10 @@
+CONFIG_IMD=y
+CONFIG_IMD_TARGET=y
+CONFIG_KERNEL_INSTALL_TARGET=y
+CONFIG_BAREBOXENV_TARGET=y
+CONFIG_BAREBOXCRC32_TARGET=y
+CONFIG_MVEBU_KWBOOT_TARGET=y
+CONFIG_ARCH_IMX_USBLOADER_TARGET=y
+CONFIG_OMAP3_USB_LOADER_TARGET=y
+CONFIG_OMAP4_USBBOOT_TARGET=y
+CONFIG_RK_USB_LOADER_TARGET=y
diff --git a/arch/sandbox/dts/.gitignore b/arch/sandbox/dts/.gitignore
deleted file mode 100644
index 077903c50a..0000000000
--- a/arch/sandbox/dts/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*dtb*
diff --git a/arch/sandbox/dts/Makefile b/arch/sandbox/dts/Makefile
index 6f4344da68..79625b103e 100644
--- a/arch/sandbox/dts/Makefile
+++ b/arch/sandbox/dts/Makefile
@@ -1,8 +1,10 @@
-always-$(CONFIG_OFTREE) += \
- sandbox.dtb
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_OFTREE) += \
+ sandbox.dtb.o
# just to build a built-in.o. Otherwise compilation fails when no devicetree is
# created.
obj- += dummy.o
-clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts
+clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.z
diff --git a/arch/sandbox/dts/sandbox-state-example.dtsi b/arch/sandbox/dts/sandbox-state-example.dtsi
deleted file mode 100644
index 98640f6677..0000000000
--- a/arch/sandbox/dts/sandbox-state-example.dtsi
+++ /dev/null
@@ -1,50 +0,0 @@
-/ {
- aliases {
- state = &state;
- };
-
- disk {
- compatible = "barebox,hostfile";
- barebox,filename = "disk";
- reg = <0x0 0x0 0x0 0x100000>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- hostfile_state: state@0 {
- reg = <0x0 0x1000>;
- label = "state";
- };
- };
- };
-
- state: state {
- magic = <0xaa3b86a6>;
- compatible = "barebox,state";
- backend-type = "raw";
- backend = <&hostfile_state>;
- backend-storage-type = "direct";
- backend-stridesize = <64>;
-
- #address-cells = <1>;
- #size-cells = <1>;
- vars {
- #address-cells = <1>;
- #size-cells = <1>;
-
- x {
- reg = <0x0 0x4>;
- type = "uint32";
- default = <1>;
- };
-
- y {
- reg = <0x4 0x4>;
- type = "uint32";
- default = <3>;
- };
- };
- };
-};
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 2595aa13fa..f3fe6ce65c 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -1,7 +1,126 @@
/dts-v1/;
-#include "skeleton.dtsi"
-
/ {
+ model = "Sandbox";
+ compatible = "barebox,sandbox";
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ bmode = &bmode;
+ state = &state;
+ };
+
+ chosen {
+ environment {
+ compatible = "barebox,environment";
+ device-path = &part_env;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0 0 0 0>;
+ };
+
+ state: state {
+ magic = <0xaa3b86a6>;
+ compatible = "barebox,state";
+ backend-type = "raw";
+ backend = <&part_state>;
+ backend-storage-type = "direct";
+ backend-stridesize = <64>;
+ /* suppres sandbox warnings when stickypage is missing */
+ barebox,feature-gates = <&stickypage>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ vars {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ x {
+ reg = <0x0 0x4>;
+ type = "uint32";
+ default = <1>;
+ };
+
+ y {
+ reg = <0x4 0x4>;
+ type = "uint32";
+ default = <3>;
+ };
+ };
+ };
+
+ stickypage: stickypage {
+ compatible = "barebox,stickypage", "syscon";
+ reg = <0 0 0 4096>;
+ barebox,cdev; /* no caching allowed */
+ barebox,feature-controller;
+ #feature-cells = <0>;
+
+ bmode: reboot-mode {
+ compatible = "nvmem-reboot-mode";
+ nvmem-cells = <&reboot_mode>;
+ nvmem-cell-names = "reboot-mode";
+
+ mode-normal = <0x000000>;
+ mode-loader = <0xbbbbbb>;
+ };
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ part_nvmem: nvmem@300 {
+ compatible = "nvmem-cells";
+ reg = <0x300 0x100>;
+ label = "nvmem";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ reset_source: reset-source@0 {
+ reg = <0x0 0x1>;
+ };
+
+ reboot_mode: reboot-mode@1 {
+ reg = <0x1 0x4>;
+ };
+ };
+
+ part_env: env@400 {
+ reg = <0x400 0x800>;
+ label = "env";
+ };
+
+ part_state: state@c00 {
+ reg = <0xC00 0x400>;
+ label = "state";
+ };
+ };
+ };
+
+ power {
+ compatible = "barebox,sandbox-power";
+ nvmem-cell-names = "reset-source";
+ nvmem-cells = <&reset_source>;
+ };
+
+ watchdog {
+ compatible = "barebox,sandbox-watchdog";
+ nvmem-cell-names = "reset-source";
+ nvmem-cells = <&reset_source>;
+ };
+
+ sound {
+ compatible = "barebox,sandbox-sound";
+ };
+ led {
+ compatible = "barebox,sandbox-led";
+ };
};
diff --git a/arch/sandbox/dts/skeleton.dtsi b/arch/sandbox/dts/skeleton.dtsi
deleted file mode 100644
index 8ba7663eb5..0000000000
--- a/arch/sandbox/dts/skeleton.dtsi
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Skeleton device tree; the bare minimum needed to boot; just include and
- * add a compatible value. The bootloader will typically populate the memory
- * node.
- */
-
-/ {
- #address-cells = <2>;
- #size-cells = <2>;
- chosen { };
- aliases { };
- memory { device_type = "memory"; reg = <0 0 0 0>; };
-};
diff --git a/arch/sandbox/include/asm/barebox.lds.h b/arch/sandbox/include/asm/barebox.lds.h
new file mode 100644
index 0000000000..540d740959
--- /dev/null
+++ b/arch/sandbox/include/asm/barebox.lds.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <asm-generic/barebox.lds.h>
diff --git a/arch/sandbox/include/asm/bitsperlong.h b/arch/sandbox/include/asm/bitsperlong.h
index 6dc0bb0c13..bf000a04cc 100644
--- a/arch/sandbox/include/asm/bitsperlong.h
+++ b/arch/sandbox/include/asm/bitsperlong.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#include <asm-generic/bitsperlong.h>
diff --git a/arch/sandbox/include/asm/byteorder.h b/arch/sandbox/include/asm/byteorder.h
index 3d82bcba6e..fdb421c7a5 100644
--- a/arch/sandbox/include/asm/byteorder.h
+++ b/arch/sandbox/include/asm/byteorder.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef _SANDBOX_BYTEORDER_H
#define _SANDBOX_BYTEORDER_H
diff --git a/arch/sandbox/include/asm/common.h b/arch/sandbox/include/asm/common.h
index 9b8bd2d94c..002dfb52b5 100644
--- a/arch/sandbox/include/asm/common.h
+++ b/arch/sandbox/include/asm/common.h
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef ASM_COMMON_H
#define ASM_COMMON_H
-#define ARCH_HAS_CTRLC
-
#endif /* ASM_COMMON_H */
diff --git a/arch/sandbox/include/asm/debug_ll.h b/arch/sandbox/include/asm/debug_ll.h
new file mode 100644
index 0000000000..7bef871058
--- /dev/null
+++ b/arch/sandbox/include/asm/debug_ll.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_DEBUG_LL__
+#define __ASM_DEBUG_LL__
+
+#undef putchar
+
+static inline void PUTC_LL(char ch)
+{
+ int putchar(int c);
+ putchar(ch);
+}
+
+#define putchar barebox_putchar
+
+#endif /* __ASM_DEBUG_LL__ */
diff --git a/arch/sandbox/include/asm/dma.h b/arch/sandbox/include/asm/dma.h
index 5e72d8e7df..cafbb7fe6a 100644
--- a/arch/sandbox/include/asm/dma.h
+++ b/arch/sandbox/include/asm/dma.h
@@ -12,12 +12,9 @@
#include <linux/string.h>
#include <driver.h>
-#define dma_alloc dma_alloc
-static inline void *dma_alloc(size_t size)
-{
- return xmemalign(64, ALIGN(size, 64));
-}
+#define DMA_ALIGNMENT 64
+#define dma_alloc_coherent dma_alloc_coherent
static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
{
void *ret = xmemalign(4096, size);
@@ -29,35 +26,28 @@ static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
return ret;
}
+#define dma_alloc_writecombine dma_alloc_writecombine
static inline void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle)
{
return dma_alloc_coherent(size, dma_handle);
}
+#define dma_free_coherent dma_free_coherent
static inline void dma_free_coherent(void *mem, dma_addr_t dma_handle,
size_t size)
{
free(mem);
}
-static inline dma_addr_t dma_map_single(struct device_d *dev, void *ptr, size_t size,
- enum dma_data_direction dir)
-{
- return (dma_addr_t)ptr;
-}
-
-static inline void dma_unmap_single(struct device_d *dev, dma_addr_t addr, size_t size,
- enum dma_data_direction dir)
-{
-}
-
-static inline void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
- enum dma_data_direction dir)
+#define arch_sync_dma_for_cpu arch_sync_dma_for_cpu
+static inline void arch_sync_dma_for_cpu(void *vaddr, size_t size,
+ enum dma_data_direction dir)
{
}
-static inline void dma_sync_single_for_device(dma_addr_t address, size_t size,
- enum dma_data_direction dir)
+#define arch_sync_dma_for_device arch_sync_dma_for_device
+static inline void arch_sync_dma_for_device(void *vaddr, size_t size,
+ enum dma_data_direction dir)
{
}
diff --git a/arch/sandbox/include/asm/elf.h b/arch/sandbox/include/asm/elf.h
index e71a60aeb9..f08d5930c6 100644
--- a/arch/sandbox/include/asm/elf.h
+++ b/arch/sandbox/include/asm/elf.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __ASM_SANDBOX_ELF_H__
#define __ASM_SANDBOX_ELF_H__
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index 6a0e77aead..eec279b888 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -1,19 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __ASM_SANDBOX_IO_H
#define __ASM_SANDBOX_IO_H
-#define IO_SPACE_LIMIT 0
-
-#include <asm-generic/io.h>
-#include <asm-generic/bitio.h>
+#define IO_SPACE_LIMIT 0xffff
+/* pacify static analyzers */
+#define PCI_IOBASE ((void __iomem *)__pci_iobase)
-static inline void *phys_to_virt(unsigned long phys)
-{
- return (void *)phys;
-}
+extern unsigned char __pci_iobase[IO_SPACE_LIMIT];
-static inline unsigned long virt_to_phys(volatile void *mem)
-{
- return (unsigned long)mem;
-}
+#include <asm-generic/io.h>
#endif /* __ASM_SANDBOX_IO_H */
diff --git a/arch/sandbox/include/asm/linkage.h b/arch/sandbox/include/asm/linkage.h
new file mode 100644
index 0000000000..1d78d9169b
--- /dev/null
+++ b/arch/sandbox/include/asm/linkage.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+/* referenced by <linux/linkage.h> */
+
+#endif
diff --git a/arch/sandbox/include/asm/mmu.h b/arch/sandbox/include/asm/mmu.h
index 95af871420..1c2646ebb3 100644
--- a/arch/sandbox/include/asm/mmu.h
+++ b/arch/sandbox/include/asm/mmu.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __ASM_MMU_H
#define __ASM_MMU_H
diff --git a/arch/sandbox/include/asm/posix_types.h b/arch/sandbox/include/asm/posix_types.h
index 22cae6230c..feaed42471 100644
--- a/arch/sandbox/include/asm/posix_types.h
+++ b/arch/sandbox/include/asm/posix_types.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#include <asm-generic/posix_types.h>
diff --git a/arch/sandbox/include/asm/reset_source.h b/arch/sandbox/include/asm/reset_source.h
new file mode 100644
index 0000000000..1690299c47
--- /dev/null
+++ b/arch/sandbox/include/asm/reset_source.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __SANDBOX_RESET_SOURCE_H
+#define __SANDBOX_RESET_SOURCE_H
+
+#include <reset_source.h>
+#include <linux/nvmem-consumer.h>
+
+static inline void sandbox_save_reset_source(struct nvmem_cell *reset_source_cell,
+ enum reset_src_type src)
+{
+ if (reset_source_cell)
+ WARN_ON(nvmem_cell_write(reset_source_cell, &(u8) { src }, 1) <= 0);
+}
+
+#endif
diff --git a/arch/sandbox/include/asm/sections.h b/arch/sandbox/include/asm/sections.h
index 2b8c516038..c6dd0eead2 100644
--- a/arch/sandbox/include/asm/sections.h
+++ b/arch/sandbox/include/asm/sections.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#include <asm-generic/sections.h>
diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h
new file mode 100644
index 0000000000..a300758c3d
--- /dev/null
+++ b/arch/sandbox/include/asm/setjmp.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __SETJMP_H_
+#define __SETJMP_H_
+
+struct jmp_buf_data {
+ unsigned char opaque[512] __aligned(16);
+};
+
+typedef struct jmp_buf_data jmp_buf[1];
+
+int setjmp(jmp_buf jmp) __attribute__((returns_twice));
+void longjmp(jmp_buf jmp, int ret) __attribute__((noreturn));
+
+int initjmp(jmp_buf jmp, void __attribute__((noreturn)) (*func)(void), void *stack_top);
+
+#endif
diff --git a/arch/sandbox/include/asm/string.h b/arch/sandbox/include/asm/string.h
index 2997587d82..b3c27a412d 100644
--- a/arch/sandbox/include/asm/string.h
+++ b/arch/sandbox/include/asm/string.h
@@ -1 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
/* dummy */
diff --git a/arch/sandbox/include/asm/swab.h b/arch/sandbox/include/asm/swab.h
index 60a90120b6..0ca746f0f1 100644
--- a/arch/sandbox/include/asm/swab.h
+++ b/arch/sandbox/include/asm/swab.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef _ASM_SWAB_H
#define _ASM_SWAB_H
diff --git a/arch/sandbox/include/asm/types.h b/arch/sandbox/include/asm/types.h
index 7b356a99eb..e29dde377c 100644
--- a/arch/sandbox/include/asm/types.h
+++ b/arch/sandbox/include/asm/types.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __ASM_SANDBOX_TYPES_H
#define __ASM_SANDBOX_TYPES_H
diff --git a/arch/sandbox/include/asm/unaligned.h b/arch/sandbox/include/asm/unaligned.h
index d02da6e60d..7bca3ff8a4 100644
--- a/arch/sandbox/include/asm/unaligned.h
+++ b/arch/sandbox/include/asm/unaligned.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef _ASM_SANDBOX_UNALIGNED_H
#define _ASM_SANDBOX_UNALIGNED_H
diff --git a/arch/sandbox/include/asm/word-at-a-time.h b/arch/sandbox/include/asm/word-at-a-time.h
new file mode 100644
index 0000000000..f6306fb896
--- /dev/null
+++ b/arch/sandbox/include/asm/word-at-a-time.h
@@ -0,0 +1,2 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <asm-generic/word-at-a-time.h>
diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile
index b32ca6aaf8..9535305d5b 100644
--- a/arch/sandbox/lib/Makefile
+++ b/arch/sandbox/lib/Makefile
@@ -1 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-$(CONFIG_ARCH_HAS_STACK_DUMP) += unwind.o
diff --git a/arch/sandbox/lib/asm-offsets.c b/arch/sandbox/lib/asm-offsets.c
index 22f382b71e..21aab692d0 100644
--- a/arch/sandbox/lib/asm-offsets.c
+++ b/arch/sandbox/lib/asm-offsets.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
/*
* Generate definitions needed by assembly language modules.
* This code generates raw asm output which is post-processed to extract
diff --git a/arch/sandbox/mach-sandbox/include/mach/hostfile.h b/arch/sandbox/mach-sandbox/include/mach/hostfile.h
index c3f9af97c4..b461d5ebc3 100644
--- a/arch/sandbox/mach-sandbox/include/mach/hostfile.h
+++ b/arch/sandbox/mach-sandbox/include/mach/hostfile.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __ASM_ARCH_HOSTFILE_H
#define __ASM_ARCH_HOSTFILE_H
@@ -8,6 +10,8 @@ struct hf_info {
const char *devname;
const char *filename;
unsigned int is_blockdev:1;
+ unsigned int is_cdev:1;
+ unsigned int is_readonly:1;
};
int barebox_register_filedev(struct hf_info *hf);
diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h
index 1ab48e52a0..f4d91f08de 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -1,9 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __ASM_ARCH_LINUX_H
#define __ASM_ARCH_LINUX_H
-struct device_d;
+struct hf_info;
+
+struct device;
-int sandbox_add_device(struct device_d *dev);
+int sandbox_add_device(struct device *dev);
struct fb_bitfield;
@@ -11,10 +15,12 @@ int linux_register_device(const char *name, void *start, void *end);
int tap_alloc(const char *dev);
uint64_t linux_get_time(void);
int linux_open(const char *filename, int readwrite);
+char *linux_get_stickypage_path(void);
+int linux_open_hostfile(struct hf_info *hf);
int linux_read(int fd, void *buf, size_t count);
int linux_read_nonblock(int fd, void *buf, size_t count);
ssize_t linux_write(int fd, const void *buf, size_t count);
-off_t linux_lseek(int fildes, off_t offset);
+loff_t linux_lseek(int fildes, loff_t offset);
int linux_tstc(int fd);
void __attribute__((noreturn)) linux_exit(void);
void linux_hang(void);
@@ -22,6 +28,8 @@ void linux_reexec(void);
int linux_execve(const char * filename, char *const argv[], char *const envp[]);
+int linux_watchdog_set_timeout(unsigned int timeout);
+
int barebox_register_console(int stdinfd, int stdoutfd);
int barebox_register_dtb(const void *dtb);
@@ -33,13 +41,21 @@ struct linux_console_data {
extern int sdl_xres;
extern int sdl_yres;
-void sdl_close(void);
-int sdl_open(int xres, int yres, int bpp, void* buf);
-void sdl_stop_timer(void);
-void sdl_start_timer(void);
-void sdl_get_bitfield_rgba(struct fb_bitfield *r, struct fb_bitfield *g,
- struct fb_bitfield *b, struct fb_bitfield *a);
-void sdl_setpixel(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+struct sdl_fb_info {
+ void *screen_base;
+ int xres;
+ int yres;
+ int bpp;
+ int rmask, gmask, bmask, amask;
+};
+int sdl_video_open(const struct sdl_fb_info *);
+void sdl_video_pause(void);
+void sdl_video_close(void);
+
+int sdl_sound_init(unsigned sample_rate);
+int sdl_sound_play(const void *data, unsigned nsamples);
+void sdl_sound_stop(void);
+void sdl_sound_close(void);
struct ft2232_bitbang;
struct ft2232_bitbang *barebox_libftdi1_open(int vendor_id, int device_id,
diff --git a/arch/sandbox/os/Makefile b/arch/sandbox/os/Makefile
index 15d688bfdd..055ce1a316 100644
--- a/arch/sandbox/os/Makefile
+++ b/arch/sandbox/os/Makefile
@@ -1,10 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
machine-y := sandbox
machdirs := $(patsubst %,arch/sandbox/mach-%/,$(machine-y))
KBUILD_CPPFLAGS = $(patsubst %,-I$(srctree)/%include,$(machdirs))
-KBUILD_CPPFLAGS += -DCONFIG_MALLOC_SIZE=$(CONFIG_MALLOC_SIZE)
+KBUILD_CPPFLAGS += -DCONFIG_MALLOC_SIZE=$(CONFIG_MALLOC_SIZE) -D_FILE_OFFSET_BITS=64 \
+ -DCONFIG_STACK_SIZE=$(CONFIG_STACK_SIZE)
KBUILD_CFLAGS := -Wall
@@ -14,11 +17,11 @@ ifeq ($(CONFIG_SANDBOX_LINUX_I386),y)
KBUILD_CFLAGS += -m32
endif
-obj-y = common.o tap.o
+obj-y = common.o tap.o setjmp.o
obj-$(CONFIG_MALLOC_LIBC) += libc_malloc.o
-CFLAGS_sdl.o = $(shell pkg-config sdl --cflags)
-obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o
+CFLAGS_sdl.o = $(shell $(PKG_CONFIG) sdl2 --cflags)
+obj-$(CONFIG_SDL) += sdl.o
-CFLAGS_ftdi.o = $(shell pkg-config libftdi1 --cflags)
+CFLAGS_ftdi.o = $(shell $(PKG_CONFIG) libftdi1 --cflags)
obj-$(CONFIG_GPIO_LIBFTDI1) += ftdi.o
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c
index 43ee95edb6..3446074f99 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -19,6 +19,7 @@
* These are host includes. Never include any barebox header
* files here...
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -38,6 +39,7 @@
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
+#include <sys/time.h>
/*
* ...except the ones needed to connect with barebox
*/
@@ -73,6 +75,15 @@ static void cookmode(void)
tcsetattr(0, TCSANOW, &term_orig);
}
+static char *stickypage_path;
+
+static void prepare_exit(void)
+{
+ cookmode();
+ if (stickypage_path)
+ remove(stickypage_path);
+}
+
int linux_tstc(int fd)
{
struct timeval tv = {
@@ -120,12 +131,27 @@ uint64_t linux_get_time(void)
void __attribute__((noreturn)) linux_exit(void)
{
- cookmode();
+ prepare_exit();
exit(0);
}
static char **saved_argv;
+static int selfpath(char *buf, size_t len)
+{
+ int ret;
+
+ /* we must follow the symlink, so we can exec an updated executable */
+ ret = readlink("/proc/self/exe", buf, len - 1);
+ if (ret < 0)
+ return ret;
+
+ if (0 < ret && ret < len - 1)
+ buf[ret] = '\0';
+
+ return ret;
+}
+
void linux_reexec(void)
{
char buf[4097];
@@ -134,9 +160,8 @@ void linux_reexec(void)
cookmode();
/* we must follow the symlink, so we can exec an updated executable */
- ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
- if (0 < ret && ret < sizeof(buf) - 1) {
- buf[ret] = '\0';
+ ret = selfpath(buf, sizeof(buf));
+ if (ret > 0) {
execv(buf, saved_argv);
if (!strcmp(&buf[ret - DELETED_OFFSET], " (deleted)")) {
printf("barebox image on disk changed. Loading new.\n");
@@ -151,7 +176,7 @@ void linux_reexec(void)
void linux_hang(void)
{
- cookmode();
+ prepare_exit();
/* falls through to generic hang() */
}
@@ -216,7 +241,7 @@ ssize_t linux_write(int fd, const void *buf, size_t count)
return write(fd, buf, count);
}
-off_t linux_lseek(int fd, off_t offset)
+loff_t linux_lseek(int fd, loff_t offset)
{
return lseek(fd, offset, SEEK_SET);
}
@@ -242,6 +267,29 @@ int linux_execve(const char * filename, char *const argv[], char *const envp[])
}
}
+static void linux_watchdog(int signo)
+{
+ linux_reexec();
+ _exit(0);
+}
+
+int linux_watchdog_set_timeout(unsigned int timeout)
+{
+ static int signal_handler_installed;
+
+ if (!signal_handler_installed) {
+ struct sigaction sact = {
+ .sa_flags = SA_NODEFER, .sa_handler = linux_watchdog
+ };
+
+ sigemptyset(&sact.sa_mask);
+ sigaction(SIGALRM, &sact, NULL);
+ signal_handler_installed = 1;
+ }
+
+ return alarm(timeout);
+}
+
extern void start_barebox(void);
extern void mem_malloc_init(void *start, void *end);
@@ -249,13 +297,11 @@ extern char * strsep_unescaped(char **s, const char *ct);
static int add_image(const char *_str, char *devname_template, int *devname_number)
{
- struct hf_info *hf = malloc(sizeof(struct hf_info));
+ struct hf_info *hf = calloc(1, sizeof(struct hf_info));
char *str, *filename, *devname;
char tmp[16];
- int readonly = 0, cdev = 0, blkdev = 0;
- struct stat s;
char *opt;
- int fd, ret;
+ int ret;
if (!hf)
return -1;
@@ -265,11 +311,11 @@ static int add_image(const char *_str, char *devname_template, int *devname_numb
filename = strsep_unescaped(&str, ",");
while ((opt = strsep_unescaped(&str, ","))) {
if (!strcmp(opt, "ro"))
- readonly = 1;
+ hf->is_readonly = 1;
if (!strcmp(opt, "cdev"))
- cdev = 1;
+ hf->is_cdev = 1;
if (!strcmp(opt, "blkdev"))
- blkdev = 1;
+ hf->is_blockdev = 1;
}
/* parses: "devname=filename" */
@@ -282,14 +328,86 @@ static int add_image(const char *_str, char *devname_template, int *devname_numb
devname = tmp;
}
- printf("add %s backed by file %s%s\n", devname,
- filename, readonly ? "(ro)" : "");
-
- fd = open(filename, (readonly ? O_RDONLY : O_RDWR) | O_CLOEXEC);
- hf->fd = fd;
hf->filename = filename;
- hf->is_blockdev = blkdev;
+ hf->devname = strdup(devname);
+
+ ret = barebox_register_filedev(hf);
+ if (ret)
+ free(hf);
+
+ return ret;
+}
+
+extern uint8_t stickypage[4096];
+char *linux_get_stickypage_path(void)
+{
+ size_t nwritten;
+ ssize_t ret;
+ int fd;
+
+ ret = asprintf(&stickypage_path, "%s/barebox/stickypage.%lu",
+ getenv("XDG_RUNTIME_DIR") ?: "/run", (long)getpid());
+ if (ret < 0)
+ goto err_asprintf;
+
+ ret = mkdir(dirname(stickypage_path), 0755);
+ if (ret < 0 && errno != EEXIST) {
+ perror("mkdir");
+ goto err_creat;
+ }
+
+ stickypage_path[strlen(stickypage_path)] = '/';
+
+ fd = open(stickypage_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644);
+ if (fd < 0) {
+ if (errno == EEXIST)
+ return stickypage_path;
+
+ perror("open");
+ goto err_creat;
+ }
+
+ for (nwritten = 0; nwritten < sizeof(stickypage); ) {
+ ret = write(fd, &stickypage[nwritten], sizeof(stickypage) - nwritten);
+ if (ret < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ perror("write");
+ goto err_write;
+ }
+
+ nwritten += ret;
+ }
+
+ close(fd);
+
+ return stickypage_path;
+
+err_write:
+ close(fd);
+err_creat:
+ free(stickypage_path);
+err_asprintf:
+ stickypage_path = NULL;
+
+ return NULL;
+}
+
+int linux_open_hostfile(struct hf_info *hf)
+{
+ char *buf = NULL;
+ struct stat s;
+ int fd = -1;
+
+ printf("add %s %sbacked by file %s%s\n", hf->devname,
+ hf->filename ? "" : "initially un", hf->filename ?: "",
+ hf->is_readonly ? "(ro)" : "");
+
+ if (!hf->filename)
+ return -ENOENT;
+
+ fd = hf->fd = open(hf->filename, (hf->is_readonly ? O_RDONLY : O_RDWR) | O_CLOEXEC);
if (fd < 0) {
perror("open");
goto err_out;
@@ -300,42 +418,41 @@ static int add_image(const char *_str, char *devname_template, int *devname_numb
goto err_out;
}
+ hf->base = (unsigned long)MAP_FAILED;
hf->size = s.st_size;
- hf->devname = strdup(devname);
if (S_ISBLK(s.st_mode)) {
if (ioctl(fd, BLKGETSIZE64, &hf->size) == -1) {
perror("ioctl");
goto err_out;
}
- if (!cdev)
+ if (!hf->is_cdev)
hf->is_blockdev = 1;
}
- if (hf->size <= SIZE_MAX)
+ if (hf->size <= SIZE_MAX) {
hf->base = (unsigned long)mmap(NULL, hf->size,
- PROT_READ | (readonly ? 0 : PROT_WRITE),
+ PROT_READ | (hf->is_readonly ? 0 : PROT_WRITE),
MAP_SHARED, fd, 0);
- else
- printf("warning: %s: contiguous map failed\n", filename);
- if (hf->base == (unsigned long)MAP_FAILED)
- printf("warning: mmapping %s failed: %s\n", filename, strerror(errno));
+ if (hf->base == (unsigned long)MAP_FAILED)
+ printf("warning: mmapping %s failed: %s\n",
+ hf->filename, strerror(errno));
+ } else {
+ printf("warning: %s: contiguous map failed\n", hf->filename);
+ }
- if (blkdev && hf->size % 512 != 0) {
+ if (hf->is_blockdev && hf->size % 512 != 0) {
printf("warning: registering %s as block device failed: invalid block size\n",
- filename);
+ hf->filename);
return -EINVAL;
}
- ret = barebox_register_filedev(hf);
- if (ret)
- goto err_out;
return 0;
err_out:
- if (fd > 0)
+ if (fd >= 0)
close(fd);
- free(hf);
+ free(buf);
return -1;
}
@@ -402,11 +519,9 @@ int main(int argc, char *argv[])
char *aux;
#ifdef CONFIG_ASAN
- __sanitizer_set_death_callback(cookmode);
+ __sanitizer_set_death_callback(prepare_exit);
#endif
- saved_argv = argv;
-
while (1) {
option_index = 0;
opt = getopt_long(argc, argv, optstring,
@@ -444,6 +559,8 @@ int main(int argc, char *argv[])
}
}
+ saved_argv = argv;
+
ram = malloc(malloc_size);
if (!ram) {
printf("unable to get malloc space\n");
diff --git a/arch/sandbox/os/libc_malloc.c b/arch/sandbox/os/libc_malloc.c
index 74e3e26805..975c41b0ec 100644
--- a/arch/sandbox/os/libc_malloc.c
+++ b/arch/sandbox/os/libc_malloc.c
@@ -6,18 +6,30 @@
#include <stdlib.h>
#include <malloc.h>
+#define BAREBOX_ENOMEM 12
+extern int barebox_errno;
+
void barebox_malloc_stats(void)
{
}
void *barebox_memalign(size_t alignment, size_t bytes)
{
- return memalign(alignment, bytes);
+ void *mem = memalign(alignment, bytes);
+ if (!mem)
+ barebox_errno = BAREBOX_ENOMEM;
+
+ return mem;
}
void *barebox_malloc(size_t size)
{
- return malloc(size);
+
+ void *mem = malloc(size);
+ if (!mem)
+ barebox_errno = BAREBOX_ENOMEM;
+
+ return mem;
}
void barebox_free(void *ptr)
@@ -27,10 +39,18 @@ void barebox_free(void *ptr)
void *barebox_realloc(void *ptr, size_t size)
{
- return realloc(ptr, size);
+ void *mem = realloc(ptr, size);
+ if (!mem)
+ barebox_errno = BAREBOX_ENOMEM;
+
+ return mem;
}
void *barebox_calloc(size_t n, size_t elem_size)
{
- return calloc(n, elem_size);
+ void *mem = calloc(n, elem_size);
+ if (!mem)
+ barebox_errno = BAREBOX_ENOMEM;
+
+ return mem;
}
diff --git a/arch/sandbox/os/sdl.c b/arch/sandbox/os/sdl.c
index 9a35279eb7..13178abfc0 100644
--- a/arch/sandbox/os/sdl.c
+++ b/arch/sandbox/os/sdl.c
@@ -1,103 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * GPL v2
+ * Copyright (c) 2021 Ahmad Fatoum
*/
#include <stdio.h>
+#include <stdbool.h>
#include <SDL.h>
-#include <time.h>
-#include <signal.h>
#include <mach/linux.h>
-#include <unistd.h>
-#include <pthread.h>
-struct fb_bitfield {
- uint32_t offset; /* beginning of bitfield */
- uint32_t length; /* length of bitfield */
- uint32_t msb_right; /* != 0 : Most significant bit is */
- /* right */
-};
+static void sdl_perror(const char *what)
+{
+ printf("SDL: Could not %s: %s.\n", what, SDL_GetError());
+}
-static SDL_Surface *real_screen;
-static void *buffer = NULL;
-pthread_t th;
+static struct sdl_fb_info info;
+static SDL_atomic_t shutdown;
+SDL_Window *window;
-static void sdl_copy_buffer(SDL_Surface *screen)
+static int scanout(void *ptr)
{
- if (SDL_MUSTLOCK(screen)) {
- if (SDL_LockSurface(screen) < 0)
- return;
+ SDL_Renderer *renderer;
+ SDL_Surface *surface;
+ SDL_Texture *texture;
+ void *buf = info.screen_base;
+ int ret = -1;
+
+ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+ if (!renderer) {
+ sdl_perror("create renderer");
+ return -1;
}
- memcpy(screen->pixels, buffer, screen->pitch * screen->h);
+ surface = SDL_CreateRGBSurface(0, info.xres, info.yres, info.bpp,
+ info.rmask, info.gmask, info.bmask, info.amask);
+ if (!surface) {
+ sdl_perror("create surface");
+ goto destroy_renderer;
+ }
- if(SDL_MUSTLOCK(screen))
- SDL_UnlockSurface(screen);
-}
+ texture = SDL_CreateTextureFromSurface(renderer, surface);
+ if (!texture) {
+ sdl_perror("create texture");
+ goto free_surface;
+ }
-static void *threadStart(void *ptr)
-{
- while (1) {
- usleep(1000 * 100);
+ while (!SDL_AtomicGet(&shutdown)) {
+ SDL_Delay(100);
- sdl_copy_buffer(real_screen);
- SDL_Flip(real_screen);
+ SDL_UpdateTexture(texture, NULL, buf, surface->pitch);
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
}
- return 0;
-}
+ ret = 0;
-void sdl_start_timer(void)
-{
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_create(&th, &attr, threadStart, NULL);
-}
+ SDL_DestroyTexture(texture);
+free_surface:
+ SDL_FreeSurface(surface);
+destroy_renderer:
+ SDL_DestroyRenderer(renderer);
-void sdl_stop_timer(void)
-{
- pthread_cancel(th);
+ return ret;
}
-void sdl_get_bitfield_rgba(struct fb_bitfield *r, struct fb_bitfield *g,
- struct fb_bitfield *b, struct fb_bitfield *a)
+static SDL_Thread *thread;
+
+void sdl_video_close(void)
{
- SDL_Surface *screen = real_screen;
-
- r->length = 8 - screen->format->Rloss;
- r->offset = screen->format->Rshift;
- g->length = 8 - screen->format->Gloss;
- g->offset = screen->format->Gshift;
- b->length = 8 - screen->format->Bloss;
- b->offset = screen->format->Bshift;
- a->length = 8 - screen->format->Aloss;
- a->offset = screen->format->Ashift;
+ SDL_AtomicSet(&shutdown, true); /* implies full memory barrier */
+ SDL_WaitThread(thread, NULL);
+ SDL_AtomicSet(&shutdown, false);
+ SDL_DestroyWindow(window);
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
-int sdl_open(int xres, int yres, int bpp, void* buf)
+int sdl_video_open(const struct sdl_fb_info *_info)
{
- int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
+ info = *_info;
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
- printf("Could not initialize SDL: %s.\n", SDL_GetError());
+ if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
+ sdl_perror("initialize SDL Video");
return -1;
}
- real_screen = SDL_SetVideoMode(xres, yres, bpp, flags);
- if (!real_screen) {
- sdl_close();
- fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError());
+ window = SDL_CreateWindow("barebox", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+ info.xres, info.yres, 0);
+ if (!window) {
+ sdl_perror("create window");
+ goto quit_subsystem;
+ }
+
+ /* All scanout needs to happen in the same thread, because not all
+ * graphic backends are thread-safe. The window is created in the main
+ * thread though to work around libEGL crashing with SDL_VIDEODRIVER=wayland
+ */
+
+ thread = SDL_CreateThread(scanout, "video-scanout", NULL);
+ if (!thread) {
+ sdl_perror("start scanout thread");
+ goto destroy_window;
+ }
+
+ return 0;
+
+destroy_window:
+ SDL_DestroyWindow(window);
+quit_subsystem:
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+
+ return -1;
+}
+
+static SDL_AudioDeviceID dev;
+
+int sdl_sound_init(unsigned sample_rate)
+{
+ SDL_AudioSpec audiospec = {
+ .freq = sample_rate,
+ .format = AUDIO_S16,
+ .channels = 1,
+ .samples = 2048,
+ };
+
+ if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
+ sdl_perror("initialize SDL Audio");
return -1;
}
- buffer = buf;
+ dev = SDL_OpenAudioDevice(NULL, 0, &audiospec, NULL, 0);
+ if (!dev) {
+ sdl_perror("initialize open audio device");
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ return -1;
+ }
+ SDL_PauseAudioDevice(dev, 0);
return 0;
}
-void sdl_close(void)
+void sdl_sound_close(void)
+{
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+}
+
+int sdl_sound_play(const void *data, unsigned nsamples)
+{
+ /* core sound support handles all the queueing for us */
+ SDL_ClearQueuedAudio(dev);
+ return SDL_QueueAudio(dev, data, nsamples * sizeof(uint16_t));
+}
+
+void sdl_sound_stop(void)
{
- sdl_stop_timer();
- SDL_Quit();
+ SDL_ClearQueuedAudio(dev);
}
diff --git a/arch/sandbox/os/setjmp.c b/arch/sandbox/os/setjmp.c
new file mode 100644
index 0000000000..7f686b0fc6
--- /dev/null
+++ b/arch/sandbox/os/setjmp.c
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * sigaltstack coroutine initialization code
+ *
+ * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
+ * Copyright (C) 2011 Kevin Wolf <kwolf@redhat.com>
+ * Copyright (C) 2012 Alex Barcelo <abarcelo@ac.upc.edu>
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ * This file is partly based on pth_mctx.c, from the GNU Portable Threads
+ * Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
+ */
+
+/* XXX Is there a nicer way to disable glibc's stack check for longjmp? */
+#ifdef _FORTIFY_SOURCE
+#undef _FORTIFY_SOURCE
+#endif
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <signal.h>
+
+typedef sigjmp_buf _jmp_buf __attribute__((aligned((16))));
+_Static_assert(sizeof(_jmp_buf) <= 512, "sigjmp_buf size exceeds expectation");
+
+/*
+ * Information for the signal handler (trampoline)
+ */
+static struct {
+ _jmp_buf *reenter;
+ void (*entry)(void);
+ volatile sig_atomic_t called;
+} tr_state;
+
+/*
+ * "boot" function
+ * This is what starts the coroutine, is called from the trampoline
+ * (from the signal handler when it is not signal handling, read ahead
+ * for more information).
+ */
+static void __attribute__((noinline, noreturn))
+coroutine_bootstrap(void (*entry)(void))
+{
+ for (;;)
+ entry();
+}
+
+/*
+ * This is used as the signal handler. This is called with the brand new stack
+ * (thanks to sigaltstack). We have to return, given that this is a signal
+ * handler and the sigmask and some other things are changed.
+ */
+static void coroutine_trampoline(int signal)
+{
+ /* Get the thread specific information */
+ tr_state.called = 1;
+
+ /*
+ * Here we have to do a bit of a ping pong between the caller, given that
+ * this is a signal handler and we have to do a return "soon". Then the
+ * caller can reestablish everything and do a siglongjmp here again.
+ */
+ if (!sigsetjmp(*tr_state.reenter, 0)) {
+ return;
+ }
+
+ /*
+ * Ok, the caller has siglongjmp'ed back to us, so now prepare
+ * us for the real machine state switching. We have to jump
+ * into another function here to get a new stack context for
+ * the auto variables (which have to be auto-variables
+ * because the start of the thread happens later). Else with
+ * PIC (i.e. Position Independent Code which is used when PTH
+ * is built as a shared library) most platforms would
+ * horrible core dump as experience showed.
+ */
+ coroutine_bootstrap(tr_state.entry);
+}
+
+int initjmp(_jmp_buf jmp, void (*func)(void), void *stack_top)
+{
+ struct sigaction sa;
+ struct sigaction osa;
+ stack_t ss;
+ stack_t oss;
+ sigset_t sigs;
+ sigset_t osigs;
+
+ /* The way to manipulate stack is with the sigaltstack function. We
+ * prepare a stack, with it delivering a signal to ourselves and then
+ * put sigsetjmp/siglongjmp where needed.
+ * This has been done keeping coroutine-ucontext (from the QEMU project)
+ * as a model and with the pth ideas (GNU Portable Threads).
+ * See coroutine-ucontext for the basics of the coroutines and see
+ * pth_mctx.c (from the pth project) for the
+ * sigaltstack way of manipulating stacks.
+ */
+
+ tr_state.entry = func;
+ tr_state.reenter = (void *)jmp;
+
+ /*
+ * Preserve the SIGUSR2 signal state, block SIGUSR2,
+ * and establish our signal handler. The signal will
+ * later transfer control onto the signal stack.
+ */
+ sigemptyset(&sigs);
+ sigaddset(&sigs, SIGUSR2);
+ pthread_sigmask(SIG_BLOCK, &sigs, &osigs);
+ sa.sa_handler = coroutine_trampoline;
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags = SA_ONSTACK;
+ if (sigaction(SIGUSR2, &sa, &osa) != 0) {
+ return -1;
+ }
+
+ /*
+ * Set the new stack.
+ */
+ ss.ss_sp = stack_top - CONFIG_STACK_SIZE;
+ ss.ss_size = CONFIG_STACK_SIZE;
+ ss.ss_flags = 0;
+ if (sigaltstack(&ss, &oss) < 0) {
+ return -1;
+ }
+
+ /*
+ * Now transfer control onto the signal stack and set it up.
+ * It will return immediately via "return" after the sigsetjmp()
+ * was performed. Be careful here with race conditions. The
+ * signal can be delivered the first time sigsuspend() is
+ * called.
+ */
+ tr_state.called = 0;
+ pthread_kill(pthread_self(), SIGUSR2);
+ sigfillset(&sigs);
+ sigdelset(&sigs, SIGUSR2);
+ while (!tr_state.called) {
+ sigsuspend(&sigs);
+ }
+
+ /*
+ * Inform the system that we are back off the signal stack by
+ * removing the alternative signal stack. Be careful here: It
+ * first has to be disabled, before it can be removed.
+ */
+ sigaltstack(NULL, &ss);
+ ss.ss_flags = SS_DISABLE;
+ if (sigaltstack(&ss, NULL) < 0) {
+ return -1;
+ }
+ sigaltstack(NULL, &ss);
+ if (!(oss.ss_flags & SS_DISABLE)) {
+ sigaltstack(&oss, NULL);
+ }
+
+ /*
+ * Restore the old SIGUSR2 signal handler and mask
+ */
+ sigaction(SIGUSR2, &osa, NULL);
+ pthread_sigmask(SIG_SETMASK, &osigs, NULL);
+
+ /*
+ * jmp can now be used to enter the trampoline again, but not as a
+ * signal handler. Instead it's longjmp'd to directly.
+ */
+
+ return 0;
+}
+
+int __attribute__((returns_twice)) barebox_setjmp(_jmp_buf jmp)
+{
+ return sigsetjmp(jmp, 0);
+}
+
+void __attribute((noreturn)) barebox_longjmp(_jmp_buf jmp, int ret)
+{
+ siglongjmp(jmp, ret);
+}