summaryrefslogtreecommitdiffstats
path: root/arch/sandbox
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sandbox')
-rw-r--r--arch/sandbox/Kconfig56
-rw-r--r--arch/sandbox/Makefile49
-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.c25
-rw-r--r--arch/sandbox/board/clock.c4
-rw-r--r--arch/sandbox/board/console.c7
-rw-r--r--arch/sandbox/board/dev-random.c2
-rw-r--r--arch/sandbox/board/devices.c11
-rw-r--r--arch/sandbox/board/dtb.c33
-rw-r--r--arch/sandbox/board/env/nv/autoboot1
-rw-r--r--arch/sandbox/board/hostfile.c246
-rw-r--r--arch/sandbox/board/led.c68
-rw-r--r--arch/sandbox/board/power.c99
-rw-r--r--arch/sandbox/board/poweroff.c17
-rw-r--r--arch/sandbox/board/stickypage.S29
-rw-r--r--arch/sandbox/board/watchdog.c77
-rw-r--r--arch/sandbox/configs/hosttools_defconfig7
-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/Makefile11
-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/atomic.h2
-rw-r--r--arch/sandbox/include/asm/barebox.lds.h3
-rw-r--r--arch/sandbox/include/asm/bitsperlong.h11
-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.h43
-rw-r--r--arch/sandbox/include/asm/elf.h3
-rw-r--r--arch/sandbox/include/asm/io.h8
-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.h59
-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/lib/unwind.c2
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/hostfile.h7
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/linux.h38
-rw-r--r--arch/sandbox/os/Makefile27
-rw-r--r--arch/sandbox/os/common.c254
-rw-r--r--arch/sandbox/os/libc_malloc.c56
-rw-r--r--arch/sandbox/os/sdl.c184
-rw-r--r--arch/sandbox/os/setjmp.c180
-rw-r--r--arch/sandbox/os/tap.c5
57 files changed, 1547 insertions, 422 deletions
diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 6ec71a99e5..3419b6e4f6 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -1,22 +1,62 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+source "scripts/Kconfig.include"
+
config SANDBOX
bool
select OFTREE
select GPIOLIB
select ARCH_HAS_UBSAN_SANITIZE_ALL
- select HAVE_ARCH_KASAN
+ select HAVE_ARCH_ASAN
+ 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
+menu "Sandbox specific settings"
+
+config PHYS_ADDR_T_64BIT
bool
- default y
- select GENERIC_FIND_NEXT_BIT
-config SANDBOX_UNWIND
+config CC_IS_64BIT
+ def_bool $(success,$(srctree)/scripts/gcc-64bitptr.sh $(CC))
+
+config CC_HAS_LINUX_I386_SUPPORT
+ def_bool $(cc-option,-m32) && $(ld-option,-m elf_i386)
+
+config 64BIT
bool
- default y
- select ARCH_HAS_STACK_DUMP
- depends on UBSAN || KASAN
+ default n if SANDBOX_LINUX_I386
+ default CC_IS_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 b7470c3330..c2906c0b1c 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -1,6 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
KBUILD_DEFCONFIG := sandbox_defconfig
-CPPFLAGS += -D__SANDBOX__ -fno-strict-aliasing -fvisibility=hidden
+KBUILD_CPPFLAGS += -D__SANDBOX__ -fno-strict-aliasing -fvisibility=hidden
machine-y := sandbox
@@ -11,7 +13,8 @@ lds-y := $(BOARD)/barebox.lds
TEXT_BASE = $(CONFIG_TEXT_BASE)
-CFLAGS += -Dmalloc=barebox_malloc -Dcalloc=barebox_calloc \
+KBUILD_CFLAGS += -Dmalloc=barebox_malloc -Dcalloc=barebox_calloc \
+ -Dmalloc_stats=barebox_malloc_stats -Dmemalign=barebox_memalign \
-Dfree=barebox_free -Drealloc=barebox_realloc \
-Dread=barebox_read -Dwrite=barebox_write \
-Dopen=barebox_open -Dclose=barebox_close \
@@ -23,32 +26,32 @@ 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 \
- -Doptarg=barebox_optarg -Doptind=barebox_optind
+ -Dclosedir=barebox_closedir -Dreadlink=barebox_readlink \
+ -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))
-ifeq ($(KBUILD_SRC),)
-CPPFLAGS += $(patsubst %,-I%include,$(machdirs))
-else
-CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
-endif
+KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs))
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_KASAN),y)
-CPPFLAGS += -fsanitize=address
+ifeq ($(CONFIG_ASAN),y)
+KBUILD_CPPFLAGS += -fsanitize=address
SANITIZER_LIBS += -fsanitize=address
endif
@@ -56,13 +59,25 @@ ifeq ($(CONFIG_UBSAN),y)
SANITIZER_LIBS += -fsanitize=undefined
endif
-cmd_barebox__ = $(CC) -o $@ -Wl,-T,$(BAREBOX_LDS) \
- -Wl,--start-group $(BAREBOX_OBJS) -Wl,--end-group \
- -lrt -lpthread $(SDL_LIBS) $(FTDI1_LIBS) \
+ifeq ($(CONFIG_SANDBOX_LINUX_I386),y)
+KBUILD_CFLAGS += -m32
+KBUILD_LDFLAGS += -m elf_i386
+KBUILD_AFLAGS += -m32
+BAREBOX_LDFLAGS += -m32
+endif
+
+BAREBOX_LDFLAGS += \
+ -Wl,-T,$(BAREBOX_LDS) \
+ -Wl,--whole-archive $(BAREBOX_OBJS) -Wl,--no-whole-archive \
+ -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 ad2bc910c3..c8d1c99897 100644
--- a/arch/sandbox/board/board.c
+++ b/arch/sandbox/board/board.c
@@ -3,9 +3,6 @@
*
* Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
@@ -23,6 +20,7 @@
#include <mach/linux.h>
#include <init.h>
#include <errno.h>
+#include <deep-probe.h>
#include <fb.h>
struct fb_videomode mode = {
@@ -31,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);
@@ -64,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 bdea89f002..1787fb5786 100644
--- a/arch/sandbox/board/clock.c
+++ b/arch/sandbox/board/clock.c
@@ -3,9 +3,6 @@
*
* Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
@@ -31,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 4b251e9087..274ef67aef 100644
--- a/arch/sandbox/board/console.c
+++ b/arch/sandbox/board/console.c
@@ -3,9 +3,6 @@
*
* Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
@@ -24,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 af4a64a9c7..98d2e774b8 100644
--- a/arch/sandbox/board/dtb.c
+++ b/arch/sandbox/board/dtb.c
@@ -2,9 +2,6 @@
* Copyright (c) 2013 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
* Copyright (c) 2015 Marc Kleine-Budde <mkl@pengutronix.de>, Pengutronix
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
@@ -35,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;
+ if (!dtb)
+ dtb = __dtb_sandbox_start;
- ret = of_property_write_u32(root, "#size-cells", 1);
- if (ret)
- return ret;
- }
-
- 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 e5a7580d07..7afad95b6d 100644
--- a/arch/sandbox/board/hostfile.c
+++ b/arch/sandbox/board/hostfile.c
@@ -3,9 +3,6 @@
*
* Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
@@ -19,25 +16,29 @@
#include <common.h>
#include <driver.h>
+#include <block.h>
+#include <disks.h>
#include <malloc.h>
#include <mach/linux.h>
#include <init.h>
#include <errno.h>
#include <linux/err.h>
#include <mach/hostfile.h>
+#include <featctrl.h>
#include <xfuncs.h>
-#include <linux/err.h>
-
struct hf_priv {
- struct cdev cdev;
+ union {
+ struct block_device blk;
+ struct cdev cdev;
+ };
const char *filename;
int fd;
+ struct feature_controller feat;
};
-static ssize_t hf_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags)
+static ssize_t hf_read(struct hf_priv *priv, void *buf, size_t count, loff_t offset, ulong flags)
{
- struct hf_priv *priv= cdev->priv;
int fd = priv->fd;
if (linux_lseek(fd, offset) != offset)
@@ -46,9 +47,8 @@ static ssize_t hf_read(struct cdev *cdev, void *buf, size_t count, loff_t offset
return linux_read(fd, buf, count);
}
-static ssize_t hf_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags)
+static ssize_t hf_write(struct hf_priv *priv, const void *buf, size_t count, loff_t offset, ulong flags)
{
- struct hf_priv *priv = cdev->priv;
int fd = priv->fd;
if (linux_lseek(fd, offset) != offset)
@@ -57,59 +57,135 @@ static ssize_t hf_write(struct cdev *cdev, const void *buf, size_t count, loff_t
return linux_write(fd, buf, count);
}
-static void hf_info(struct device_d *dev)
+static ssize_t hf_cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags)
+{
+ return hf_read(cdev->priv, buf, count, offset, flags);
+}
+
+static ssize_t hf_cdev_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags)
+{
+ return hf_write(cdev->priv, buf, count, offset, flags);
+}
+
+static struct cdev_operations hf_cdev_ops = {
+ .read = hf_cdev_read,
+ .write = hf_cdev_write,
+};
+
+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, 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);
+ return ret > 0 ? 0 : ret;
+}
+
+static struct block_device_ops hf_blk_ops = {
+ .read = hf_blk_read,
+ .write = hf_blk_write,
+};
+
+static void hf_info(struct device *dev)
{
struct hf_priv *priv = dev->priv;
printf("file: %s\n", priv->filename);
}
-static struct cdev_operations hf_fops = {
- .read = hf_read,
- .write = hf_write,
-};
+static int hostfile_feat_check(struct feature_controller *feat, int idx)
+{
+ struct hf_priv *priv = container_of(feat, struct hf_priv, feat);
-static int hf_probe(struct device_d *dev)
+ return priv->fd >= 0 ? FEATCTRL_OKAY : FEATCTRL_GATED;
+}
+
+static int hf_probe(struct device *dev)
{
+ struct device_node *np = dev->of_node;
struct hf_priv *priv = xzalloc(sizeof(*priv));
- struct resource *res;
+ struct cdev *cdev;
+ 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);
+ if (!np)
+ return -ENODEV;
+
+ dev->priv = priv;
+ priv->fd = -1;
- priv->cdev.size = resource_size(res);
+ if (IS_ENABLED(CONFIG_FEATURE_CONTROLLER) &&
+ of_property_read_bool(np, "barebox,feature-controller")) {
+ priv->feat.dev = dev;
+ priv->feat.check = hostfile_feat_check;
- if (!dev->device_node)
- return -ENODEV;
+ err = feature_controller_register(&priv->feat);
+ if (err)
+ return err;
- of_property_read_u32(dev->device_node, "barebox,fd", &priv->fd);
+ is_featctrl = true;
+ }
- err = of_property_read_string(dev->device_node, "barebox,filename",
- &priv->filename);
+
+ err = of_property_read_u64_array(np, "reg", reg, ARRAY_SIZE(reg));
if (err)
return err;
- if (!priv->fd)
- priv->fd = linux_open(priv->filename, true);
+ of_property_read_u32(np, "barebox,fd", &priv->fd);
+
+ err = of_property_read_string(np, "barebox,filename",
+ &priv->filename);
+ if (err)
+ return err;
- priv->cdev.name = dev->device_node->name;
- priv->cdev.dev = dev;
- priv->cdev.ops = &hf_fops;
- priv->cdev.priv = priv;
+ if (priv->fd < 0)
+ return is_featctrl ? 0 : priv->fd;
dev->info = hf_info;
- dev->priv = priv;
- err = devfs_create(&priv->cdev);
- if (err)
- return err;
+ is_blockdev = of_property_read_bool(np, "barebox,blockdev");
- of_parse_partitions(&priv->cdev, dev->device_node);
- of_partitions_register_fixup(&priv->cdev);
+ cdev = is_blockdev ? &priv->blk.cdev : &priv->cdev;
- return 0;
+ 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 = reg[1] / SECTOR_SIZE;
+ priv->blk.type = BLK_TYPE_VIRTUAL;
+
+ err = blockdevice_register(&priv->blk);
+ if (err)
+ return err;
+
+ dev_info(dev, "registered as block device\n");
+ } else {
+ cdev->name = np->name;
+ cdev->dev = dev;
+ cdev->ops = &hf_cdev_ops;
+ cdev->size = reg[1];
+ cdev->priv = priv;
+
+ err = devfs_create(cdev);
+ if (err)
+ return err;
+
+ dev_info(dev, "registered as character device\n");
+ }
+
+ of_parse_partitions(cdev, np);
+ of_partitions_register_fixup(cdev);
+
+ return of_platform_populate(np, NULL, dev);
}
static __maybe_unused struct of_device_id hostfile_dt_ids[] = {
@@ -119,45 +195,111 @@ 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,
};
-coredevice_platform_driver(hf_drv);
+device_platform_driver(hf_drv);
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
- };
+ 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);
+ 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 6b5a6dff15..0000000000
--- a/arch/sandbox/board/poweroff.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <common.h>
-#include <init.h>
-#include <poweroff.h>
-#include <mach/linux.h>
-
-static void sandbox_poweroff(struct poweroff_handler *poweroff)
-{
- linux_exit();
-}
-
-static int poweroff_register_feature(void)
-{
- poweroff_handler_register_fn(sandbox_poweroff);
-
- 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
new file mode 100644
index 0000000000..0b62b648c7
--- /dev/null
+++ b/arch/sandbox/configs/hosttools_defconfig
@@ -0,0 +1,7 @@
+CONFIG_IMD=y
+CONFIG_COMPILE_HOST_TOOLS=y
+CONFIG_ARCH_IMX_USBLOADER=y
+CONFIG_MVEBU_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 6f68388578..79625b103e 100644
--- a/arch/sandbox/dts/Makefile
+++ b/arch/sandbox/dts/Makefile
@@ -1,11 +1,10 @@
-ifeq ($(CONFIG_OFTREE),y)
-dtb-y += \
- sandbox.dtb
-endif
+# 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
-always := $(dtb-y)
-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 fc17bd0788..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 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 38ead821bb..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 = <1>;
- chosen { };
- aliases { };
- memory { device_type = "memory"; reg = <0 0 0>; };
-};
diff --git a/arch/sandbox/include/asm/atomic.h b/arch/sandbox/include/asm/atomic.h
new file mode 100644
index 0000000000..af12dee130
--- /dev/null
+++ b/arch/sandbox/include/asm/atomic.h
@@ -0,0 +1,2 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <asm-generic/atomic.h>
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 00c1fc2625..bf000a04cc 100644
--- a/arch/sandbox/include/asm/bitsperlong.h
+++ b/arch/sandbox/include/asm/bitsperlong.h
@@ -1,10 +1,3 @@
-#ifndef __ASM_BITSPERLONG_H
-#define __ASM_BITSPERLONG_H
+/* SPDX-License-Identifier: GPL-2.0-only */
-#ifdef __x86_64__
-#define BITS_PER_LONG 64
-#else
-#define BITS_PER_LONG 32
-#endif
-
-#endif /* __ASM_BITSPERLONG_H */
+#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 459536779e..cafbb7fe6a 100644
--- a/arch/sandbox/include/asm/dma.h
+++ b/arch/sandbox/include/asm/dma.h
@@ -8,6 +8,47 @@
#ifndef __ASM_DMA_H
#define __ASM_DMA_H
-/* empty*/
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <driver.h>
+
+#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);
+ if (dma_handle)
+ *dma_handle = (dma_addr_t)ret;
+
+ memset(ret, 0, size);
+
+ 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);
+}
+
+#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)
+{
+}
+
+#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)
+{
+}
#endif /* __ASM_DMA_H */
diff --git a/arch/sandbox/include/asm/elf.h b/arch/sandbox/include/asm/elf.h
index 3939336ccb..f08d5930c6 100644
--- a/arch/sandbox/include/asm/elf.h
+++ b/arch/sandbox/include/asm/elf.h
@@ -1,9 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __ASM_SANDBOX_ELF_H__
#define __ASM_SANDBOX_ELF_H__
#if __SIZEOF_POINTER__ == 8
#define ELF_CLASS ELFCLASS64
-#define CONFIG_PHYS_ADDR_T_64BIT
#else
#define ELF_CLASS ELFCLASS32
#endif
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index cb891df5c8..eec279b888 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -1,7 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __ASM_SANDBOX_IO_H
#define __ASM_SANDBOX_IO_H
-#define IO_SPACE_LIMIT 0
+#define IO_SPACE_LIMIT 0xffff
+/* pacify static analyzers */
+#define PCI_IOBASE ((void __iomem *)__pci_iobase)
+
+extern unsigned char __pci_iobase[IO_SPACE_LIMIT];
#include <asm-generic/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 8426de4cc2..e29dde377c 100644
--- a/arch/sandbox/include/asm/types.h
+++ b/arch/sandbox/include/asm/types.h
@@ -1,59 +1,8 @@
-#ifndef __ASM_I386_TYPES_H
-#define __ASM_I386_TYPES_H
+/* SPDX-License-Identifier: GPL-2.0-only */
-#ifdef __x86_64__
-/*
- * This is used in dlmalloc. On X86_64 we need it to be
- * 64 bit
- */
-#define INTERNAL_SIZE_T unsigned long
+#ifndef __ASM_SANDBOX_TYPES_H
+#define __ASM_SANDBOX_TYPES_H
-/*
- * This is a Kconfig variable in the Kernel, but we want to detect
- * this during compile time, so we set it here.
- */
-#define CONFIG_PHYS_ADDR_T_64BIT
-
-#endif
-
-/*
- * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
- * header files exported to user space
- */
-
-typedef __signed__ char __s8;
-typedef unsigned char __u8;
-
-typedef __signed__ short __s16;
-typedef unsigned short __u16;
-
-typedef __signed__ int __s32;
-typedef unsigned int __u32;
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
-#endif
-
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-
-typedef signed char s8;
-typedef unsigned char u8;
-
-typedef signed short s16;
-typedef unsigned short u16;
-
-typedef signed int s32;
-typedef unsigned int u32;
-
-typedef signed long long s64;
-typedef unsigned long long u64;
-
-#include <asm/bitsperlong.h>
-
-#endif /* __KERNEL__ */
+#include <asm-generic/int-ll64.h>
#endif
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/lib/unwind.c b/arch/sandbox/lib/unwind.c
index 15a2798cc4..f46365ac2b 100644
--- a/arch/sandbox/lib/unwind.c
+++ b/arch/sandbox/lib/unwind.c
@@ -7,5 +7,5 @@ void __sanitizer_print_stack_trace(void);
void dump_stack(void)
{
- __sanitizer_print_stack_trace();
+ __sanitizer_print_stack_trace();
}
diff --git a/arch/sandbox/mach-sandbox/include/mach/hostfile.h b/arch/sandbox/mach-sandbox/include/mach/hostfile.h
index 54f690be5f..b461d5ebc3 100644
--- a/arch/sandbox/mach-sandbox/include/mach/hostfile.h
+++ b/arch/sandbox/mach-sandbox/include/mach/hostfile.h
@@ -1,12 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef __ASM_ARCH_HOSTFILE_H
#define __ASM_ARCH_HOSTFILE_H
struct hf_info {
int fd;
unsigned long long base;
- size_t size;
+ unsigned long long size;
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 9759a376ec..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,15 +15,21 @@ 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);
+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);
@@ -31,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 75baa34a83..055ce1a316 100644
--- a/arch/sandbox/os/Makefile
+++ b/arch/sandbox/os/Makefile
@@ -1,22 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
machine-y := sandbox
machdirs := $(patsubst %,arch/sandbox/mach-%/,$(machine-y))
-ifeq ($(KBUILD_SRC),)
-CPPFLAGS := $(patsubst %,-I%include,$(machdirs))
-else
-CPPFLAGS = $(patsubst %,-I$(srctree)/%include,$(machdirs))
-endif
+KBUILD_CPPFLAGS = $(patsubst %,-I$(srctree)/%include,$(machdirs))
+
+KBUILD_CPPFLAGS += -DCONFIG_MALLOC_SIZE=$(CONFIG_MALLOC_SIZE) -D_FILE_OFFSET_BITS=64 \
+ -DCONFIG_STACK_SIZE=$(CONFIG_STACK_SIZE)
-CPPFLAGS += -DCONFIG_MALLOC_SIZE=$(CONFIG_MALLOC_SIZE)
+KBUILD_CFLAGS := -Wall
-CFLAGS := -Wall
NOSTDINC_FLAGS :=
-obj-y = common.o tap.o
+ifeq ($(CONFIG_SANDBOX_LINUX_I386),y)
+KBUILD_CFLAGS += -m32
+endif
+
+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 3f9cc70770..3446074f99 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -4,9 +4,6 @@
*
* Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
@@ -22,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>
@@ -41,12 +39,17 @@
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
+#include <sys/time.h>
/*
* ...except the ones needed to connect with barebox
*/
#include <mach/linux.h>
#include <mach/hostfile.h>
+#define DELETED_OFFSET (sizeof(" (deleted)") - 1)
+
+void __sanitizer_set_death_callback(void (*callback)(void));
+
int sdl_xres;
int sdl_yres;
@@ -72,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 = {
@@ -119,13 +131,58 @@ 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];
+ ssize_t ret;
+
+ cookmode();
+
+ /* we must follow the symlink, so we can exec an updated executable */
+ 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");
+ buf[ret - DELETED_OFFSET] = '\0';
+ execv(buf, saved_argv);
+ }
+ }
+
+ printf("exec(%s) failed: %d\n", buf, errno);
+ /* falls through to generic hang() */
+}
+
+void linux_hang(void)
+{
+ prepare_exit();
+ /* falls through to generic hang() */
+}
+
int linux_open(const char *filename, int readwrite)
{
- return open(filename, readwrite ? O_RDWR : O_RDONLY);
+ return open(filename, (readwrite ? O_RDWR : O_RDONLY) | O_CLOEXEC);
}
int linux_read(int fd, void *buf, size_t count)
@@ -184,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);
}
@@ -210,45 +267,147 @@ 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);
-static int add_image(char *str, char *devname_template, int *devname_number)
+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));
- char *filename, *devname;
+ struct hf_info *hf = calloc(1, sizeof(struct hf_info));
+ char *str, *filename, *devname;
char tmp[16];
- int readonly = 0;
- struct stat s;
char *opt;
- int fd, ret;
+ int ret;
if (!hf)
return -1;
- filename = strtok(str, ",");
- while ((opt = strtok(NULL, ","))) {
+ str = strdup(_str);
+
+ filename = strsep_unescaped(&str, ",");
+ while ((opt = strsep_unescaped(&str, ","))) {
if (!strcmp(opt, "ro"))
- readonly = 1;
+ hf->is_readonly = 1;
+ if (!strcmp(opt, "cdev"))
+ hf->is_cdev = 1;
+ if (!strcmp(opt, "blkdev"))
+ hf->is_blockdev = 1;
}
/* parses: "devname=filename" */
- devname = strtok(filename, "=");
- filename = strtok(NULL, "=");
+ devname = strsep_unescaped(&filename, "=");
+ filename = strsep_unescaped(&filename, "=");
if (!filename) {
filename = devname;
snprintf(tmp, sizeof(tmp),
devname_template, (*devname_number)++);
- devname = strdup(tmp);
+ devname = tmp;
}
- printf("add %s backed by file %s%s\n", devname,
- filename, readonly ? "(ro)" : "");
-
- fd = open(filename, readonly ? O_RDONLY : O_RDWR);
- hf->fd = fd;
hf->filename = filename;
+ 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;
@@ -259,30 +418,41 @@ static int add_image(char *str, char *devname_template, int *devname_number)
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 (!hf->is_cdev)
+ hf->is_blockdev = 1;
+ }
+ if (hf->size <= SIZE_MAX) {
+ hf->base = (unsigned long)mmap(NULL, hf->size,
+ PROT_READ | (hf->is_readonly ? 0 : PROT_WRITE),
+ MAP_SHARED, fd, 0);
+
+ 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 (hf->is_blockdev && hf->size % 512 != 0) {
+ printf("warning: registering %s as block device failed: invalid block size\n",
+ hf->filename);
+ return -EINVAL;
}
- hf->base = (unsigned long)mmap(NULL, hf->size,
- PROT_READ | (readonly ? 0 : PROT_WRITE),
- MAP_SHARED, fd, 0);
- if ((void *)hf->base == MAP_FAILED)
- printf("warning: mmapping %s failed: %s\n", filename, strerror(errno));
- 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;
}
@@ -292,7 +462,7 @@ static int add_dtb(const char *file)
void *dtb = NULL;
int fd;
- fd = open(file, O_RDONLY);
+ fd = open(file, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
perror("open");
goto err_out;
@@ -348,6 +518,10 @@ int main(int argc, char *argv[])
int fdno = 0, envno = 0, option_index = 0;
char *aux;
+#ifdef CONFIG_ASAN
+ __sanitizer_set_death_callback(prepare_exit);
+#endif
+
while (1) {
option_index = 0;
opt = getopt_long(argc, argv, optstring,
@@ -385,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");
@@ -419,7 +595,7 @@ int main(int argc, char *argv[])
exit(1);
break;
case 'O':
- fd = open(optarg, O_WRONLY);
+ fd = open(optarg, O_WRONLY | O_CLOEXEC);
if (fd < 0) {
perror("open");
exit(1);
@@ -428,7 +604,7 @@ int main(int argc, char *argv[])
barebox_register_console(-1, fd);
break;
case 'I':
- fd = open(optarg, O_RDWR);
+ fd = open(optarg, O_RDWR | O_CLOEXEC);
if (fd < 0) {
perror("open");
exit(1);
@@ -444,7 +620,7 @@ int main(int argc, char *argv[])
}
/* open stdout file */
- fd = open(aux + 1, O_WRONLY);
+ fd = open(aux + 1, O_WRONLY | O_CLOEXEC);
if (fd < 0) {
perror("open stdout");
exit(1);
@@ -452,7 +628,7 @@ int main(int argc, char *argv[])
/* open stdin file */
aux = strndup(optarg, aux - optarg);
- fd2 = open(aux, O_RDWR);
+ fd2 = open(aux, O_RDWR | O_CLOEXEC);
if (fd2 < 0) {
perror("open stdin");
exit(1);
diff --git a/arch/sandbox/os/libc_malloc.c b/arch/sandbox/os/libc_malloc.c
new file mode 100644
index 0000000000..975c41b0ec
--- /dev/null
+++ b/arch/sandbox/os/libc_malloc.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Ahmad Fatoum <a.fatoum@pengutronix.de>
+ */
+
+#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)
+{
+ void *mem = memalign(alignment, bytes);
+ if (!mem)
+ barebox_errno = BAREBOX_ENOMEM;
+
+ return mem;
+}
+
+void *barebox_malloc(size_t size)
+{
+
+ void *mem = malloc(size);
+ if (!mem)
+ barebox_errno = BAREBOX_ENOMEM;
+
+ return mem;
+}
+
+void barebox_free(void *ptr)
+{
+ free(ptr);
+}
+
+void *barebox_realloc(void *ptr, size_t size)
+{
+ void *mem = realloc(ptr, size);
+ if (!mem)
+ barebox_errno = BAREBOX_ENOMEM;
+
+ return mem;
+}
+
+void *barebox_calloc(size_t n, size_t 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);
+}
diff --git a/arch/sandbox/os/tap.c b/arch/sandbox/os/tap.c
index 3a29a4be64..83b97ffd49 100644
--- a/arch/sandbox/os/tap.c
+++ b/arch/sandbox/os/tap.c
@@ -3,9 +3,6 @@
*
* Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
@@ -33,7 +30,7 @@ int tap_alloc(const char *dev)
struct ifreq ifr;
int fd, err;
- if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
+ if ((fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC)) < 0) {
perror("could not open /dev/net/tun");
return -1;
}