diff options
Diffstat (limited to 'arch/sandbox')
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; } |