summaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
Diffstat (limited to 'commands')
-rw-r--r--commands/Kconfig331
-rw-r--r--commands/Makefile24
-rw-r--r--commands/beep.c99
-rw-r--r--commands/boot.c36
-rw-r--r--commands/bootm.c1
-rw-r--r--commands/bthread.c234
-rw-r--r--commands/cat.c2
-rw-r--r--commands/clk.c64
-rw-r--r--commands/crc.c14
-rw-r--r--commands/detect.c2
-rw-r--r--commands/devinfo.c27
-rw-r--r--commands/devlookup.c77
-rw-r--r--commands/devunbind.c83
-rw-r--r--commands/dfu.c31
-rw-r--r--commands/dhrystone.c2
-rw-r--r--commands/digest.c2
-rw-r--r--commands/dmesg.c97
-rw-r--r--commands/drvinfo.c12
-rw-r--r--commands/echo.c55
-rw-r--r--commands/edit.c117
-rw-r--r--commands/efi_handle_dump.c144
-rw-r--r--commands/ethlog.c94
-rw-r--r--commands/export.c4
-rw-r--r--commands/fbtest.c7
-rw-r--r--commands/filetype.c6
-rw-r--r--commands/findmnt.c108
-rw-r--r--commands/flash.c8
-rw-r--r--commands/global.c9
-rw-r--r--commands/go.c59
-rw-r--r--commands/gpio.c51
-rw-r--r--commands/hab.c8
-rw-r--r--commands/hashsum.c12
-rw-r--r--commands/hwclock.c14
-rw-r--r--commands/hwmon.c2
-rw-r--r--commands/i2c.c10
-rw-r--r--commands/imd.c1
-rw-r--r--commands/insmod.c2
-rw-r--r--commands/internal.h2
-rw-r--r--commands/iomemport.c9
-rw-r--r--commands/kallsyms.c50
-rw-r--r--commands/keystore.c4
-rw-r--r--commands/linux16.c331
-rw-r--r--commands/loadb.c6
-rw-r--r--commands/loadenv.c3
-rw-r--r--commands/loads.c4
-rw-r--r--commands/loadxy.c2
-rw-r--r--commands/ls.c13
-rw-r--r--commands/lsmod.c2
-rw-r--r--commands/magicvar.c2
-rw-r--r--commands/md.c10
-rw-r--r--commands/memcmp.c2
-rw-r--r--commands/memcpy.c6
-rw-r--r--commands/memset.c6
-rw-r--r--commands/memtest.c5
-rw-r--r--commands/memtester/Makefile3
-rw-r--r--commands/memtester/memtester.c274
-rw-r--r--commands/memtester/memtester.h21
-rw-r--r--commands/memtester/sizes.h35
-rw-r--r--commands/memtester/tests.c495
-rw-r--r--commands/memtester/tests.h36
-rw-r--r--commands/memtester/types.h35
-rw-r--r--commands/menu.c107
-rw-r--r--commands/miitool.c2
-rw-r--r--commands/mipi_dbi.c104
-rw-r--r--commands/mkdir.c2
-rw-r--r--commands/mm.c12
-rw-r--r--commands/mmc.c124
-rw-r--r--commands/mmc_extcsd.c2
-rw-r--r--commands/mount.c6
-rw-r--r--commands/mw.c11
-rw-r--r--commands/nand-bitflip.c23
-rw-r--r--commands/nand.c7
-rw-r--r--commands/nandtest.c14
-rw-r--r--commands/nv.c7
-rw-r--r--commands/nvmem.c24
-rw-r--r--commands/of_compatible.c121
-rw-r--r--commands/of_diff.c71
-rw-r--r--commands/of_display_timings.c30
-rw-r--r--commands/of_dump.c78
-rw-r--r--commands/of_fixup.c93
-rw-r--r--commands/of_overlay.c46
-rw-r--r--commands/of_property.c66
-rw-r--r--commands/oftree.c12
-rw-r--r--commands/parted.c374
-rw-r--r--commands/partition.c1
-rw-r--r--commands/pm_domain.c18
-rw-r--r--commands/pwm.c212
-rw-r--r--commands/readf.c2
-rw-r--r--commands/readline.c16
-rw-r--r--commands/readlink.c4
-rw-r--r--commands/regulator.c43
-rw-r--r--commands/reset.c16
-rw-r--r--commands/rm.c16
-rw-r--r--commands/rmdir.c4
-rw-r--r--commands/selftest.c88
-rw-r--r--commands/setenv.c18
-rw-r--r--commands/smc.c14
-rw-r--r--commands/spd_decode.c3
-rw-r--r--commands/splash.c7
-rw-r--r--commands/stacksmash.c58
-rw-r--r--commands/stat.c74
-rw-r--r--commands/state.c3
-rw-r--r--commands/test.c101
-rw-r--r--commands/tftp.c22
-rw-r--r--commands/time.c46
-rw-r--r--commands/trigger.c5
-rw-r--r--commands/tutorial.c157
-rw-r--r--commands/ubi.c4
-rw-r--r--commands/ubsan.c2
-rw-r--r--commands/uimage.c8
-rw-r--r--commands/uptime.c82
-rw-r--r--commands/usb.c2
-rw-r--r--commands/usbgadget.c38
-rw-r--r--commands/usbserial.c2
-rw-r--r--commands/version.c2
-rw-r--r--commands/wd.c7
116 files changed, 4658 insertions, 958 deletions
diff --git a/commands/Kconfig b/commands/Kconfig
index 9114d3cb31..8d0816c4d0 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
config REGINFO
bool
@@ -21,6 +23,13 @@ menu "Commands"
menu "Information"
+config CMD_TUTORIAL
+ bool "barebox tutorial (next command)"
+ default SANDBOX
+ help
+ Help navigate a barebox tutorial available
+ in /env/data/tutorial/
+
config CMD_AT91CLK
bool "at91clk"
default y
@@ -44,6 +53,21 @@ config CMD_ARM_CPUINFO
D-cache: 8192 bytes (linelen = 8)
Control register: M C W P D L I V RR DT IT U XP
+config CMD_RISCV_CPUINFO
+ bool "cpuinfo command"
+ default y
+ depends on RISCV
+ help
+ Show info about RISC-V CPU
+
+config CMD_BOOTROM
+ bool "bootrom command"
+ depends on ARCH_IMX8M
+ help
+ Interact with bootrom on i.MX8M
+
+ bootrom [-la]
+
config CMD_DEVINFO
tristate
default y
@@ -59,6 +83,31 @@ config CMD_DEVINFO
If called with a device path being the argument, devinfo shows more
default information about this device and its parameters.
+config CMD_DEVLOOKUP
+ tristate
+ prompt "devlookup"
+ help
+ Look up device behind device file and its parameters
+
+ devlookup [-v VAR] /dev/DEVICE [parameter]
+
+ Detects the device behind a device file and outputs it,
+ unless a second argument is given. In that case the device
+ parameter with that name is looked up. Specifying -v VARIABLE
+ will write output to VARIABLE instead of printing it.
+
+config CMD_DEVUNBIND
+ tristate
+ prompt "devunbind"
+ help
+ Debugging aid to unbind device(s) from driver at runtime
+
+ devunbind [-fl] DEVICES..
+
+ Options:
+ -f unbind driver and force removal of device and children
+ -l list remove callbacks in shutdown order
+
config CMD_DMESG
tristate
prompt "dmesg"
@@ -74,6 +123,14 @@ config CMD_DRVINFO
help
List compiled-in device drivers and the devices they support.
+config CMD_EFI_HANDLE_DUMP
+ tristate
+ default y
+ depends on EFI
+ prompt "efi_handle_dump"
+ help
+ Dump information on EFI handles
+
config CMD_HELP
tristate
default y
@@ -152,12 +209,13 @@ config CMD_MEMINFO
config CMD_ARM_MMUINFO
bool "mmuinfo command"
- depends on CPU_V7
+ depends on CPU_V7 || CPU_V8
+ select MMUINFO
help
Say yes here to get a mmuinfo command to show some
- MMU and cache information using the cp15 registers.
+ MMU and cache information using the cp15/model-specific registers.
- Example:
+ Example for ARMv7:
PAR result for 0x00110000:
privileged read: 0x00110090
@@ -199,6 +257,21 @@ config CMD_REGULATOR
the regulator command lists the currently registered regulators and
their current state.
+config CMD_PM_DOMAIN
+ bool
+ depends on PM_GENERIC_DOMAINS
+ prompt "pm_domain command"
+ help
+ The pm_domain command lists the currently registered power domains and
+ their current state.
+
+config CMD_NVMEM
+ bool
+ depends on NVMEM
+ prompt "nvmem command"
+ help
+ the nvmem command lists the currently registered nvmem devices.
+
config CMD_LSPCI
bool
depends on PCI
@@ -253,6 +326,15 @@ config CMD_POLLER
is_timeout() or one of the various delay functions. The poller command prints
informations about registered pollers.
+config CMD_BTHREAD
+ tristate
+ prompt "bthread"
+ depends on BTHREAD
+ help
+ barebox threads are cooperatively-scheduled (green) threads that are running in
+ the background whenever code executes is_timeout() or one of the various delay
+ functions. The bthread command prints informations about registered bthreads.
+
config CMD_SLICE
tristate
prompt "slice"
@@ -261,6 +343,15 @@ config CMD_SLICE
command can be used to print informations about slices and also to manipulate
them on the command line for debugging purposes.
+config CMD_FCB
+ depends on BAREBOX_UPDATE_IMX_NAND_FCB
+ tristate
+ prompt "fcb"
+ help
+ Several i.MX SoCs booting from NAND flash need a so called Flash Control Block
+ at the beginning of the NAND device. The fcb command prints information about
+ the FCB.
+
# end Information commands
endmenu
@@ -285,9 +376,9 @@ config CMD_AT91_BOOT_TEST
config CMD_BOOT_ORDER
tristate
depends on ARCH_OMAP4
- prompt "boot_order"
+ prompt "OMAP boot_order"
help
- Set warm boot order (the next boot device on a warm reset).
+ Set OMAP warm boot order (the next boot device on a warm reset).
Usage: boot_order DEVICE...
@@ -310,6 +401,7 @@ config CMD_BOOT
BOOTSRC can be:
- a filename under /env/boot/
- a full path to a boot script
+ - a full path to a bootspec entry
- a device name
- a partition name under /dev/
- a full path to a directory which
@@ -371,38 +463,21 @@ config CMD_BOOTZ
Usage: bootz FILE
-config CMD_LINUX16
- tristate
- depends on X86 && !X86_EFI
- default y if X86
- prompt "linux16"
- help
- Usage: linux16 [-v VESAMODE] FILE
-
- Load kernel from FILE and boot on x86 in real-mode.
-
- Only kernel images in bzImage format are supported by now.
-
- For the video mode refer the Linux kernel documentation
- 'Documentation/fb/vesafb.txt' for correct VESA mode numbers. Use 'ask'
- instead of a number to make Linux prompt for options.
-
- Options:
- -v VESAMODE set VESAMODE
-
-
config CMD_GO
tristate
prompt "go"
help
Start application at address or file
- Usage: go ADDR [ARG...]
+ Usage: go [-si] ADDR [ARG...]
Start application at ADDR passing ARG as arguments.
If addr does not start with a digit it is interpreted as a filename
in which case the file is memmapped and executed
+ Options:
+ -s pass all arguments as strings referenced by argc, argv arguments (default)
+ -i pass up to four integer arguments using default calling convention
config CMD_LOADB
depends on CONSOLE_FULL
@@ -498,6 +573,23 @@ config CMD_UIMAGE
-e OUTFILE extract image to OUTFILE
-n NO use image number NO in multifile image
+config CMD_BOOTCHOOSER
+ tristate
+ depends on BOOTCHOOSER
+ prompt "bootchooser control utility"
+ help
+ Control misc behaviour of the bootchooser
+
+ Options:
+ -a <n|default> [TARGETS]
+ set remaining attempts of given targets to 'n' or the default attempts
+ -p <n|default> [TARGETS]
+ set priority of given targets to 'n' or the default priority
+ -i
+ Show information about the bootchooser
+ -s
+ Mark the last boot successful
+
# end Boot commands
endmenu
@@ -571,6 +663,42 @@ config CMD_MOUNT
-o OPTIONS set file system OPTIONS
-v verbose
+config CMD_FINDMNT
+ tristate
+ prompt "findmnt"
+ help
+ Find a file system
+
+ Usage: findmnt [ DEVICE | -T FILE ]
+
+ findmnt will list all mounted filesystems or search
+ for a filesystem when given the mountpoint or the
+ source device as an argument
+
+ Options:
+ -T mount target file path
+
+config CMD_PARTED
+ tristate
+ depends on PARTITION
+ select PARTITION_MANIPULATION
+ prompt "parted"
+ help
+ parted - edit partition tables
+
+ Usage: parted <device> [command [options...]...]
+
+ parted is a partition manipulation program with a behaviour similar to
+ GNU Parted
+
+ commands:
+ print print partitions
+ mklabel <type> create a new partition table
+ rm <num> remove a partition
+ mkpart <name> <fstype> <start> <end> create a new partition
+ unit <unit> change display/input units
+ refresh refresh a partition table
+
config CMD_UBI
tristate
default y if MTD_UBI
@@ -729,7 +857,7 @@ config CMD_SAVEENV
config CMD_SETENV
tristate
default y
- depends on !CONFIG_SHELL_NONE
+ depends on !SHELL_NONE
prompt "setenv"
help
Set environment variable
@@ -884,6 +1012,22 @@ config CMD_LS
-C column format (opposite of long format)
-R list subdirectories recursively
+config CMD_STAT
+ tristate
+ prompt "stat"
+ select PRINTF_UUID
+ help
+ Display file status
+
+ Usage: stat [-LcC] [FILEDIR...]
+
+ Display status information about the specified files or directories.
+
+ Options:
+ -L follow symlinks
+ -c DIR lookup file relative to directory DIR
+ -C DIR change root to DIR before file lookup
+
config CMD_MD5SUM
tristate
select COMPILE_HASH
@@ -933,10 +1077,11 @@ config CMD_RM
help
Remove files
- Usage: rm [-r] FILES...
+ Usage: rm [-rf] FILES...
Options:
-r remove directories and their contents recursively
+ -f ignore nonexistent files
config CMD_RMDIR
tristate
@@ -1113,15 +1258,17 @@ config CMD_SLEEP
config CMD_TEST
tristate
depends on SHELL_HUSH
+ select FNMATCH
default y
prompt "test"
help
- Minimal test command like in /bin/sh
+ Minimal test command like in /bin/sh with support for bash-style
+ [[ expression ]] tests as well.
Usage: test [EXPR]
Options:
- !, =, !=, -eq, -ne, -ge, -gt, -le, -lt, -o, -a, -z, -n, -d, -e,
+ !, =, ==, !=, -eq, -ne, -ge, -gt, -le, -lt, -o, -a, -z, -n, -d, -e,
-f, -L; see 'man test' on your PC for more information.
config CMD_TRUE
@@ -1231,6 +1378,14 @@ config CMD_IP_ROUTE_GET
be shown on the command line or alternatively a variable is set to
the result.
+config CMD_ETHLOG
+ tristate
+ prompt "ethlog"
+ help
+ log ethernet traffic.
+
+ Usage: ethlog [-r] [DEVICENAME]
+
# end Network commands
endmenu
@@ -1278,9 +1433,10 @@ config CMD_ECHO_E
config CMD_EDIT
tristate
+ depends on CONSOLE_FULL || CONSOLE_SIMPLE
prompt "edit"
help
- A small fill-screen editor.
+ A small full-screen editor.
Usage: edit FILE
@@ -1457,6 +1613,13 @@ config CMD_FBTEST
Framebuffer test command that allows to produce a number of
test patterns on a screen.
+config CMD_BEEP
+ def_bool y
+ depends on SOUND
+ prompt "Beep"
+ help
+ Play beeps. Accepts same format as GRUB play
+
config CMD_READLINE
tristate
prompt "readline"
@@ -1597,6 +1760,7 @@ config CMD_MEMSET
config CMD_MEMTEST
tristate
+ select MEMTEST
prompt "memtest"
help
The memtest command can test the registered barebox memory.
@@ -1611,6 +1775,14 @@ config CMD_MEMTEST
-i ITERATIONS perform number of iterations (default 1, 0 is endless)
-b perform only a test on bus lines
+config CMD_MEMTESTER
+ tristate
+ prompt "memtester"
+ help
+ Utility for testing the memory subsystem.
+
+ Homepage: http://pyropus.ca/software/memtester/
+
config CMD_MM
tristate
select DEV_MEM
@@ -1809,6 +1981,18 @@ config CMD_I2C
-w use word (16 bit) wide access
-v verbose
+config CMD_PWM
+ bool
+ depends on PWM
+ prompt "PWM commands: pwm"
+ help
+ pwm - set or show pwm state
+
+ Usage: pwm [dDPfwisv]
+
+ Controls the pwm values such as period and duty cycle, or shows
+ the current values.
+
config CMD_LED
bool
depends on LED
@@ -1832,18 +2016,19 @@ config CMD_NAND
help
NAND flash handling
- Usage: nand [-adb] NANDDEV
+ Usage: nand [-adbgi] NANDDEV
Options:
-a register a bad block aware device ontop of a normal NAND device
-d deregister a bad block aware device
-b OFFS mark block at OFFSet as bad
+ -g OFFS mark block at OFFSet as good
+ -i info. Show information about bad blocks
config CMD_NANDTEST
tristate
depends on NAND
depends on PARTITION
- depends on NAND_ECC_HW || NAND_ECC_SOFT
prompt "nandtest"
help
NAND flash memory test
@@ -1914,6 +2099,21 @@ config CMD_SPI
-w BIT bits per word (default 8)
-v verbose
+config CMD_MIPI_DBI
+ bool
+ depends on DRIVER_VIDEO_MIPI_DBI && SPI
+ select PRINTF_HEXSTR
+ prompt "mipi_dbi command"
+ help
+ write/read from MIPI DBI SPI device
+
+ Usage: mipi_dbi [-wld] [REG] [DATA...]
+
+ Options:
+ -l list all MIPI DBI devices
+ -d DEVICE select specific device (default is first registered)
+ -w issue write command
+
config CMD_LED_TRIGGER
bool
depends on LED_TRIGGERS
@@ -2024,6 +2224,15 @@ config CMD_FIRMWARELOAD
Provides the "firmwareload" command which deals with devices which need
firmware to work. It is also used to upload firmware to FPGA devices.
+config CMD_KALLSYMS
+ depends on KALLSYMS
+ bool
+ prompt "kallsyms"
+ help
+ query kallsyms table
+
+ Usage: kallsyns [SYMBOL | ADDRESS]
+
config CMD_KEYSTORE
depends on CRYPTO_KEYSTORE
bool
@@ -2033,7 +2242,7 @@ config CMD_KEYSTORE
config CMD_LINUX_EXEC
bool "linux exec"
- depends on LINUX
+ depends on SANDBOX
help
Execute a command on the host
@@ -2054,6 +2263,21 @@ config CMD_LSMOD
help
List loaded barebox modules.
+config CMD_OF_COMPATIBLE
+ tristate
+ select OFTREE
+ prompt "of_compatible"
+ help
+ Check DT node's compatible
+
+ Usage: [-fFnk] [COMPAT]
+
+ Options:
+ -f dtb work on dtb instead of internal devicetree
+ -F apply fixups on devicetree before compare
+ -n node node path or alias to compare its compatible (default is /)
+ -k compare $global.of.kernel.add_machine_compatible as well
+
config CMD_OF_DIFF
tristate
select OFTREE
@@ -2121,6 +2345,20 @@ config CMD_OF_DISPLAY_TIMINGS
-s path select display-timings and register oftree fixup
-f dtb work on dtb. Has no effect on -s option
+config CMD_OF_FIXUP
+ tristate
+ select OFTREE
+ depends on KALLSYMS
+ prompt "of_fixup"
+ help
+ List and enable/disable fixups
+
+ Usage: of_fixup [-de] [fixups...]
+
+ Options:
+ -d disable fixup
+ -e re-enable fixup
+
config CMD_OF_FIXUP_STATUS
tristate
select OFTREE
@@ -2174,16 +2412,24 @@ config CMD_TIME
Note: This command depends on COMMAND being interruptible,
otherwise the timer may overrun resulting in incorrect results
+config CMD_UPTIME
+ bool "uptime"
+ help
+ uptime - Tell how long barebox has been running
+
+ Usage: uptime [-n]
+
+ This command formats the number of elapsed nanoseconds
+ as measured with the current clocksource.
+
+ Options:
+ -n output elapsed time in nanoseconds
+
config CMD_STATE
tristate
depends on STATE
prompt "state"
-config CMD_BOOTCHOOSER
- tristate
- depends on BOOTCHOOSER
- prompt "bootchooser"
-
config CMD_DHRYSTONE
bool
prompt "dhrystone"
@@ -2210,6 +2456,13 @@ config CMD_UBSAN
This is a test command for the undefined behavior sanitizer.
It triggers various undefined behavior, and detect it.
+config CMD_STACKSMASH
+ tristate "stacksmash"
+ depends on STACKPROTECTOR || STACK_GUARD_PAGE || COMPILE_TEST
+ help
+ This commands trashes the stack to test stackprotector and
+ guard page. This command does not return.
+
# end Miscellaneous commands
endmenu
diff --git a/commands/Makefile b/commands/Makefile
index 6cc4997cc5..30e1f8403e 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -1,9 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-$(CONFIG_STDDEV) += stddev.o
obj-$(CONFIG_CMD_DIGEST) += digest.o
obj-$(CONFIG_COMPILE_HASH) += hashsum.o
obj-$(CONFIG_CMD_BOOTM) += bootm.o
obj-$(CONFIG_CMD_UIMAGE) += uimage.o
-obj-$(CONFIG_CMD_LINUX16) += linux16.o
obj-$(CONFIG_CMD_LOADB) += loadb.o
obj-$(CONFIG_CMD_LOADY) += loadxy.o
obj-$(CONFIG_CMD_LOADS) += loads.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_CMD_MEMCMP) += memcmp.o
obj-$(CONFIG_CMD_MEMCPY) += memcpy.o
obj-$(CONFIG_CMD_MEMSET) += memset.o
obj-$(CONFIG_CMD_EDIT) += edit.o
+obj-$(CONFIG_CMD_ETHLOG) += ethlog.o
obj-$(CONFIG_CMD_EXEC) += exec.o
obj-$(CONFIG_CMD_SLEEP) += sleep.o
obj-$(CONFIG_CMD_SMC) += smc.o
@@ -24,6 +26,7 @@ obj-$(CONFIG_CMD_POWEROFF) += poweroff.o
obj-$(CONFIG_CMD_GO) += go.o
obj-$(CONFIG_CMD_PARTITION) += partition.o
obj-$(CONFIG_CMD_LS) += ls.o
+obj-$(CONFIG_CMD_STAT) += stat.o
obj-$(CONFIG_CMD_CD) += cd.o
obj-$(CONFIG_CMD_PWD) += pwd.o
obj-$(CONFIG_CMD_MKDIR) += mkdir.o
@@ -33,6 +36,7 @@ obj-$(CONFIG_CMD_RM) += rm.o
obj-$(CONFIG_CMD_CAT) += cat.o
obj-$(CONFIG_CMD_MOUNT) += mount.o
obj-$(CONFIG_CMD_UMOUNT) += umount.o
+obj-$(CONFIG_CMD_FINDMNT) += findmnt.o
obj-$(CONFIG_CMD_REGINFO) += reginfo.o
obj-$(CONFIG_CMD_CRC) += crc.o
obj-$(CONFIG_CMD_CLEAR) += clear.o
@@ -48,7 +52,9 @@ obj-$(CONFIG_CMD_SAVEENV) += saveenv.o
obj-$(CONFIG_CMD_LOADENV) += loadenv.o
obj-$(CONFIG_CMD_NAND) += nand.o
obj-$(CONFIG_CMD_NANDTEST) += nandtest.o
+obj-$(CONFIG_CMD_NVMEM) += nvmem.o
obj-$(CONFIG_CMD_MEMTEST) += memtest.o
+obj-$(CONFIG_CMD_MEMTESTER) += memtester/
obj-$(CONFIG_CMD_TRUE) += true.o
obj-$(CONFIG_CMD_FALSE) += false.o
obj-$(CONFIG_CMD_VERSION) += version.o
@@ -57,12 +63,15 @@ obj-$(CONFIG_CMD_LSMOD) += lsmod.o
obj-$(CONFIG_CMD_INSMOD) += insmod.o
obj-$(CONFIG_CMD_SPLASH) += splash.o
obj-$(CONFIG_CMD_FBTEST) += fbtest.o
+obj-$(CONFIG_CMD_BEEP) += beep.o
obj-$(CONFIG_USB_GADGET_DFU) += dfu.o
obj-$(CONFIG_USB_GADGET_SERIAL) += usbserial.o
obj-$(CONFIG_CMD_GPIO) += gpio.o
obj-$(CONFIG_CMD_UNCOMPRESS) += uncompress.o
obj-$(CONFIG_CMD_I2C) += i2c.o
obj-$(CONFIG_CMD_SPI) += spi.o
+obj-$(CONFIG_CMD_PWM) += pwm.o
+obj-$(CONFIG_CMD_MIPI_DBI) += mipi_dbi.o
obj-$(CONFIG_CMD_UBI) += ubi.o
obj-$(CONFIG_CMD_UBIFORMAT) += ubiformat.o
obj-$(CONFIG_CMD_MENU) += menu.o
@@ -73,12 +82,15 @@ obj-$(CONFIG_CMD_WD) += wd.o
obj-$(CONFIG_CMD_LED_TRIGGER) += trigger.o
obj-$(CONFIG_CMD_USB) += usb.o
obj-$(CONFIG_CMD_TIME) += time.o
+obj-$(CONFIG_CMD_UPTIME) += uptime.o
obj-$(CONFIG_CMD_OFTREE) += oftree.o
+obj-$(CONFIG_CMD_OF_COMPATIBLE) += of_compatible.o
obj-$(CONFIG_CMD_OF_DIFF) += of_diff.o
obj-$(CONFIG_CMD_OF_PROPERTY) += of_property.o
obj-$(CONFIG_CMD_OF_NODE) += of_node.o
obj-$(CONFIG_CMD_OF_DUMP) += of_dump.o
obj-$(CONFIG_CMD_OF_DISPLAY_TIMINGS) += of_display_timings.o
+obj-$(CONFIG_CMD_OF_FIXUP) += of_fixup.o
obj-$(CONFIG_CMD_OF_FIXUP_STATUS) += of_fixup_status.o
obj-$(CONFIG_CMD_OF_OVERLAY) += of_overlay.o
obj-$(CONFIG_CMD_MAGICVAR) += magicvar.o
@@ -95,6 +107,7 @@ obj-$(CONFIG_CMD_READLINK) += readlink.o
obj-$(CONFIG_CMD_LET) += let.o
obj-$(CONFIG_CMD_LN) += ln.o
obj-$(CONFIG_CMD_CLK) += clk.o
+obj-$(CONFIG_CMD_KALLSYMS) += kallsyms.o
obj-$(CONFIG_CMD_KEYSTORE) += keystore.o
obj-$(CONFIG_CMD_TFTP) += tftp.o
obj-$(CONFIG_CMD_FILETYPE) += filetype.o
@@ -103,11 +116,14 @@ obj-$(CONFIG_CMD_MIITOOL) += miitool.o
obj-$(CONFIG_CMD_DETECT) += detect.o
obj-$(CONFIG_CMD_BOOT) += boot.o
obj-$(CONFIG_CMD_DEVINFO) += devinfo.o
+obj-$(CONFIG_CMD_DEVUNBIND) += devunbind.o
+obj-$(CONFIG_CMD_DEVLOOKUP) += devlookup.o
obj-$(CONFIG_CMD_DRVINFO) += drvinfo.o
obj-$(CONFIG_CMD_READF) += readf.o
obj-$(CONFIG_CMD_MENUTREE) += menutree.o
obj-$(CONFIG_CMD_2048) += 2048.o
obj-$(CONFIG_CMD_REGULATOR) += regulator.o
+obj-$(CONFIG_CMD_PM_DOMAIN) += pm_domain.o
obj-$(CONFIG_CMD_LSPCI) += lspci.o
obj-$(CONFIG_CMD_IMD) += imd.o
obj-$(CONFIG_CMD_HWCLOCK) += hwclock.o
@@ -127,6 +143,12 @@ obj-$(CONFIG_CMD_MMC_EXTCSD) += mmc_extcsd.o
obj-$(CONFIG_CMD_NAND_BITFLIP) += nand-bitflip.o
obj-$(CONFIG_CMD_SEED) += seed.o
obj-$(CONFIG_CMD_IP_ROUTE_GET) += ip-route-get.o
+obj-$(CONFIG_CMD_BTHREAD) += bthread.o
obj-$(CONFIG_CMD_UBSAN) += ubsan.o
+obj-$(CONFIG_CMD_SELFTEST) += selftest.o
+obj-$(CONFIG_CMD_TUTORIAL) += tutorial.o
+obj-$(CONFIG_CMD_STACKSMASH) += stacksmash.o
+obj-$(CONFIG_CMD_PARTED) += parted.o
+obj-$(CONFIG_CMD_EFI_HANDLE_DUMP) += efi_handle_dump.o
UBSAN_SANITIZE_ubsan.o := y
diff --git a/commands/beep.c b/commands/beep.c
new file mode 100644
index 0000000000..29569fb51a
--- /dev/null
+++ b/commands/beep.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: © 2021 Ahmad Fatoum
+
+#include <common.h>
+#include <command.h>
+#include <sound.h>
+#include <getopt.h>
+
+static int do_beep(int argc, char *argv[])
+{
+ int ret, i, opt;
+ u32 tempo, total_us = 0;
+ bool wait = false;
+
+ while((opt = getopt(argc, argv, "wc")) > 0) {
+ switch(opt) {
+ case 'w':
+ wait = true;
+ break;
+ case 'c':
+ return beep_cancel();
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0 || argc % 2 != 1)
+ return COMMAND_ERROR_USAGE;
+
+ ret = kstrtou32(argv[0], 0, &tempo);
+ if (ret || tempo == 0)
+ return COMMAND_ERROR_USAGE;
+
+ tempo = 60 * USEC_PER_SEC / tempo;
+
+ if (argc == 1) {
+ ret = beep(BELL_DEFAULT_FREQUENCY, tempo);
+ if (ret)
+ return ret;
+
+ total_us += tempo;
+ goto out;
+ }
+
+ for (i = 1; i < argc; i += 2) {
+ u32 pitch = 0, duration;
+ u16 val;
+
+ ret = kstrtou16(argv[i], 0, &val);
+ if (ret)
+ return COMMAND_ERROR_USAGE;
+
+ if (val)
+ pitch = clamp_t(unsigned, val, 20, 20000);
+
+ ret = kstrtou16(argv[i+1], 0, &val);
+ if (ret)
+ return COMMAND_ERROR_USAGE;
+
+ duration = val * tempo;
+
+ ret = beep(pitch, duration);
+ if (ret)
+ return ret;
+
+ total_us += duration;
+ }
+
+out:
+ if (wait)
+ beep_wait(total_us);
+
+ return 0;
+}
+
+/* https://www.gnu.org/software/grub/manual/grub/html_node/play.html */
+BAREBOX_CMD_HELP_START(beep)
+BAREBOX_CMD_HELP_TEXT("Tempo is an unsigned 32bit number. It's followed by pairs of unsigned")
+BAREBOX_CMD_HELP_TEXT("16bit numbers for pitch and duration.")
+BAREBOX_CMD_HELP_TEXT("The tempo is the base for all note durations. 60 gives a 1-second base,")
+BAREBOX_CMD_HELP_TEXT("120 gives a half-second base, etc. Pitches are Hz.")
+BAREBOX_CMD_HELP_TEXT("Set pitch to 0 to produce a rest.")
+BAREBOX_CMD_HELP_TEXT("When only tempo is given, a beep of duration 1 at bell frequency results.")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-c", "cancel pending beeps")
+BAREBOX_CMD_HELP_OPT ("-w", "wait until beep is over")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(beep)
+ .cmd = do_beep,
+ BAREBOX_CMD_DESC("play a GRUB beep tune")
+ BAREBOX_CMD_OPTS("tempo [pitch1 duration1 [pitch2 duration2] ...]")
+ BAREBOX_CMD_HELP(cmd_beep_help)
+ BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE)
+BAREBOX_CMD_END
diff --git a/commands/boot.c b/commands/boot.c
index d7795bde72..e4699520e8 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -28,13 +28,14 @@ static int do_boot(int argc, char *argv[])
char *freep = NULL;
int opt, ret = 0, do_list = 0, do_menu = 0;
int dryrun = 0, verbose = 0, timeout = -1;
+ unsigned default_menu_entry = 0;
struct bootentries *entries;
struct bootentry *entry;
void *handle;
const char *name;
char *(*next)(void *);
- while ((opt = getopt(argc, argv, "vldmt:w:")) > 0) {
+ while ((opt = getopt(argc, argv, "vldmM:t:w:")) > 0) {
switch (opt) {
case 'v':
verbose++;
@@ -43,8 +44,18 @@ static int do_boot(int argc, char *argv[])
do_list = 1;
break;
case 'd':
- dryrun = 1;
+ dryrun++;
break;
+ case 'M':
+ /* To simplify scripting, an empty string is treated as 1 */
+ if (*optarg == '\0') {
+ default_menu_entry = 1;
+ } else {
+ ret = kstrtouint(optarg, 0, &default_menu_entry);
+ if (ret)
+ return ret;
+ }
+ fallthrough;
case 'm':
do_menu = 1;
break;
@@ -97,19 +108,16 @@ static int do_boot(int argc, char *argv[])
if (list_empty(&entries->entries)) {
printf("Nothing bootable found\n");
- return COMMAND_ERROR;
- }
-
- if (do_list) {
- bootsources_list(entries);
+ ret = COMMAND_ERROR;
goto out;
}
- if (do_menu) {
- bootsources_menu(entries, timeout);
- goto out;
- }
+ if (do_list)
+ bootsources_list(entries);
+ else if (do_menu)
+ bootsources_menu(entries, default_menu_entry, timeout);
+ ret = 0;
out:
bootentries_free(entries);
free(freep);
@@ -125,6 +133,7 @@ BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("BOOTSRC can be:")
BAREBOX_CMD_HELP_TEXT("- a filename under /env/boot/")
BAREBOX_CMD_HELP_TEXT("- a full path to a boot script")
+BAREBOX_CMD_HELP_TEXT("- a full path to a bootspec entry")
BAREBOX_CMD_HELP_TEXT("- a device name")
BAREBOX_CMD_HELP_TEXT("- a partition name under /dev/")
BAREBOX_CMD_HELP_TEXT("- a full path to a directory which")
@@ -136,9 +145,10 @@ BAREBOX_CMD_HELP_TEXT("one succeeds.")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-v","Increase verbosity")
-BAREBOX_CMD_HELP_OPT ("-d","Dryrun. See what happens but do no actually boot")
+BAREBOX_CMD_HELP_OPT ("-d","Dryrun. See what happens but do no actually boot (pass twice to run scripts)")
BAREBOX_CMD_HELP_OPT ("-l","List available boot sources")
BAREBOX_CMD_HELP_OPT ("-m","Show a menu with boot options")
+BAREBOX_CMD_HELP_OPT ("-M INDEX","Show a menu with boot options with entry INDEX preselected")
BAREBOX_CMD_HELP_OPT ("-w SECS","Start watchdog with timeout SECS before booting")
BAREBOX_CMD_HELP_OPT ("-t SECS","specify timeout in SECS")
BAREBOX_CMD_HELP_END
@@ -146,7 +156,7 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(boot)
.cmd = do_boot,
BAREBOX_CMD_DESC("boot from script, device, ...")
- BAREBOX_CMD_OPTS("[-vdlmwt] [BOOTSRC...]")
+ BAREBOX_CMD_OPTS("[-vdlmMwt] [BOOTSRC...]")
BAREBOX_CMD_GROUP(CMD_GRP_BOOT)
BAREBOX_CMD_HELP(cmd_boot_help)
BAREBOX_CMD_END
diff --git a/commands/bootm.c b/commands/bootm.c
index f54a4827eb..95d267135c 100644
--- a/commands/bootm.c
+++ b/commands/bootm.c
@@ -17,7 +17,6 @@
#include <fs.h>
#include <errno.h>
#include <bootm.h>
-#include <of.h>
#include <rtc.h>
#include <init.h>
#include <of.h>
diff --git a/commands/bthread.c b/commands/bthread.c
new file mode 100644
index 0000000000..aaade46e92
--- /dev/null
+++ b/commands/bthread.c
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#include <bthread.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <command.h>
+#include <getopt.h>
+#include <clock.h>
+#include <slice.h>
+
+static int bthread_time(void)
+{
+ uint64_t start = get_time_ns();
+ int i = 0;
+
+ slice_release(&command_slice);
+
+ /*
+ * How many background tasks can we have in one second?
+ *
+ * A low number here may point to problems with bthreads taking too
+ * much time.
+ */
+ while (!is_timeout(start, SECOND))
+ i++;
+
+ slice_acquire(&command_slice);
+
+ return i;
+}
+
+static void bthread_infinite(void *data)
+{
+ while (!bthread_should_stop())
+ ;
+}
+
+static int bthread_isolated_time(void)
+{
+ uint64_t start = get_time_ns();
+ struct bthread *bthread;
+ int i = 0;
+
+ bthread = bthread_run(bthread_infinite, NULL, "infinite");
+ if (!bthread)
+ return -ENOMEM;
+
+ /* main thread is the first in the run queue. Newly created bthread
+ * is the last. So if main_thread explicitly schedules new bthread,
+ * it will schedule back to main_thread afterwards and we won't
+ * execute any other threads in-between.
+ */
+
+ while (!is_timeout_non_interruptible(start, SECOND)) {
+ bthread_schedule(bthread);
+ i += 2;
+ }
+
+ __bthread_stop(bthread);
+
+ return i;
+}
+
+struct arg {
+ unsigned long in;
+ long out;
+};
+
+static void bthread_printer(void *_arg)
+{
+ struct arg *arg = _arg;
+ volatile u64 start;
+ volatile unsigned long i = 0;
+ start = get_time_ns();
+
+ while (!bthread_should_stop()) {
+ if (!is_timeout_non_interruptible(start, 225 * MSECOND))
+ continue;
+
+ if (arg->in == i++)
+ printf("%s yield #%lu\n", bthread_name(current), i);
+ start = get_time_ns();
+ }
+
+ arg->out = i;
+}
+
+static int yields;
+
+static void bthread_spawner(void *_spawner_arg)
+{
+ struct arg *arg, *spawner_arg = _spawner_arg;
+ struct bthread *bthread[4];
+ volatile u64 start;
+ volatile unsigned long i = 0;
+ int ret = 0;
+
+ start = get_time_ns();
+
+ for (i = 0; i < ARRAY_SIZE(bthread); i++) {
+ arg = malloc(sizeof(*arg));
+ arg->in = i;
+ bthread[i] = bthread_run(bthread_printer, arg,
+ "%s-bthread%u", bthread_name(current), i+1);
+ if (!bthread[i]) {
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ }
+
+ while (!bthread_should_stop())
+ ;
+
+cleanup:
+ while (i--) {
+ arg = bthread_data(bthread[i]);
+ __bthread_stop(bthread[i]);
+
+ if (!ret && (arg->out != 4 || yields < arg->out))
+ ret = -EIO;
+ free(arg);
+ }
+
+ spawner_arg->out = ret;
+}
+
+struct spawn {
+ struct bthread *bthread;
+ struct list_head list;
+};
+
+static int do_bthread(int argc, char *argv[])
+{
+ static int dummynr;
+ static LIST_HEAD(dummies);
+ LIST_HEAD(spawners);
+ struct spawn *spawner, *tmp;
+ int ret = 0;
+ int opt, i = 0;
+ bool time = false;
+ struct arg *arg;
+
+ while ((opt = getopt(argc, argv, "aritcv")) > 0) {
+ switch (opt) {
+ case 'a':
+ spawner = xzalloc(sizeof(*spawner));
+ spawner->bthread = bthread_run(bthread_infinite, NULL,
+ "dummy%u", dummynr++);
+ if (!spawner->bthread) {
+ free(spawner);
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ list_add(&spawner->list, &dummies);
+ break;
+ case 'r':
+ if (dummynr == 0)
+ return -EINVAL;
+ spawner = list_first_entry(&dummies, struct spawn, list);
+ bthread_cancel(spawner->bthread);
+ list_del(&spawner->list);
+ free(spawner);
+ dummynr--;
+ break;
+ case 'i':
+ bthread_info();
+ break;
+ case 'c':
+ yields = bthread_isolated_time();
+ printf("%d bthread context switches possible in 1s\n", yields);
+ break;
+ case 'v':
+ spawner = xzalloc(sizeof(*spawner));
+ arg = malloc(sizeof(*arg));
+ spawner->bthread = bthread_run(bthread_spawner, arg,
+ "spawner%u", ++i);
+ if (!spawner->bthread) {
+ free(spawner);
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ /* We create intermediate spawning threads to test thread
+ * creation and scheduling from non-main thread.
+ */
+ list_add(&spawner->list, &spawners);
+
+ /* fallthrough */
+ case 't':
+ time = true;
+ }
+ }
+
+ if (time) {
+ yields = bthread_time();
+ printf("%d bthread yield calls in 1s\n", yields);
+ }
+
+cleanup:
+ list_for_each_entry_safe(spawner, tmp, &spawners, list) {
+ arg = bthread_data(spawner->bthread);
+ __bthread_stop(spawner->bthread);
+ if (!ret && arg->out)
+ ret = arg->out;
+ free(arg);
+ free(spawner);
+ }
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(bthread)
+ BAREBOX_CMD_HELP_TEXT("print info about registered barebox threads")
+ BAREBOX_CMD_HELP_TEXT("")
+ BAREBOX_CMD_HELP_TEXT("Options:")
+ BAREBOX_CMD_HELP_OPT ("-i", "Print information about registered bthreads")
+ BAREBOX_CMD_HELP_OPT ("-t", "measure how many bthreads we currently run in 1s")
+ BAREBOX_CMD_HELP_OPT ("-c", "count maximum context switches in 1s")
+ BAREBOX_CMD_HELP_OPT ("-a", "add a dummy bthread")
+ BAREBOX_CMD_HELP_OPT ("-r", "remove a dummy bthread")
+ BAREBOX_CMD_HELP_OPT ("-v", "verify correct bthread operation")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(bthread)
+ .cmd = do_bthread,
+ BAREBOX_CMD_DESC("print info about registered bthreads")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_HELP(cmd_bthread_help)
+BAREBOX_CMD_END
diff --git a/commands/cat.c b/commands/cat.c
index 17c31ed083..503520dc64 100644
--- a/commands/cat.c
+++ b/commands/cat.c
@@ -40,7 +40,7 @@ static int do_cat(int argc, char *argv[])
fd = open(argv[args], O_RDONLY);
if (fd < 0) {
err = 1;
- printf("could not open %s: %s\n", argv[args], errno_str());
+ printf("could not open %s: %m\n", argv[args]);
goto out;
}
diff --git a/commands/clk.c b/commands/clk.c
index 649a0a7cb2..606519091e 100644
--- a/commands/clk.c
+++ b/commands/clk.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <getopt.h>
@@ -54,23 +56,18 @@ BAREBOX_CMD_END
static int do_clk_set_rate(int argc, char *argv[])
{
- struct clk *clk;
unsigned long rate;
if (argc != 3)
return COMMAND_ERROR_USAGE;
- clk = clk_lookup(argv[1]);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
rate = simple_strtoul(argv[2], NULL, 0);
- return clk_set_rate(clk, rate);
+ return clk_name_set_rate(argv[1], rate);
}
BAREBOX_CMD_HELP_START(clk_set_rate)
-BAREBOX_CMD_HELP_TEXT("Set clock CLK to RATE")
+BAREBOX_CMD_HELP_TEXT("Set clock CLK rate to HZ")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(clk_set_rate)
@@ -82,6 +79,38 @@ BAREBOX_CMD_START(clk_set_rate)
BAREBOX_CMD_COMPLETE(clk_name_complete)
BAREBOX_CMD_END
+static int do_clk_round_rate(int argc, char *argv[])
+{
+ struct clk *clk;
+ unsigned long rate;
+
+ if (argc != 3)
+ return COMMAND_ERROR_USAGE;
+
+ clk = clk_lookup(argv[1]);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ rate = simple_strtoul(argv[2], NULL, 0);
+
+ printf("%ld\n", clk_round_rate(clk, rate));
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(clk_round_rate)
+BAREBOX_CMD_HELP_TEXT("Show clock CLK actual rate if set to HZ")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(clk_round_rate)
+ .cmd = do_clk_round_rate,
+ BAREBOX_CMD_DESC("show a resulting clocks rate")
+ BAREBOX_CMD_OPTS("CLK HZ")
+ BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_HELP(cmd_clk_round_rate_help)
+ BAREBOX_CMD_COMPLETE(clk_name_complete)
+BAREBOX_CMD_END
+
static int do_clk_get_rate(int argc, char *argv[])
{
int opt;
@@ -110,13 +139,9 @@ static int do_clk_get_rate(int argc, char *argv[])
rate = clk_get_rate(clk);
- if (variable_name) {
- char *t;
-
- t = basprintf("%lu", rate);
- setenv(variable_name, t);
- free(t);
- } else
+ if (variable_name)
+ pr_setenv(variable_name, "%lu", rate);
+ else
printf("%lu\n", rate);
return COMMAND_SUCCESS;
@@ -182,19 +207,10 @@ BAREBOX_CMD_END
static int do_clk_set_parent(int argc, char *argv[])
{
- struct clk *clk, *parent;
-
if (argc != 3)
return COMMAND_ERROR_USAGE;
- clk = clk_lookup(argv[1]);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
- parent = clk_lookup(argv[2]);
- if (IS_ERR(parent))
- return PTR_ERR(parent);
-
- return clk_set_parent(clk, parent);
+ return clk_name_set_parent(argv[1], argv[2]);
}
BAREBOX_CMD_START(clk_set_parent)
diff --git a/commands/crc.c b/commands/crc.c
index 80ecf7fe29..23ffd4360b 100644
--- a/commands/crc.c
+++ b/commands/crc.c
@@ -83,17 +83,11 @@ static int do_crc(int argc, char *argv[])
printf("CRC32 for %s 0x%08lx ... 0x%08lx ==> 0x%08lx",
filename, (ulong)start, (ulong)start + total - 1, crc);
- if (crcvarname) {
- char *crcstr = basprintf("0x%lx", crc);
- setenv(crcvarname, crcstr);
- kfree(crcstr);
- }
+ if (crcvarname)
+ pr_setenv(crcvarname, "0x%lx", crc);
- if (sizevarname) {
- char *sizestr = basprintf("0x%lx", total);
- setenv(sizevarname, sizestr);
- kfree(sizestr);
- }
+ if (sizevarname)
+ pr_setenv(sizevarname, "0x%lx", total);
#ifdef CONFIG_CMD_CRC_CMP
if (vfilename) {
diff --git a/commands/detect.c b/commands/detect.c
index 70eca57537..ad1745adce 100644
--- a/commands/detect.c
+++ b/commands/detect.c
@@ -12,7 +12,7 @@
static int do_detect(int argc, char *argv[])
{
- struct device_d *dev;
+ struct device *dev;
int opt, i, ret, err;
int option_list = 0;
int option_all = 0;
diff --git a/commands/devinfo.c b/commands/devinfo.c
index 2e2e48e42c..6001b00cfa 100644
--- a/commands/devinfo.c
+++ b/commands/devinfo.c
@@ -6,9 +6,9 @@
#include <complete.h>
#include <driver.h>
-static int do_devinfo_subtree(struct device_d *dev, int depth)
+static int do_devinfo_subtree(struct device *dev, int depth)
{
- struct device_d *child;
+ struct device *child;
struct cdev *cdev, *cdevl;
int i;
@@ -46,7 +46,7 @@ static int do_devinfo_subtree(struct device_d *dev, int depth)
static int do_devinfo(int argc, char *argv[])
{
- struct device_d *dev;
+ struct device *dev;
struct param_d *param;
int i;
int first;
@@ -85,7 +85,7 @@ static int do_devinfo(int argc, char *argv[])
if (dev->info)
dev->info(dev);
- if (dev->parent)
+ if (dev->parent && (!dev->bus || dev->bus->dev != dev->parent))
printf("Parent: %s\n", dev_name(dev->parent));
first = true;
@@ -102,9 +102,22 @@ static int do_devinfo(int argc, char *argv[])
printf("\n");
}
#ifdef CONFIG_OFDEVICE
- if (dev->device_node) {
- printf("Device node: %s\n", dev->device_node->full_name);
- of_print_nodes(dev->device_node, 0);
+ if (dev->of_node) {
+ struct device *main_dev = dev->of_node->dev;
+
+ printf("DMA Coherent: %s%s\n",
+ dev_is_dma_coherent(dev) ? "true" : "false",
+ dev->dma_coherent == DEV_DMA_COHERENCE_DEFAULT ? " (default)" : "");
+
+ printf("Device node: %pOF", dev->of_node);
+ if (!main_dev) {
+ printf(" (unpopulated)\n");
+ } else if (main_dev != dev) {
+ printf(" (populated by %s)\n", dev_name(main_dev));
+ } else {
+ printf("\n");
+ of_print_nodes(dev->of_node, 0, ~0);
+ }
}
#endif
}
diff --git a/commands/devlookup.c b/commands/devlookup.c
new file mode 100644
index 0000000000..ffd6afbaba
--- /dev/null
+++ b/commands/devlookup.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <getopt.h>
+#include <malloc.h>
+#include <linux/stat.h>
+#include <linux/ctype.h>
+#include <environment.h>
+
+static int report(const char *variable, const char *val)
+{
+ if (!val)
+ return -(errno ?: EINVAL);
+
+ if (variable)
+ return setenv(variable, val);
+
+ printf("%s\n", val);
+ return 0;
+}
+
+static int do_devlookup(int argc, char *argv[])
+{
+ const char *variable = NULL, *devicefile, *paramname;
+ struct cdev *cdev;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "v:")) > 0) {
+ switch(opt) {
+ case 'v':
+ variable = optarg;
+ break;
+ }
+ }
+
+ if (argc - optind == 0 || argc - optind > 2)
+ return COMMAND_ERROR_USAGE;
+
+ devicefile = argv[optind];
+ paramname = argv[optind + 1];
+
+ devicefile = devpath_to_name(devicefile);
+
+ cdev = cdev_by_name(devicefile);
+ if (!cdev) {
+ printf("devlookup: cdev %s not found\n", devicefile);
+ return -ENOENT;
+ }
+
+ if (!cdev->dev) {
+ printf("devlookup: cdev %s not associated with a device\n", devicefile);
+ return -ENODEV;
+ }
+
+ if (paramname)
+ return report(variable, dev_get_param(cdev->dev, paramname));
+
+ return report(variable, dev_name(cdev->dev));
+}
+
+BAREBOX_CMD_HELP_START(devlookup)
+BAREBOX_CMD_HELP_TEXT("Detects the device behind a device file and outputs it,")
+BAREBOX_CMD_HELP_TEXT("unless a second argument is given. In that case the device")
+BAREBOX_CMD_HELP_TEXT("parameter with that name is looked up. Specifying -v VARIABLE")
+BAREBOX_CMD_HELP_TEXT("will write output to VARIABLE instead of printing it")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(devlookup)
+ .cmd = do_devlookup,
+ BAREBOX_CMD_DESC("look up device behind device file and its parameters")
+ BAREBOX_CMD_OPTS("[-v VAR] /dev/DEVICE [parameter]")
+ BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
+ BAREBOX_CMD_HELP(cmd_devlookup_help)
+BAREBOX_CMD_END
+
diff --git a/commands/devunbind.c b/commands/devunbind.c
new file mode 100644
index 0000000000..d30193b285
--- /dev/null
+++ b/commands/devunbind.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: © 2021 Ahmad Fatoum <a.fatoum@pengutronix.de>, Pengutronix
+
+#include <command.h>
+#include <common.h>
+#include <complete.h>
+#include <driver.h>
+#include <getopt.h>
+
+static int do_devunbind(int argc, char *argv[])
+{
+ bool unregister = false;
+ struct device *dev;
+ int ret = COMMAND_SUCCESS, i, opt;
+
+ while ((opt = getopt(argc, argv, "fl")) > 0) {
+ switch (opt) {
+ case 'f':
+ unregister = true;
+ break;
+ case 'l':
+ list_for_each_entry(dev, &active_device_list, active) {
+ void *rm_dev;
+
+ BUG_ON(!dev->driver);
+
+ rm_dev = dev->bus->remove ?: dev->driver->remove;
+
+ if (rm_dev)
+ printf("%pS(%s, %s)\n", rm_dev,
+ dev->driver->name, dev_name(dev));
+ }
+ return 0;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (!argv[optind])
+ return COMMAND_ERROR_USAGE;
+
+ for (i = optind; i < argc; i++) {
+ dev = get_device_by_name(argv[i]);
+ if (!dev) {
+ printf("skipping missing %s\n", argv[i]);
+ ret = -ENODEV;
+ continue;
+ }
+
+ if (unregister) {
+ unregister_device(dev);
+ continue;
+ }
+
+ if (!device_remove(dev)) {
+ printf("no remove callback registered for %s\n", argv[i]);
+ ret = COMMAND_ERROR;
+ continue;
+ }
+
+ dev->driver = NULL;
+ list_del(&dev->active);
+ }
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(devunbind)
+BAREBOX_CMD_HELP_TEXT("Debugging aid to unbind device from driver at runtime")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-f", "unbind driver and force removal of device and children")
+BAREBOX_CMD_HELP_OPT ("-l", "list remove callbacks in shutdown order")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(devunbind)
+ .cmd = do_devunbind,
+ BAREBOX_CMD_DESC("unbind device(s) from driver")
+ BAREBOX_CMD_OPTS("[-fl] DEVICES..")
+ BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+ BAREBOX_CMD_HELP(cmd_devunbind_help)
+ BAREBOX_CMD_COMPLETE(device_complete)
+BAREBOX_CMD_END
diff --git a/commands/dfu.c b/commands/dfu.c
index 3132a7479d..2116747f68 100644
--- a/commands/dfu.c
+++ b/commands/dfu.c
@@ -10,7 +10,8 @@
#include <getopt.h>
#include <fs.h>
#include <xfuncs.h>
-#include <usb/dfu.h>
+#include <linux/usb/dfu.h>
+#include <linux/usb/gadget-multi.h>
#include <linux/err.h>
/* dfu /dev/self0(bootloader)sr,/dev/nand0.root.bb(root)
@@ -20,28 +21,28 @@
*/
static int do_dfu(int argc, char *argv[])
{
- struct f_dfu_opts opts;
- char *argstr;
- struct usb_dfu_dev *dfu_alts = NULL;
+ struct usbgadget_funcs funcs = {};
int ret;
if (argc != optind + 1)
return COMMAND_ERROR_USAGE;
- argstr = argv[optind];
+ funcs.flags |= USBGADGET_DFU;
+ funcs.dfu_opts = argv[optind];
+ ret = usbgadget_register(&funcs);
+ if (ret)
+ return ret;
- opts.files = file_list_parse(argstr);
- if (IS_ERR(opts.files)) {
- ret = PTR_ERR(opts.files);
- goto out;
+ command_slice_release();
+ while (!usb_dfu_detached()) {
+ if (ctrlc()) {
+ ret = -EINTR;
+ break;
+ }
}
+ command_slice_acquire();
- ret = usb_dfu_register(&opts);
-
- file_list_free(opts.files);
-out:
-
- free(dfu_alts);
+ usb_multi_unregister();
return ret;
}
diff --git a/commands/dhrystone.c b/commands/dhrystone.c
index 154910e5d0..17efa9c099 100644
--- a/commands/dhrystone.c
+++ b/commands/dhrystone.c
@@ -15,7 +15,7 @@
#include <command.h>
#include <errno.h>
#include <clock.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <malloc.h>
#include <stdio.h> /* for strcpy, strcmp */
diff --git a/commands/digest.c b/commands/digest.c
index b7ed4d50af..e57920e582 100644
--- a/commands/digest.c
+++ b/commands/digest.c
@@ -190,7 +190,7 @@ err:
BAREBOX_CMD_HELP_START(digest)
BAREBOX_CMD_HELP_TEXT("Calculate a digest over a FILE or a memory area.")
BAREBOX_CMD_HELP_TEXT("Options:")
-BAREBOX_CMD_HELP_OPT ("-a <algo>\t", "hash or signature algorithm to use")
+BAREBOX_CMD_HELP_OPT ("-a <algo>\t", "hash or signature algorithm name/driver to use")
BAREBOX_CMD_HELP_OPT ("-k <key>\t", "use supplied <key> (ASCII or hex) for MAC")
BAREBOX_CMD_HELP_OPT ("-K <file>\t", "use key from <file> (binary) for MAC")
BAREBOX_CMD_HELP_OPT ("-s <hex>\t", "verify data against supplied <hex> (hash, MAC or signature)")
diff --git a/commands/dmesg.c b/commands/dmesg.c
index 15ad449639..8a60f07507 100644
--- a/commands/dmesg.c
+++ b/commands/dmesg.c
@@ -11,6 +11,42 @@
#include <getopt.h>
#include <clock.h>
+static int str_to_loglevel(const char *str)
+{
+ int ret;
+ unsigned long level;
+
+ ret = kstrtoul(str, 10, &level);
+ if (!ret) {
+ if (level > MSG_VDEBUG)
+ goto unknown;
+ return level;
+ }
+
+ if (!strcmp(str, "vdebug"))
+ return MSG_VDEBUG;
+ if (!strcmp(str, "debug"))
+ return MSG_DEBUG;
+ if (!strcmp(str, "info"))
+ return MSG_INFO;
+ if (!strcmp(str, "notice"))
+ return MSG_NOTICE;
+ if (!strcmp(str, "warn"))
+ return MSG_WARNING;
+ if (!strcmp(str, "err"))
+ return MSG_ERR;
+ if (!strcmp(str, "crit"))
+ return MSG_CRIT;
+ if (!strcmp(str, "alert"))
+ return MSG_ALERT;
+ if (!strcmp(str, "emerg"))
+ return MSG_EMERG;
+unknown:
+ printf("dmesg: unknown loglevel %s\n", str);
+
+ return -EINVAL;
+}
+
static unsigned dmesg_get_levels(const char *__args)
{
char *args = xstrdup(__args);
@@ -18,28 +54,19 @@ static unsigned dmesg_get_levels(const char *__args)
unsigned flags = 0;
while (1) {
+ int level;
+
str = strsep(&levels, ",");
if (!str)
break;
- if(!strcmp(str, "vdebug"))
- flags |= BAREBOX_LOG_PRINT_VDEBUG;
- else if(!strcmp(str, "debug"))
- flags |= BAREBOX_LOG_PRINT_DEBUG;
- else if(!strcmp(str, "info"))
- flags |= BAREBOX_LOG_PRINT_INFO;
- else if(!strcmp(str, "notice"))
- flags |= BAREBOX_LOG_PRINT_NOTICE;
- else if(!strcmp(str, "warn"))
- flags |= BAREBOX_LOG_PRINT_WARNING;
- else if(!strcmp(str, "err"))
- flags |= BAREBOX_LOG_PRINT_ERR;
- else if(!strcmp(str, "crit"))
- flags |= BAREBOX_LOG_PRINT_CRIT;
- else if(!strcmp(str, "alert"))
- flags |= BAREBOX_LOG_PRINT_ALERT;
- else if(!strcmp(str, "emerg"))
- flags |= BAREBOX_LOG_PRINT_EMERG;
+ level = str_to_loglevel(str);
+ if (level < 0) {
+ flags = 0;
+ break;
+ }
+
+ flags |= BIT(level);
}
free(args);
@@ -49,11 +76,12 @@ static unsigned dmesg_get_levels(const char *__args)
static int do_dmesg(int argc, char *argv[])
{
- int opt, i;
+ int opt, ret, i;
int delete_buf = 0, emit = 0;
unsigned flags = 0, levels = 0;
+ char *set = NULL;
- while ((opt = getopt(argc, argv, "ctderl:")) > 0) {
+ while ((opt = getopt(argc, argv, "ctderl:n:")) > 0) {
switch (opt) {
case 'c':
delete_buf = 1;
@@ -70,16 +98,30 @@ static int do_dmesg(int argc, char *argv[])
case 'l':
levels = dmesg_get_levels(optarg);
if (!levels)
- return COMMAND_ERROR_USAGE;
+ return COMMAND_ERROR;
break;
case 'r':
flags |= BAREBOX_LOG_PRINT_RAW | BAREBOX_LOG_PRINT_TIME;
break;
+ case 'n':
+ set = optarg;
+ break;
default:
return COMMAND_ERROR_USAGE;
}
}
+ if (set) {
+ int level = str_to_loglevel(set);
+
+ if (level < 0)
+ return COMMAND_ERROR;
+
+ barebox_loglevel = level;
+
+ return 0;
+ }
+
if (emit) {
char *buf;
int len = 0;
@@ -106,7 +148,9 @@ static int do_dmesg(int argc, char *argv[])
return 0;
}
- log_print(flags, levels);
+ ret = log_print(flags, levels);
+ if (ret)
+ return 1;
if (delete_buf)
log_clean(10);
@@ -114,12 +158,19 @@ static int do_dmesg(int argc, char *argv[])
return 0;
}
+
BAREBOX_CMD_HELP_START(dmesg)
+BAREBOX_CMD_HELP_TEXT("print or control the barebox message buffer")
+BAREBOX_CMD_HELP_TEXT("Loglevels can be specified as number (0=emerg, 7=vdebug)")
+BAREBOX_CMD_HELP_TEXT("Known debug loglevels are: emerg, alert, crit, err, warn, notice, info, debug,")
+BAREBOX_CMD_HELP_TEXT("vdebug")
+BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-c", "Delete messages after printing them")
BAREBOX_CMD_HELP_OPT ("-d", "Show a time delta to the last message")
BAREBOX_CMD_HELP_OPT ("-e <msg>", "Emit a log message")
-BAREBOX_CMD_HELP_OPT ("-l <vdebug|debug|info|notice|warn|err|crit|alert|emerg>", "Restrict output to the given (comma-separated) list of levels")
+BAREBOX_CMD_HELP_OPT ("-l <loglevel>", "Restrict output to the given (comma-separated) list of levels")
+BAREBOX_CMD_HELP_OPT ("-n <loglevel>", "Set level at which printing of messages is done to the console")
BAREBOX_CMD_HELP_OPT ("-r", "Print timestamp and log-level prefixes.")
BAREBOX_CMD_HELP_OPT ("-t", "Show timestamp informations")
BAREBOX_CMD_HELP_END
diff --git a/commands/drvinfo.c b/commands/drvinfo.c
index 9f8f971ee9..e13b04870e 100644
--- a/commands/drvinfo.c
+++ b/commands/drvinfo.c
@@ -5,15 +5,21 @@
#include <common.h>
#include <command.h>
#include <driver.h>
+#include <complete.h>
+#include <fnmatch.h>
static int do_drvinfo(int argc, char *argv[])
{
- struct driver_d *drv;
- struct device_d *dev;
+ char *pattern = argv[1];
+ struct driver *drv;
+ struct device *dev;
printf("Driver\tDevice(s)\n");
printf("--------------------\n");
for_each_driver(drv) {
+ if (pattern && fnmatch(pattern, drv->name, 0))
+ continue;
+
printf("%s\n",drv->name);
for_each_device(dev) {
if (dev->driver == drv)
@@ -31,5 +37,7 @@ static int do_drvinfo(int argc, char *argv[])
BAREBOX_CMD_START(drvinfo)
.cmd = do_drvinfo,
BAREBOX_CMD_DESC("list compiled-in device drivers")
+ BAREBOX_CMD_OPTS("[DRIVER]")
BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+ BAREBOX_CMD_COMPLETE(driver_complete)
BAREBOX_CMD_END
diff --git a/commands/echo.c b/commands/echo.c
index 99575b4c0c..572b852ea3 100644
--- a/commands/echo.c
+++ b/commands/echo.c
@@ -10,6 +10,40 @@
#include <errno.h>
#include <libbb.h>
+static void echo_dputc(int fd, char c, bool wide)
+{
+ wchar_t wc;
+ int n;
+
+ if (!wide || fd == 1 || fd == 2) {
+ dputc(fd, c);
+ return;
+ }
+
+ n = mbtowc(&wc, &c, 1);
+ if (n < 0)
+ return;
+
+ write(fd, &wc, sizeof(wchar_t));
+}
+
+static void echo_dputs(int fd, const char *s, bool wide)
+{
+ wchar_t *ws;
+
+ if (!wide || fd == 1 || fd == 2) {
+ dputs(fd, s);
+ return;
+ }
+
+ ws = strdup_char_to_wchar(s);
+ if (!ws)
+ return;
+
+ write(fd, ws, wcslen(ws) * sizeof(wchar_t));
+ free(ws);
+}
+
static int do_echo(int argc, char *argv[])
{
int i, optind = 1;
@@ -18,6 +52,10 @@ static int do_echo(int argc, char *argv[])
int oflags = O_WRONLY | O_CREAT;
char str[CONFIG_CBSIZE];
int process_escape = 0;
+ bool wide = false;
+
+ if (IS_ENABLED(CONFIG_PRINTF_WCHAR) && *argv[0] == 'w')
+ wide = true;
/* We can't use getopt() here because we want to
* echo all things we don't understand.
@@ -66,18 +104,22 @@ exit_parse:
}
for (i = optind; i < argc; i++) {
+ const char *out;
+
if (i > optind)
- dputc(fd, ' ');
+ echo_dputc(fd, ' ', wide);
if (process_escape) {
process_escape_sequence(argv[i], str, CONFIG_CBSIZE);
- dputs(fd, str);
+ out = str;
} else {
- dputs(fd, argv[i]);
+ out = argv[i];
}
+
+ echo_dputs(fd, out, wide);
}
if (newline)
- dputc(fd, '\n');
+ echo_dputc(fd, '\n', wide);
if (file)
close(fd);
@@ -99,8 +141,13 @@ BAREBOX_CMD_HELP_OPT ("-a FILE", "append to FILE instead of using stdout")
BAREBOX_CMD_HELP_OPT ("-o FILE", "overwrite FILE instead of using stdout")
BAREBOX_CMD_HELP_END
+static __maybe_unused const char * const echo_aliases[] = { "wecho", NULL};
+
BAREBOX_CMD_START(echo)
.cmd = do_echo,
+#ifdef CONFIG_PRINTF_WCHAR
+ .aliases = echo_aliases,
+#endif
BAREBOX_CMD_DESC("echo args to console")
BAREBOX_CMD_OPTS("[-neao] STRING")
BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE)
diff --git a/commands/edit.c b/commands/edit.c
index 3ab4beaa4f..dea383aae7 100644
--- a/commands/edit.c
+++ b/commands/edit.c
@@ -12,6 +12,7 @@
#include <errno.h>
#include <xfuncs.h>
#include <linux/stat.h>
+#include <console.h>
#define TABSPACE 8
@@ -184,7 +185,7 @@ static int edit_read_file(const char *path)
if (!stat(path, &s)) {
filebuffer = read_file(path, NULL);
if (!filebuffer) {
- printf("could not read %s: %s\n", path, errno_str());
+ printf("could not read %s: %m\n", path);
return -1;
}
@@ -248,7 +249,7 @@ static int save_file(const char *path)
fd = open(path, O_WRONLY | O_TRUNC | O_CREAT);
if (fd < 0) {
- printf("could not open file for writing: %s\n", errno_str());
+ printf("could not open file for writing: %m\n");
return fd;
}
@@ -347,19 +348,57 @@ static void merge_line(struct line *line)
static void getwinsize(void)
{
- int i = 0, r;
- char buf[100];
+ int n;
char *endp;
+ struct console_device *cdev;
+ const char esc[] = ESC "7" ESC "[r" ESC "[999;999H" ESC "[6n";
+ char buf[64];
- printf(ESC "7" ESC "[r" ESC "[999;999H" ESC "[6n");
+ screenwidth = screenheight = 256;
- while ((r = getchar()) != 'R') {
- buf[i] = r;
- i++;
- }
+ for_each_console(cdev) {
+ int width, height;
+ uint64_t start;
+
+ if (!(cdev->f_active & CONSOLE_STDIN))
+ continue;
+ if (!(cdev->f_active & CONSOLE_STDOUT))
+ continue;
+
+ memset(buf, 0, sizeof(buf));
+
+ cdev->puts(cdev, esc, sizeof(esc));
+
+ n = 0;
+
+ start = get_time_ns();
+
+ while (1) {
+ if (is_timeout(start, 100 * MSECOND))
+ break;
+
+ if (!cdev->tstc(cdev))
+ continue;
+
+ buf[n] = cdev->getc(cdev);
+
+ if (buf[n] == 'R')
+ break;
+
+ n++;
+ }
+
+ if (buf[0] != 27)
+ continue;
+ if (buf[1] != '[')
+ continue;
- screenheight = simple_strtoul(buf + 2, &endp, 10);
- screenwidth = simple_strtoul(endp + 1, NULL, 10);
+ height = simple_strtoul(buf + 2, &endp, 10);
+ width = simple_strtoul(endp + 1, NULL, 10);
+
+ screenwidth = min(screenwidth, width);
+ screenheight = min(screenheight, height);
+ }
pos(0, 0);
}
@@ -483,6 +522,25 @@ static int read_modal_key(bool is_modal)
return -EAGAIN;
}
+static bool is_efi_console_active(void)
+{
+ struct console_device *cdev;
+
+ if (!IS_ENABLED(CONFIG_DRIVER_SERIAL_EFI_STDIO))
+ return false;
+
+ for_each_console(cdev) {
+ if (!(cdev->f_active & CONSOLE_STDIN))
+ continue;
+ if (!(cdev->f_active & CONSOLE_STDOUT))
+ continue;
+ if (!strcmp(dev_name(cdev->dev), "efi-stdio"))
+ return true;
+ }
+
+ return false;
+}
+
static int do_edit(int argc, char *argv[])
{
bool is_vi = false;
@@ -495,17 +553,12 @@ static int do_edit(int argc, char *argv[])
if (argc != 2)
return COMMAND_ERROR_USAGE;
- screenwidth = 80;
+ buffer = NULL;
+ if(edit_read_file(argv[1]))
+ return 1;
- /*
- * The EFI simple text output protocol wraps to the next line and scrolls
- * down when we write to the right bottom screen position. Reduce the number
- * of rows by one to work around this.
- */
- if (IS_ENABLED(CONFIG_EFI_BOOTUP))
- screenheight = 24;
- else
- screenheight = 25;
+ screenwidth = 80;
+ screenheight = 25;
/* check if we are not called as "edit" */
if (*argv[0] != 'e') {
@@ -517,9 +570,21 @@ static int do_edit(int argc, char *argv[])
is_vi = true;
}
- buffer = NULL;
- if(edit_read_file(argv[1]))
- return 1;
+ if (is_efi_console_active()) {
+ /*
+ * The EFI simple text output protocol wraps to the next line and
+ * scrolls down when we write to the right bottom screen position.
+ * Reduce the number of rows by one to work around this.
+ */
+ screenheight--;
+
+ /*
+ * Our console driver for the EFI simple text output protocol does
+ * not implement the "\e[1S" sequence we use for scrolling the
+ * screen.
+ */
+ smartscroll = 0;
+ }
cursx = 0;
cursy = 0;
@@ -545,7 +610,9 @@ static int do_edit(int argc, char *argv[])
argv[1]);
}
- printf("\x1b[2;%dr", screenheight);
+ if (smartscroll)
+ printf("\x1b[2;%dr", screenheight);
+
pos(0, 0);
screenheight--; /* status line */
diff --git a/commands/efi_handle_dump.c b/commands/efi_handle_dump.c
new file mode 100644
index 0000000000..a9db5eb75b
--- /dev/null
+++ b/commands/efi_handle_dump.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * efi-device.c - barebox EFI payload support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ */
+
+#include <common.h>
+#include <command.h>
+#include <efi.h>
+#include <linux/uuid.h>
+#include <efi/efi-mode.h>
+#include <efi/efi-device.h>
+
+static void efi_devpath(struct efi_boot_services *bs,
+ efi_handle_t handle,
+ const efi_guid_t *guid,
+ const char *desc)
+{
+ efi_status_t efiret;
+ void *devpath;
+ char *dev_path_str;
+
+ efiret = bs->open_protocol(handle, guid, &devpath, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(efiret))
+ return;
+
+ dev_path_str = device_path_to_str(devpath);
+ if (dev_path_str) {
+ printf(" %s: \n %s\n", desc, dev_path_str);
+ free(dev_path_str);
+ }
+}
+
+static void efi_dump(struct efi_boot_services *bs, efi_handle_t *handles, unsigned long handle_count)
+{
+ int i, j;
+ unsigned long num_guids;
+ efi_guid_t **guids;
+
+ if (!handles || !handle_count)
+ return;
+
+ for (i = 0; i < handle_count; i++) {
+ printf("handle-%p\n", handles[i]);
+
+ bs->protocols_per_handle(handles[i], &guids, &num_guids);
+ printf(" Protocols:\n");
+ for (j = 0; j < num_guids; j++)
+ printf(" %d: %pUl: %s\n", j, guids[j],
+ efi_guid_string(guids[j]));
+
+ efi_devpath(bs, handles[i], &efi_device_path_protocol_guid,
+ "Devpath");
+ efi_devpath(bs, handles[i], &efi_loaded_image_device_path_guid,
+ "Image Devpath");
+ }
+ printf("\n");
+}
+
+static int do_efi_protocol_dump(struct efi_boot_services *bs, int argc, char **argv)
+{
+ unsigned long handle_count = 0;
+ efi_handle_t *handles = NULL;
+ int ret;
+ efi_guid_t guid;
+
+ /* Format 220e73b6-6bdb-4413-8405-b974b108619a */
+ if (argc == 1) {
+ ret = guid_parse(argv[0], &guid);
+ } else if (argc == 11) {
+ u32 a;
+ u16 b, c;
+ u8 d0, d1, d2, d3, d4, d5, d6, d7;
+ /* Format :
+ * 220e73b6 6bdb 4413 84 05 b9 74 b1 08 61 9a
+ * or
+ * 0x220e73b6 0x6bdb 0x14413 0x84 0x05 0xb9 0x74 0xb1 0x08 0x61 0x9a
+ */
+ ret = kstrtou32(argv[0], 16, &a);
+ ret = ret ?: kstrtou16(argv[1], 16, &b);
+ ret = ret ?: kstrtou16(argv[2], 16, &c);
+ ret = ret ?: kstrtou8(argv[3], 16, &d0);
+ ret = ret ?: kstrtou8(argv[4], 16, &d1);
+ ret = ret ?: kstrtou8(argv[5], 16, &d2);
+ ret = ret ?: kstrtou8(argv[6], 16, &d3);
+ ret = ret ?: kstrtou8(argv[7], 16, &d4);
+ ret = ret ?: kstrtou8(argv[8], 16, &d5);
+ ret = ret ?: kstrtou8(argv[9], 16, &d6);
+ ret = ret ?: kstrtou8(argv[10], 16, &d7);
+ if (!ret)
+ guid = EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7);
+ } else {
+ ret = -EINVAL;
+ }
+
+ if (ret)
+ return ret;
+
+ printf("Searching for:\n");
+ printf(" %pUl: %s\n", &guid, efi_guid_string(&guid));
+
+ ret = __efi_locate_handle(bs, BY_PROTOCOL, &guid, NULL, &handle_count, &handles);
+ if (!ret)
+ efi_dump(bs, handles, handle_count);
+
+ return 0;
+}
+
+static int do_efi_handle_dump(int argc, char *argv[])
+{
+ unsigned long handle_count = 0;
+ efi_handle_t *handles = NULL;
+ struct efi_boot_services *bs;
+ int ret;
+
+ bs = efi_get_boot_services();
+ if (!bs) {
+ printf("EFI not yet initialized\n");
+ return COMMAND_ERROR;
+ }
+
+ if (argc > 1)
+ return do_efi_protocol_dump(bs, --argc, ++argv);
+
+ ret = __efi_locate_handle(bs, ALL_HANDLES, NULL, NULL, &handle_count, &handles);
+ if (!ret)
+ efi_dump(bs, handles, handle_count);
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(efi_handle_dump)
+BAREBOX_CMD_HELP_TEXT("Dump all the efi handle with protocol and devpath\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(efi_handle_dump)
+ .cmd = do_efi_handle_dump,
+ BAREBOX_CMD_DESC("Usage: efi_handle_dump")
+ BAREBOX_CMD_OPTS("[a-b-c-d0d1-d3d4d5d6d7] or [a b c d0 d1 d2 d3 d4 d5 d6 d7]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_HELP(cmd_efi_handle_dump_help)
+BAREBOX_CMD_END
diff --git a/commands/ethlog.c b/commands/ethlog.c
new file mode 100644
index 0000000000..21d88bf1cb
--- /dev/null
+++ b/commands/ethlog.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: (c) 2022 Pengutronix,
+// Oleksij Rempel <o.rempel@pengutronix.de>
+
+#include <common.h>
+#include <command.h>
+#include <complete.h>
+#include <environment.h>
+#include <getopt.h>
+#include <net.h>
+
+static void ethlog_rx_monitor(struct eth_device *edev, void *packet,
+ int length)
+{
+ dev_print_hex_dump(&edev->dev, KERN_DEBUG, "rx data <: ",
+ DUMP_PREFIX_OFFSET, 16, 1, packet, length, true);
+ printk("\n");
+}
+
+static void ethlog_tx_monitor(struct eth_device *edev, void *packet,
+ int length)
+{
+ dev_print_hex_dump(&edev->dev, KERN_DEBUG, "tx data >: ",
+ DUMP_PREFIX_OFFSET, 16, 1, packet, length, true);
+ printk("\n");
+}
+
+static int do_ethlog(int argc, char *argv[])
+{
+ struct eth_device *edev;
+ const char *edevname;
+ bool remove = false, promisc = false;
+ int opt, ret;
+
+ while ((opt = getopt(argc, argv, "pr")) > 0) {
+ switch (opt) {
+ case 'p':
+ promisc = true;
+ break;
+ case 'r':
+ remove = true;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (optind == argc)
+ edevname = "eth0";
+ else
+ edevname = argv[optind];
+
+ edev = eth_get_byname(edevname);
+ if (!edev) {
+ printf("No such network device: %s\n", edevname);
+ return 1;
+ }
+
+ if (remove) {
+ edev->tx_monitor = NULL;
+ edev->rx_monitor = NULL;
+ if (promisc)
+ eth_set_promisc(edev, false);
+
+ return 0;
+ }
+
+ if (promisc) {
+ ret = eth_set_promisc(edev, true);
+ if (ret)
+ dev_warn(&edev->dev, "Failed to set promisc mode: %pe\n",
+ ERR_PTR(ret));
+ }
+
+ edev->tx_monitor = ethlog_tx_monitor;
+ edev->rx_monitor = ethlog_rx_monitor;
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(ethlog)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-r", "remove log handler from Ethernet interface")
+BAREBOX_CMD_HELP_OPT("-p", "Enable promisc mode, or disable if -r is used")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(ethlog)
+ .cmd = do_ethlog,
+ BAREBOX_CMD_DESC("ETHLOG - tool to get dump of Ethernet packets")
+ BAREBOX_CMD_OPTS("[-rp] [device]")
+ BAREBOX_CMD_GROUP(CMD_GRP_NET)
+ BAREBOX_CMD_COMPLETE(eth_complete)
+ BAREBOX_CMD_HELP(cmd_ethlog_help)
+BAREBOX_CMD_END
diff --git a/commands/export.c b/commands/export.c
index 8972b7d528..c69f1595c6 100644
--- a/commands/export.c
+++ b/commands/export.c
@@ -20,10 +20,8 @@ static int do_export(int argc, char *argv[])
return COMMAND_ERROR_USAGE;
while (i < argc) {
- if ((ptr = strchr(argv[i], '='))) {
- *ptr++ = 0;
+ if ((ptr = parse_assignment(argv[i])))
setenv(argv[i], ptr);
- }
if (export(argv[i])) {
printf("could not export: %s\n", argv[i]);
return 1;
diff --git a/commands/fbtest.c b/commands/fbtest.c
index ff24a8252a..be1540d3d1 100644
--- a/commands/fbtest.c
+++ b/commands/fbtest.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <errno.h>
@@ -271,9 +273,8 @@ static int do_fbtest(int argc, char *argv[])
sc = fb_open(fbdev);
if (IS_ERR(sc)) {
- int ret = -PTR_ERR(sc);
- printf("fb_open: %s\n", strerror(ret));
- return ret;
+ printf("fb_open: %pe\n", sc);
+ return COMMAND_ERROR;
}
if (!pattern_name) {
diff --git a/commands/filetype.c b/commands/filetype.c
index 818c14fe79..7a556a980d 100644
--- a/commands/filetype.c
+++ b/commands/filetype.c
@@ -66,7 +66,11 @@ static int do_filetype(int argc, char *argv[])
if (S_ISDIR(s.st_mode))
return -EISDIR;
- type = file_name_detect_type(filename);
+ ret = file_name_detect_type(filename, &type);
+ if (ret) {
+ printf("failed to detect type of %s: %s\n", filename, strerror(-ret));
+ return COMMAND_ERROR;
+ }
if (verbose)
printf("%s: %s (%s)\n", filename,
diff --git a/commands/findmnt.c b/commands/findmnt.c
new file mode 100644
index 0000000000..da8f58835f
--- /dev/null
+++ b/commands/findmnt.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: © 2022 Ahmad Fatoum, Pengutronix
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <errno.h>
+#include <getopt.h>
+
+static void print_header(bool *header_printed)
+{
+ if (*header_printed)
+ return;
+ printf("%-20s%-25s%-10s%-20s\n", "TARGET", "SOURCE", "FSTYPE", "OPTIONS");
+ *header_printed = true;
+}
+
+static void report_findmnt(const struct fs_device *fsdev)
+{
+ const char *backingstore;
+
+ backingstore = fsdev->backingstore ?: cdev_name(fsdev->cdev) ?: "none";
+
+ printf("%-20s%-25s%-10s%-20s\n", fsdev->path, backingstore,
+ fsdev->driver->drv.name, fsdev->options);
+}
+
+static int do_findmnt(int argc, char *argv[])
+{
+ bool header_printed = false;
+ struct fs_device *target = NULL;
+ char *device = NULL;
+ int opt, dirfd = AT_FDCWD;
+
+ while ((opt = getopt(argc, argv, "T:")) > 0) {
+ switch(opt) {
+ case 'T':
+ target = get_fsdevice_by_path(dirfd, optarg);
+ if (!target)
+ return COMMAND_ERROR;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if ((target && argc > 0) || (!target && argc > 1))
+ return COMMAND_ERROR_USAGE;
+
+ if (target) {
+ print_header(&header_printed);
+ report_findmnt(target);
+ return 0;
+ }
+
+ if (argv[0]) {
+ device = canonicalize_path(dirfd, argv[0]);
+ if (!device)
+ return COMMAND_ERROR;
+ }
+
+ for_each_fs_device(target) {
+ if (!device || streq_ptr(target->path, device) ||
+ streq_ptr(target->backingstore, device)) {
+ print_header(&header_printed);
+ report_findmnt(target);
+ } else {
+ const char *backingstore;
+ struct cdev *cdev;
+
+ cdev = cdev_by_name(devpath_to_name(device));
+ if (!cdev)
+ continue;
+
+ backingstore = target->backingstore;
+ backingstore += str_has_prefix(backingstore, "/dev/");
+
+ if (streq_ptr(backingstore, cdev->name)) {
+ print_header(&header_printed);
+ report_findmnt(target);
+ }
+ }
+ }
+
+ free(device);
+
+ return header_printed ? 0 : COMMAND_ERROR;
+}
+
+BAREBOX_CMD_HELP_START(findmnt)
+BAREBOX_CMD_HELP_TEXT("findmnt will list all mounted filesystems or search")
+BAREBOX_CMD_HELP_TEXT("for a filesystem when given the mountpoint or the")
+BAREBOX_CMD_HELP_TEXT("source device as an argument")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-T", "mount target file path")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(findmnt)
+ .cmd = do_findmnt,
+ BAREBOX_CMD_DESC("find a file system")
+ BAREBOX_CMD_OPTS("[ DEVICE | -T FILE ]")
+ BAREBOX_CMD_GROUP(CMD_GRP_FILE)
+ BAREBOX_CMD_HELP(cmd_findmnt_help)
+BAREBOX_CMD_END
diff --git a/commands/flash.c b/commands/flash.c
index 3d7c8fd577..5b7060aead 100644
--- a/commands/flash.c
+++ b/commands/flash.c
@@ -25,7 +25,7 @@ static int do_flerase(int argc, char *argv[])
filename = argv[1];
if (stat(filename, &s)) {
- printf("stat %s: %s\n", filename, errno_str());
+ printf("stat %s: %m\n", filename);
return 1;
}
@@ -33,7 +33,7 @@ static int do_flerase(int argc, char *argv[])
fd = open(filename, O_WRONLY);
if (fd < 0) {
- printf("open %s: %s\n", filename, errno_str());
+ printf("open %s: %m\n", filename);
return 1;
}
@@ -89,7 +89,7 @@ static int do_protect(int argc, char *argv[])
prot = 0;
if (stat(filename, &s)) {
- printf("stat %s: %s\n", filename, errno_str());
+ printf("stat %s: %m\n", filename);
return 1;
}
@@ -97,7 +97,7 @@ static int do_protect(int argc, char *argv[])
fd = open(filename, O_WRONLY);
if (fd < 0) {
- printf("open %s: %s\n", filename, errno_str());
+ printf("open %s: %m\n", filename);
return 1;
}
diff --git a/commands/global.c b/commands/global.c
index 15b6a9f3d3..a8ff5ea18f 100644
--- a/commands/global.c
+++ b/commands/global.c
@@ -37,11 +37,7 @@ static int do_global(int argc, char *argv[])
return COMMAND_ERROR_USAGE;
for (i = 0; i < argc; i++) {
- value = strchr(argv[i], '=');
- if (value) {
- *value = 0;
- value++;
- }
+ value = parse_assignment(argv[i]);
if (do_remove)
globalvar_remove(argv[i]);
@@ -54,6 +50,7 @@ static int do_global(int argc, char *argv[])
BAREBOX_CMD_HELP_START(global)
BAREBOX_CMD_HELP_TEXT("Add a new global variable named VAR, optionally set to VALUE.")
+BAREBOX_CMD_HELP_TEXT("Without options, print all global and env (prefixed with *) variables.")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT("-r", "Remove globalvars")
@@ -62,7 +59,7 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(global)
.cmd = do_global,
BAREBOX_CMD_DESC("create or set global variables")
- BAREBOX_CMD_OPTS("[-r] VAR[=VALUE] ...")
+ BAREBOX_CMD_OPTS("[-r] [VAR[=VALUE] ...]")
BAREBOX_CMD_GROUP(CMD_GRP_ENV)
BAREBOX_CMD_HELP(cmd_global_help)
BAREBOX_CMD_COMPLETE(global_complete)
diff --git a/commands/go.c b/commands/go.c
index 0c0b4cb15e..3449a2181a 100644
--- a/commands/go.c
+++ b/commands/go.c
@@ -8,21 +8,44 @@
#include <complete.h>
#include <fs.h>
#include <fcntl.h>
+#include <getopt.h>
#include <linux/ctype.h>
#include <errno.h>
+#define INT_ARGS_MAX 4
+
static int do_go(int argc, char *argv[])
{
void *addr;
int rcode = 1;
int fd = -1;
- int (*func)(int argc, char *argv[]);
+ void (*func)(ulong r0, ulong r1, ulong r2, ulong r3);
+ int opt;
+ ulong arg[INT_ARGS_MAX] = {};
+ bool pass_argv = true;
+
+ while ((opt = getopt(argc, argv, "+si")) > 0) {
+ switch (opt) {
+ case 's':
+ pass_argv = true;
+ break;
+ case 'i':
+ pass_argv = false;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ /* skip options */
+ argv += optind;
+ argc -= optind;
- if (argc < 2)
+ if (argc == 0 || (!pass_argv && argc - 1 > INT_ARGS_MAX))
return COMMAND_ERROR_USAGE;
- if (!isdigit(*argv[1])) {
- fd = open(argv[1], O_RDONLY);
+ if (!isdigit(*argv[0])) {
+ fd = open(argv[0], O_RDONLY);
if (fd < 0) {
perror("open");
goto out;
@@ -34,7 +57,7 @@ static int do_go(int argc, char *argv[])
goto out;
}
} else
- addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ addr = (void *)simple_strtoul(argv[0], NULL, 16);
printf("## Starting application at 0x%p ...\n", addr);
@@ -42,9 +65,28 @@ static int do_go(int argc, char *argv[])
func = addr;
+ if (pass_argv) {
+ arg[0] = argc;
+ arg[1] = (ulong)argv;
+ } else {
+ int i;
+
+ /* skip argv[0] */
+ argc--;
+ argv++;
+
+ for (i = 0; i < argc; i++) {
+ rcode = kstrtoul(argv[i], 0, &arg[i]);
+ if (rcode) {
+ printf("Can't parse \"%s\" as an integer value\n", argv[i]);
+ goto out;
+ }
+ }
+ }
+
shutdown_barebox();
- func(argc - 1, &argv[1]);
+ func(arg[0], arg[1], arg[2], arg[3]);
/*
* The application returned. Since we have shutdown barebox and
@@ -64,12 +106,15 @@ BAREBOX_CMD_HELP_TEXT("Start application at ADDR passing ARG as arguments.")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("If addr does not start with a digit it is interpreted as a filename")
BAREBOX_CMD_HELP_TEXT("in which case the file is memmapped and executed")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-s", "pass all arguments as strings referenced by argc, argv arguments (default)")
+BAREBOX_CMD_HELP_OPT("-i", "pass up to four integer arguments using default calling convention")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(go)
.cmd = do_go,
BAREBOX_CMD_DESC("start application at address or file")
- BAREBOX_CMD_OPTS("ADDR [ARG...]")
+ BAREBOX_CMD_OPTS("[-si] ADDR [ARG...]")
BAREBOX_CMD_GROUP(CMD_GRP_BOOT)
BAREBOX_CMD_HELP(cmd_go_help)
BAREBOX_CMD_COMPLETE(command_var_complete)
diff --git a/commands/gpio.c b/commands/gpio.c
index 955b60e91b..caabb5adc0 100644
--- a/commands/gpio.c
+++ b/commands/gpio.c
@@ -4,27 +4,58 @@
#include <command.h>
#include <errno.h>
#include <gpio.h>
+#include <getopt.h>
static int get_gpio_and_value(int argc, char *argv[],
int *gpio, int *value)
{
- const int count = value ? 3 : 2;
+ struct gpio_chip *chip = NULL;
+ struct device *dev;
+ int count = 1;
int ret = 0;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "d:")) > 0) {
+ switch (opt) {
+ case 'd':
+ dev = find_device(optarg);
+ if (!dev)
+ return -ENODEV;
+
+ chip = gpio_get_chip_by_dev(dev);
+ if (!chip)
+ return -EINVAL;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (value)
+ count++;
- if (argc < count)
+ if (argc < optind + count)
return COMMAND_ERROR_USAGE;
- *gpio = gpio_find_by_name(argv[1]);
+ *gpio = gpio_find_by_name(argv[optind]);
if (*gpio < 0)
- *gpio = gpio_find_by_label(argv[1]);
+ *gpio = gpio_find_by_label(argv[optind]);
if (*gpio < 0) {
- ret = kstrtoint(argv[1], 0, gpio);
+ ret = kstrtoint(argv[optind], 0, gpio);
if (ret < 0)
return ret;
+
+ if (chip)
+ *gpio += chip->base;
+ } else if (chip) {
+ if (gpio_get_chip(*gpio) != chip) {
+ printf("%s: not exporting pin %u\n", dev_name(chip->dev), *gpio);
+ return -EINVAL;
+ }
}
if (value)
- ret = kstrtoint(argv[2], 0, value);
+ ret = kstrtoint(argv[optind + 1], 0, value);
return ret;
}
@@ -47,7 +78,7 @@ static int do_gpio_get_value(int argc, char *argv[])
BAREBOX_CMD_START(gpio_get_value)
.cmd = do_gpio_get_value,
BAREBOX_CMD_DESC("return value of a GPIO pin")
- BAREBOX_CMD_OPTS("GPIO")
+ BAREBOX_CMD_OPTS("[-d CONTROLLER] GPIO")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_END
@@ -67,7 +98,7 @@ static int do_gpio_set_value(int argc, char *argv[])
BAREBOX_CMD_START(gpio_set_value)
.cmd = do_gpio_set_value,
BAREBOX_CMD_DESC("set a GPIO's output value")
- BAREBOX_CMD_OPTS("GPIO VALUE")
+ BAREBOX_CMD_OPTS("[-d CONTROLLER] GPIO VALUE")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_END
@@ -89,7 +120,7 @@ static int do_gpio_direction_input(int argc, char *argv[])
BAREBOX_CMD_START(gpio_direction_input)
.cmd = do_gpio_direction_input,
BAREBOX_CMD_DESC("set direction of a GPIO pin to input")
- BAREBOX_CMD_OPTS("GPIO")
+ BAREBOX_CMD_OPTS("[-d CONTROLLER] GPIO")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_END
@@ -111,6 +142,6 @@ static int do_gpio_direction_output(int argc, char *argv[])
BAREBOX_CMD_START(gpio_direction_output)
.cmd = do_gpio_direction_output,
BAREBOX_CMD_DESC("set direction of a GPIO pin to output")
- BAREBOX_CMD_OPTS("GPIO VALUE")
+ BAREBOX_CMD_OPTS("[-d CONTROLLER] GPIO VALUE")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_END
diff --git a/commands/hab.c b/commands/hab.c
index 97a1701fa5..8ae943a4c8 100644
--- a/commands/hab.c
+++ b/commands/hab.c
@@ -58,7 +58,13 @@ static int do_hab(int argc, char *argv[])
printf("%02x", srk[i]);
printf("\n");
- if (imx_hab_device_locked_down())
+ ret = imx_hab_device_locked_down();
+ if (ret < 0) {
+ printf("failed to determine lockdown mode: '%pe'\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ if (ret)
printf("secure mode\n");
else
printf("devel mode\n");
diff --git a/commands/hashsum.c b/commands/hashsum.c
index bfacee0b92..308faa172a 100644
--- a/commands/hashsum.c
+++ b/commands/hashsum.c
@@ -74,7 +74,7 @@ BAREBOX_CMD_START(md5sum)
BAREBOX_CMD_HELP(cmd_md5sum_help)
BAREBOX_CMD_END
-#endif /* CMD_CMD_MD5SUM */
+#endif /* CONFIG_CMD_MD5SUM */
#ifdef CONFIG_CMD_SHA1SUM
@@ -95,7 +95,7 @@ BAREBOX_CMD_START(sha1sum)
BAREBOX_CMD_HELP(cmd_sha1sum_help)
BAREBOX_CMD_END
-#endif /* CMD_CMD_SHA1SUM */
+#endif /* CONFIG_CMD_SHA1SUM */
#ifdef CONFIG_CMD_SHA224SUM
@@ -116,7 +116,7 @@ BAREBOX_CMD_START(sha224sum)
BAREBOX_CMD_HELP(cmd_sha224sum_help)
BAREBOX_CMD_END
-#endif /* CMD_CMD_SHA224SUM */
+#endif /* CONFIG_CMD_SHA224SUM */
#ifdef CONFIG_CMD_SHA256SUM
@@ -137,7 +137,7 @@ BAREBOX_CMD_START(sha256sum)
BAREBOX_CMD_HELP(cmd_sha256sum_help)
BAREBOX_CMD_END
-#endif /* CMD_CMD_SHA256SUM */
+#endif /* CONFIG_CMD_SHA256SUM */
#ifdef CONFIG_CMD_SHA384SUM
@@ -158,7 +158,7 @@ BAREBOX_CMD_START(sha384sum)
BAREBOX_CMD_HELP(cmd_sha384sum_help)
BAREBOX_CMD_END
-#endif /* CMD_CMD_SHA384SUM */
+#endif /* CONFIG_CMD_SHA384SUM */
#ifdef CONFIG_CMD_SHA512SUM
@@ -179,4 +179,4 @@ BAREBOX_CMD_START(sha512sum)
BAREBOX_CMD_HELP(cmd_sha512sum_help)
BAREBOX_CMD_END
-#endif /* CMD_CMD_SHA512SUM */
+#endif /* CONFIG_CMD_SHA512SUM */
diff --git a/commands/hwclock.c b/commands/hwclock.c
index 1b5c2cd100..c594e070ac 100644
--- a/commands/hwclock.c
+++ b/commands/hwclock.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <getopt.h>
@@ -9,14 +11,6 @@
#include <string.h>
#include <environment.h>
-static char *strchrnul(const char *s, int c)
-{
- while (*s != '\0' && *s != c)
- s++;
-
- return (char *)s;
-}
-
static int sscanf_two_digits(char *s, int *res)
{
char buf[3];
@@ -159,11 +153,9 @@ static int do_hwclock(int argc, char *argv[])
if (env_name) {
unsigned long time;
- char t[12];
rtc_tm_to_time(&tm, &time);
- snprintf(t, 12, "%lu", time);
- setenv(env_name, t);
+ pr_setenv(env_name, "%lu", time);
} else {
printf("%s\n", time_str(&tm));
}
diff --git a/commands/hwmon.c b/commands/hwmon.c
index ace4503c0b..04c3e728c6 100644
--- a/commands/hwmon.c
+++ b/commands/hwmon.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <getopt.h>
diff --git a/commands/i2c.c b/commands/i2c.c
index 53f36dfaab..3a708531ee 100644
--- a/commands/i2c.c
+++ b/commands/i2c.c
@@ -16,10 +16,12 @@ static void i2c_probe_range(struct i2c_adapter *adapter, int startaddr, int stop
printf("probing i2c%d range 0x%02x-0x%02x: ", adapter->nr, startaddr, stopaddr);
for (addr = startaddr; addr <= stopaddr && !ctrlc(); addr++) {
+ u8 buf[1];
struct i2c_msg msg = {
.addr = addr,
- .buf = NULL,
- .len = 0,
+ .buf = buf,
+ .len = sizeof(buf),
+ .flags = I2C_M_RD,
};
int ret = i2c_transfer(adapter, &msg, 1);
if (ret == 1)
@@ -193,7 +195,7 @@ static int do_i2c_read(int argc, char *argv[])
struct i2c_adapter *adapter = NULL;
struct i2c_client client;
u8 *buf;
- int count = -1, addr = -1, reg = -1, verbose = 0, ret, opt, bus = 0, wide = 0;
+ int count = 1, addr = -1, reg = -1, verbose = 0, ret, opt, bus = 0, wide = 0;
while ((opt = getopt(argc, argv, "a:b:c:r:vw")) > 0) {
switch (opt) {
@@ -262,7 +264,7 @@ BAREBOX_CMD_HELP_OPT("-b BUS\t", "i2c bus number (default 0)")
BAREBOX_CMD_HELP_OPT("-a ADDR\t", "i2c device address")
BAREBOX_CMD_HELP_OPT("-r START", "start register (optional, master receive mode if none given)")
BAREBOX_CMD_HELP_OPT("-w\t", "use word (16 bit) wide access")
-BAREBOX_CMD_HELP_OPT("-c COUNT", "byte count")
+BAREBOX_CMD_HELP_OPT("-c COUNT", "byte count (default 1)")
BAREBOX_CMD_HELP_OPT("-v\t", "verbose")
BAREBOX_CMD_HELP_END
diff --git a/commands/imd.c b/commands/imd.c
index 912f065c9e..9f7ac79f8f 100644
--- a/commands/imd.c
+++ b/commands/imd.c
@@ -31,6 +31,7 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-t <type>", "only show information of <type>")
BAREBOX_CMD_HELP_OPT ("-n <no>", "for tags with multiple strings only show string <no>")
BAREBOX_CMD_HELP_OPT ("-s VARNAME", "set variable VARNAME instead of showing information")
+BAREBOX_CMD_HELP_OPT ("-v", "Be verbose")
BAREBOX_CMD_HELP_OPT ("-V", "Verify checksum of FILE")
BAREBOX_CMD_HELP_OPT ("-c", "Create checksum for FILE and write it to the crc32 tag.")
BAREBOX_CMD_HELP_TEXT("")
diff --git a/commands/insmod.c b/commands/insmod.c
index 735dde0222..8f962b62d3 100644
--- a/commands/insmod.c
+++ b/commands/insmod.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <module.h>
diff --git a/commands/internal.h b/commands/internal.h
index 21d1408c91..63c10af28e 100644
--- a/commands/internal.h
+++ b/commands/internal.h
@@ -1,2 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
int __do_digest(struct digest *d, unsigned char *sig,
int argc, char *argv[]);
diff --git a/commands/iomemport.c b/commands/iomemport.c
index d0cfc413c2..f2baa0e293 100644
--- a/commands/iomemport.c
+++ b/commands/iomemport.c
@@ -16,11 +16,14 @@ static void __print_resources(struct resource *res, int indent)
for (i = 0; i < indent; i++)
printf(" ");
- printf("%pa - %pa (size %pa) %s\n",
- &res->start, &res->end, &size, res->name);
+ printf("%pa - %pa (size %pa) %s%s\n",
+ &res->start, &res->end, &size,
+ res->flags & IORESOURCE_BUSY ? "[R] " : "",
+ res->name);
- list_for_each_entry(r, &res->children, sibling)
+ list_for_each_entry(r, &res->children, sibling) {
__print_resources(r, indent + 1);
+ }
}
static void print_resources(struct resource *res)
diff --git a/commands/kallsyms.c b/commands/kallsyms.c
new file mode 100644
index 0000000000..163cd99c10
--- /dev/null
+++ b/commands/kallsyms.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * kallsyms.c - translate address to symbols
+ */
+
+#include <common.h>
+#include <kallsyms.h>
+#include <command.h>
+#include <malloc.h>
+#include <complete.h>
+#include <getopt.h>
+#include <string.h>
+
+static int do_kallsyms(int argc, char *argv[])
+{
+ unsigned long addr;
+
+ if (argc != 2)
+ return COMMAND_ERROR_USAGE;
+
+ if (kstrtoul(argv[1], 16, &addr) == 0) {
+ char sym[KSYM_SYMBOL_LEN];
+
+ sprint_symbol(sym, addr);
+
+ printf("%s\n", sym);
+ return 0;
+ }
+
+ if ((addr = kallsyms_lookup_name(argv[1]))) {
+ printf("0x%08lx\n", addr);
+ return 0;
+ }
+
+ return COMMAND_ERROR;
+}
+
+BAREBOX_CMD_HELP_START(kallsyms)
+BAREBOX_CMD_HELP_TEXT("Lookup address or symbol using kallsyms table")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(kallsyms)
+ .cmd = do_kallsyms,
+ BAREBOX_CMD_DESC("query kallsyms table")
+ BAREBOX_CMD_OPTS("[SYMBOL | ADDRESS]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+ BAREBOX_CMD_HELP(cmd_kallsyms_help)
+BAREBOX_CMD_END
diff --git a/commands/keystore.c b/commands/keystore.c
index 4f6a7ef190..40bcb7105d 100644
--- a/commands/keystore.c
+++ b/commands/keystore.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <getopt.h>
@@ -15,7 +17,7 @@ static int do_keystore(int argc, char *argv[])
const char *file = NULL;
char *secret_str = NULL;
void *secret;
- size_t s_len;
+ size_t s_len = 0;
while ((opt = getopt(argc, argv, "rs:f:")) > 0) {
switch (opt) {
diff --git a/commands/linux16.c b/commands/linux16.c
deleted file mode 100644
index 73e402d877..0000000000
--- a/commands/linux16.c
+++ /dev/null
@@ -1,331 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// SPDX-FileCopyrightText: © 2009 Juergen Beisert, Pengutronix
-
-/*
- * In parts from the GRUB2 project:
- *
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc.
- */
-
-#include <common.h>
-#include <command.h>
-#include <environment.h>
-#include <fs.h>
-#include <errno.h>
-#include <libfile.h>
-#include <getopt.h>
-#include <malloc.h>
-#include <boot.h>
-#include <asm/syslib.h>
-
-/** FIXME */
-#define LINUX_MAGIC_SIGNATURE 0x53726448 /* "HdrS" */
-
-/** FIXME */
-#define LINUX_FLAG_BIG_KERNEL 0x1
-
-/** FIXME */
-#define LINUX_BOOT_LOADER_TYPE 0x72
-
-/** FIXME */
-#define LINUX_DEFAULT_SETUP_SECTS 4
-
-/** FIXME */
-#define LINUX_MAX_SETUP_SECTS 64
-
-/** FIXME */
-#define LINUX_OLD_REAL_MODE_SEGMT 0x9000
-
-/** FIXME */
-#define LINUX_OLD_REAL_MODE_ADDR (LINUX_OLD_REAL_MODE_SEGMT << 4)
-
-/** FIXME */
-#define LINUX_HEAP_END_OFFSET (LINUX_OLD_REAL_MODE_SEGMT - 0x200)
-
-/** FIXME */
-#define LINUX_FLAG_CAN_USE_HEAP 0x80
-
-/** Define kernel command lines's start offset in the setup segment */
-#define LINUX_CL_OFFSET 0x9000
-
-/** Define kernel command lines's end offset */
-#define LINUX_CL_END_OFFSET 0x90FF
-
-/** FIXME */
-#define LINUX_CL_MAGIC 0xA33F
-
-/** FIXME */
-#define LINUX_SETUP_MOVE_SIZE 0x9100
-
-/** Sector size */
-#define DISK_SECTOR_BITS 9
-#define DISK_SECTOR_SIZE 0x200
-
-/** Where to load a bzImage */
-#define LINUX_BZIMAGE_ADDR 0x100000
-
-struct linux_kernel_header {
- /* first sector of the image */
- uint8_t code1[0x0020];
- uint16_t cl_magic; /**< Magic number 0xA33F */
- uint16_t cl_offset; /**< The offset of command line */
- uint8_t code2[0x01F1 - 0x0020 - 2 - 2];
- uint8_t setup_sects; /**< The size of the setup in sectors */
- uint16_t root_flags; /**< If the root is mounted readonly */
- uint16_t syssize; /**< obsolete */
- uint16_t swap_dev; /**< obsolete */
- uint16_t ram_size; /**< obsolete */
- uint16_t vid_mode; /**< Video mode control */
- uint16_t root_dev; /**< Default root device number */
- uint16_t boot_flag; /**< 0xAA55 magic number */
-
- /* second sector of the image */
- uint16_t jump; /**< Jump instruction (this is code!) */
- uint32_t header; /**< Magic signature "HdrS" */
- uint16_t version; /**< Boot protocol version supported */
- uint32_t realmode_swtch; /**< Boot loader hook */
- uint16_t start_sys; /**< The load-low segment (obsolete) */
- uint16_t kernel_version; /**< Points to kernel version string */
- uint8_t type_of_loader; /**< Boot loader identifier */
-#define LINUX_LOADER_ID_LILO 0x0
-#define LINUX_LOADER_ID_LOADLIN 0x1
-#define LINUX_LOADER_ID_BOOTSECT 0x2
-#define LINUX_LOADER_ID_SYSLINUX 0x3
-#define LINUX_LOADER_ID_ETHERBOOT 0x4
-#define LINUX_LOADER_ID_ELILO 0x5
-#define LINUX_LOADER_ID_GRUB 0x7
-#define LINUX_LOADER_ID_UBOOT 0x8
-#define LINUX_LOADER_ID_XEN 0x9
-#define LINUX_LOADER_ID_GUJIN 0xa
-#define LINUX_LOADER_ID_QEMU 0xb
- uint8_t loadflags; /**< Boot protocol option flags */
- uint16_t setup_move_size; /**< Move to high memory size */
- uint32_t code32_start; /**< Boot loader hook */
- uint32_t ramdisk_image; /**< initrd load address */
- uint32_t ramdisk_size; /**< initrd size */
- uint32_t bootsect_kludge; /**< obsolete */
- uint16_t heap_end_ptr; /**< Free memory after setup end */
- uint8_t ext_loader_ver; /**< boot loader's extension of the version number */
- uint8_t ext_loader_type; /**< boot loader's extension of its type */
- char *cmd_line_ptr; /**< Points to the kernel command line */
- uint32_t initrd_addr_max; /**< Highest address for initrd */
-#if 0
- /* for the records only. These members are defined in
- * more recent Linux kernels
- */
- uint32_t kernel_alignment; /**< Alignment unit required by the kernel */
- uint8_t relocatable_kernel; /** */
- uint8_t min_alignment; /** */
- uint32_t cmdline_size; /** */
- uint32_t hardware_subarch; /** */
- uint64_t hardware_subarch_data; /** */
- uint32_t payload_offset; /** */
- uint32_t payload_length; /** */
- uint64_t setup_data; /** */
- uint64_t pref_address; /** */
- uint32_t init_size; /** */
-#endif
-} __attribute__ ((packed));
-
-/* This is -1. Keep this value in sync with the kernel */
-#define NORMAL_VGA 0xffff /* 80x25 mode */
-#define ASK_VGA 0xfffd /* ask for it at bootup */
-
-/**
- * Load an x86 Linux kernel bzImage and start it
- * @param argc parameter count
- * @param argv list of parameter
- *
- * Loads an x86 bzImage, checks for its integrity, stores the two parts
- * (setup = 'real mode code' and kernel = 'protected mode code') to their
- * default locations, switches back to real mode and runs the setup code.
- */
-static int do_linux16(int argc, char *argv[])
-{
- struct linux_kernel_header *lh = NULL;
- int rc, opt;
- unsigned setup_sects;
- unsigned real_mode_size;
- int vid_mode = NORMAL_VGA;
- size_t image_size;
- const char *cmdline = linux_bootargs_get();
- const char *kernel_file;
-
- while((opt = getopt(argc, argv, "v:")) > 0) {
- switch(opt) {
- case 'v':
- vid_mode = simple_strtoul(optarg, NULL, 0);
- if (vid_mode == 0) {
- if (!strcmp(optarg, "ask"))
- vid_mode = ASK_VGA;
- else {
- printf("Unknown video mode: %s\n", optarg);
- return 1;
- }
- }
- break;
- default:
- return COMMAND_ERROR_USAGE;
- }
- }
-
- if (optind == argc) {
- printf("No kernel filename given\n");
- return 1;
- }
- kernel_file = argv[optind];
-
- lh = read_file(kernel_file, &image_size);
- if (lh == NULL) {
- printf("Cannot read file '%s'\n", argv[1]);
- return 1;
- }
-
- if (lh->boot_flag != 0xaa55) {
- printf("File '%s' has invalid magic number\n", argv[1]);
- rc = 1;
- goto on_error;
- }
-
- if (lh->setup_sects > LINUX_MAX_SETUP_SECTS) {
- printf("File '%s' contains too many setup sectors\n", argv[1]);
- rc = 1;
- goto on_error;
- }
-
- setup_sects = lh->setup_sects;
-
- printf("Found a %d.%d image header\n", lh->version >> 8, lh->version & 0xFF);
-
- if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200) {
- /* kernel is recent enough */
- ;
- if (!(lh->loadflags & LINUX_FLAG_BIG_KERNEL)) {
- printf("Cannot load a classic zImage. Use a bzImage instead\n");
- goto on_error;
- }
- lh->type_of_loader = LINUX_BOOT_LOADER_TYPE; /* TODO */
-
- if (lh->version >= 0x0201) {
- lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
- lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
- }
-
- if (lh->version >= 0x0202)
- lh->cmd_line_ptr = (void*)(LINUX_OLD_REAL_MODE_ADDR + LINUX_CL_OFFSET); /* FIXME */
- else {
- lh->cl_magic = LINUX_CL_MAGIC;
- lh->cl_offset = LINUX_CL_OFFSET;
- lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
- }
- } else {
- printf("Kernel too old to handle\n");
- rc = 1;
- goto on_error;
- }
-
- if (strlen(cmdline) >= (LINUX_CL_END_OFFSET - LINUX_CL_OFFSET)) {
- printf("Kernel command line exceeds the available space\n");
- rc = 1;
- goto on_error;
- }
-
- /*
- * The kernel does not check for the "vga=<val>" kernel command line
- * parameter anymore. It expects this kind of information in the
- * boot parameters instead.
- */
- if (vid_mode != NORMAL_VGA)
- lh->vid_mode = vid_mode;
-
- /* If SETUP_SECTS is not set, set it to the default. */
- if (setup_sects == 0) {
- printf("Fixing setup sector count\n");
- setup_sects = LINUX_DEFAULT_SETUP_SECTS;
- }
-
- if (setup_sects >= 15) {
- void *src = lh;
- if (lh->kernel_version != 0)
- printf("Kernel version: '%s'\n",
- (char *)src + lh->kernel_version + DISK_SECTOR_SIZE);
- }
-
- /*
- * Size of the real mode part to handle in a separate way
- */
- real_mode_size = (setup_sects << DISK_SECTOR_BITS) + DISK_SECTOR_SIZE;
-
- /*
- * real mode space hole extended memory
- * |---------------------------------------------->|----------->|------------------------------>
- * 0 0xa0000 0x100000
- * <-1-|----------2-----------><-3- |
- * 0x7e00 0x90000
- * <-4--|-5--> |---------6------------->
- *
- * 1) real mode stack
- * 2) barebox code
- * 3) flat mode stack
- * 4) realmode stack when starting a Linux kernel
- * 5) Kernel's real mode setup code
- * 6) compressed kernel image
- */
- /*
- * Parts of the image we know:
- * - real mode part
- * - kernel payload
- */
- /*
- * NOTE: This part is dangerous, as it copies some image content to
- * various locations in the main memory. This could overwrite important
- * data of the running barebox (hopefully not)
- */
- /* copy the real mode part of the image to the 9th segment */
- memcpy((void*)LINUX_OLD_REAL_MODE_ADDR, lh, LINUX_SETUP_MOVE_SIZE);
-
- /* TODO add 'BOOT_IMAGE=<file>' and 'auto' if no user intervention was done (in front of all other params) */
- /* copy also the command line into this area */
- memcpy((void*)(LINUX_OLD_REAL_MODE_ADDR + LINUX_CL_OFFSET), cmdline, strlen(cmdline) + 1);
- printf("Using kernel command line: '%s'\n", cmdline);
-
- /* copy the compressed image part to its final address the setup code expects it
- * Note: The protected mode part starts at offset (setup_sects + 1) * 512
- */
- memcpy((void*)LINUX_BZIMAGE_ADDR, ((void*)lh) + real_mode_size, image_size - real_mode_size);
-
- /*
- * switch back to real mode now and start the real mode part of the
- * image at address "(LINUX_OLD_REAL_MODE_ADDR >> 4) + 0x20:0x0000"
- * which means "0x9020:0x000" -> 0x90200
- */
- bios_start_linux(LINUX_OLD_REAL_MODE_SEGMT); /* does not return */
-
-on_error:
- if (lh != NULL)
- free(lh);
-
- return rc;
-}
-
-BAREBOX_CMD_HELP_START(linux16)
-BAREBOX_CMD_HELP_TEXT("Load kernel from FILE and boot on x86 in real-mode.")
-BAREBOX_CMD_HELP_TEXT("")
-BAREBOX_CMD_HELP_TEXT("Only kernel images in bzImage format are supported by now.")
-BAREBOX_CMD_HELP_TEXT("")
-BAREBOX_CMD_HELP_TEXT("For the video mode refer the Linux kernel documentation")
-BAREBOX_CMD_HELP_TEXT("'Documentation/fb/vesafb.txt' for correct VESA mode numbers. Use 'ask'")
-BAREBOX_CMD_HELP_TEXT("instead of a number to make Linux for options..")
-BAREBOX_CMD_HELP_TEXT("")
-BAREBOX_CMD_HELP_TEXT("Options:")
-BAREBOX_CMD_HELP_OPT ("-v VESAMODE", "set VESAMODE")
-BAREBOX_CMD_HELP_END
-
-BAREBOX_CMD_START(linux16)
- .cmd = do_linux16,
- BAREBOX_CMD_DESC("boot a linux kernel on x86 via real-mode code")
- BAREBOX_CMD_OPTS("[-v VESAMODE] FILE")
- BAREBOX_CMD_GROUP(CMD_GRP_BOOT)
- BAREBOX_CMD_HELP(cmd_linux16_help)
-BAREBOX_CMD_END
diff --git a/commands/loadb.c b/commands/loadb.c
index 17d3af84b5..140d3743f6 100644
--- a/commands/loadb.c
+++ b/commands/loadb.c
@@ -542,7 +542,6 @@ packet_error:
static ulong load_serial_bin(void)
{
int size, i;
- char buf[32];
/* Try to allocate the buffer we shall write to files */
write_buffer = malloc(MAX_WRITE_BUFFER);
@@ -576,8 +575,7 @@ static ulong load_serial_bin(void)
write_idx = 0;
}
printf("## Total Size = 0x%08x = %d Bytes\n", size, size);
- sprintf(buf, "%X", size);
- setenv("filesize", buf);
+ pr_setenv("filesize", "%X", size);
err_quit:
free(write_buffer);
@@ -648,7 +646,7 @@ static int do_load_serial_bin(int argc, char *argv[])
/* File should exist */
ofd = open_and_lseek(output_file, O_WRONLY | O_CREAT, offset);
if (ofd < 0) {
- perror(argv[0]);
+ printf("Could not open \"%s\": %m\n", output_file);
return 3;
}
diff --git a/commands/loadenv.c b/commands/loadenv.c
index 279ee52da5..ddbf66b764 100644
--- a/commands/loadenv.c
+++ b/commands/loadenv.c
@@ -18,7 +18,8 @@
static int do_loadenv(int argc, char *argv[])
{
- char *filename = NULL, *dirname;
+ const char *filename = NULL;
+ char *dirname;
unsigned flags = 0;
int opt, ret;
int scrub = 0;
diff --git a/commands/loads.c b/commands/loads.c
index 8260673c51..7c5df31251 100644
--- a/commands/loads.c
+++ b/commands/loads.c
@@ -65,7 +65,6 @@ static ulong load_serial(ulong offset)
int type; /* return code for record type */
ulong addr; /* load address from S-Record */
ulong size; /* number of bytes transferred */
- char buf[32];
ulong store_addr;
ulong start_addr = ~0;
ulong end_addr = 0;
@@ -100,8 +99,7 @@ static ulong load_serial(ulong offset)
"## Total Size = 0x%08lX = %ld Bytes\n",
start_addr, end_addr, size, size
);
- sprintf(buf, "%lX", size);
- setenv("filesize", buf);
+ pr_setenv("filesize", "%lX", size);
return addr;
case SREC_START:
break;
diff --git a/commands/loadxy.c b/commands/loadxy.c
index 66daa117d9..e2d1a11a2c 100644
--- a/commands/loadxy.c
+++ b/commands/loadxy.c
@@ -165,7 +165,7 @@ static int do_loadx(int argc, char *argv[])
/* File should exist */
ofd = open_and_lseek(output_file, O_WRONLY | O_CREAT, offset);
if (ofd < 0) {
- perror(argv[0]);
+ printf("Could not open \"%s\": %m\n", output_file);
return 3;
}
diff --git a/commands/ls.c b/commands/ls.c
index bedf2e1c42..09a20e0a23 100644
--- a/commands/ls.c
+++ b/commands/ls.c
@@ -63,10 +63,10 @@ int ls(const char *path, ulong flags)
if (stat(path, &s))
return -errno;
- if (flags & LS_SHOWARG && s.st_mode & S_IFDIR)
+ if (flags & LS_SHOWARG && S_ISDIR(s.st_mode))
printf("%s:\n", path);
- if (!(s.st_mode & S_IFDIR)) {
+ if (!S_ISDIR(s.st_mode)) {
ls_one(path, path);
return 0;
}
@@ -112,7 +112,7 @@ int ls(const char *path, ulong flags)
continue;
}
- if (s.st_mode & S_IFDIR)
+ if (S_ISDIR(s.st_mode))
ls(tmp, flags);
}
@@ -164,14 +164,13 @@ static int do_ls(int argc, char *argv[])
while (o < argc) {
ret = stat(argv[o], &s);
if (ret) {
- printf("%s: %s: %s\n", argv[0],
- argv[o], errno_str());
+ printf("%s: %s: %m\n", argv[0], argv[o]);
o++;
exitcode = COMMAND_ERROR;
continue;
}
- if (!(s.st_mode & S_IFDIR)) {
+ if (!S_ISDIR(s.st_mode)) {
if (flags & LS_COLUMN)
string_list_add_sorted(&sl, argv[o]);
else
@@ -197,7 +196,7 @@ static int do_ls(int argc, char *argv[])
continue;
}
- if (s.st_mode & S_IFDIR) {
+ if (S_ISDIR(s.st_mode)) {
ret = ls(argv[o], flags);
if (ret) {
perror("ls");
diff --git a/commands/lsmod.c b/commands/lsmod.c
index 711c1c66dc..3d7ce40430 100644
--- a/commands/lsmod.c
+++ b/commands/lsmod.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <complete.h>
diff --git a/commands/magicvar.c b/commands/magicvar.c
index 8740784ed2..01acc741ac 100644
--- a/commands/magicvar.c
+++ b/commands/magicvar.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <getopt.h>
diff --git a/commands/md.c b/commands/md.c
index ef6a1e1bc0..f3758f571f 100644
--- a/commands/md.c
+++ b/commands/md.c
@@ -49,8 +49,10 @@ static int do_mem_md(int argc, char *argv[])
}
fd = open_and_lseek(filename, mode | O_RDONLY, start);
- if (fd < 0)
+ if (fd < 0) {
+ printf("Could not open \"%s\": %m\n", filename);
return 1;
+ }
map = memmap(fd, PROT_READ);
if (map != MAP_FAILED) {
@@ -59,7 +61,7 @@ static int do_mem_md(int argc, char *argv[])
goto out;
}
- buf = xmalloc(RW_BUF_SIZE);
+ buf = xzalloc(RW_BUF_SIZE + 7);
do {
now = min(size, (loff_t)RW_BUF_SIZE);
@@ -88,7 +90,7 @@ out:
BAREBOX_CMD_HELP_START(md)
-BAREBOX_CMD_HELP_TEXT("Display (hex dump) a memory region.")
+BAREBOX_CMD_HELP_TEXT("Display (hex dump) a memory REGION.")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-b", "byte access")
@@ -108,7 +110,7 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(md)
.cmd = do_mem_md,
BAREBOX_CMD_DESC("memory display")
- BAREBOX_CMD_OPTS("[-bwlsx] REGION")
+ BAREBOX_CMD_OPTS("[-bwlqx] [-s FILE] REGION")
BAREBOX_CMD_GROUP(CMD_GRP_MEM)
BAREBOX_CMD_HELP(cmd_md_help)
BAREBOX_CMD_END
diff --git a/commands/memcmp.c b/commands/memcmp.c
index 2b3783d66a..8122b99f17 100644
--- a/commands/memcmp.c
+++ b/commands/memcmp.c
@@ -97,7 +97,7 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(memcmp)
.cmd = do_memcmp,
BAREBOX_CMD_DESC("memory compare")
- BAREBOX_CMD_OPTS("[-bwlsd] ADDR1 ADDR2 COUNT")
+ BAREBOX_CMD_OPTS("[-bwlq] [-s FILE] [-d FILE] ADDR1 ADDR2 COUNT")
BAREBOX_CMD_GROUP(CMD_GRP_MEM)
BAREBOX_CMD_HELP(cmd_memcmp_help)
BAREBOX_CMD_END
diff --git a/commands/memcpy.c b/commands/memcpy.c
index 2477bba359..1b480f27f0 100644
--- a/commands/memcpy.c
+++ b/commands/memcpy.c
@@ -72,7 +72,9 @@ out:
}
BAREBOX_CMD_HELP_START(memcpy)
-BAREBOX_CMD_HELP_TEXT("Copy memory at SRC of COUNT bytes to DEST")
+BAREBOX_CMD_HELP_TEXT("Copy memory of COUNT bytes from offsets SRC to DEST.")
+BAREBOX_CMD_HELP_TEXT("If source is a file, COUNT can be left unspecified")
+BAREBOX_CMD_HELP_TEXT("in which case the whole file is copied.")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-b", "byte access")
@@ -86,7 +88,7 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(memcpy)
.cmd = do_memcpy,
BAREBOX_CMD_DESC("memory copy")
- BAREBOX_CMD_OPTS("[-bwlsd] SRC DEST COUNT")
+ BAREBOX_CMD_OPTS("[-bwlq] [-s FILE] [-d FILE] SRC DEST COUNT")
BAREBOX_CMD_GROUP(CMD_GRP_MEM)
BAREBOX_CMD_HELP(cmd_memcpy_help)
BAREBOX_CMD_END
diff --git a/commands/memset.c b/commands/memset.c
index 716cba26de..1139691f2f 100644
--- a/commands/memset.c
+++ b/commands/memset.c
@@ -41,8 +41,10 @@ static int do_memset(int argc, char *argv[])
n = strtoull_suffix(argv[optind + 2], NULL, 0);
fd = open_and_lseek(file, mode | O_WRONLY | O_CREAT, s);
- if (fd < 0)
+ if (fd < 0) {
+ printf("Could not open \"%s\": %m\n", file);
return 1;
+ }
buf = xmalloc(RW_BUF_SIZE);
memset(buf, c, RW_BUF_SIZE);
@@ -84,7 +86,7 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(memset)
.cmd = do_memset,
BAREBOX_CMD_DESC("memory fill")
- BAREBOX_CMD_OPTS("[-bwld] ADDR DATA COUNT")
+ BAREBOX_CMD_OPTS("[-bwlq [-d FILE] ADDR DATA COUNT")
BAREBOX_CMD_GROUP(CMD_GRP_MEM)
BAREBOX_CMD_HELP(cmd_memset_help)
BAREBOX_CMD_END
diff --git a/commands/memtest.c b/commands/memtest.c
index 864947fa94..9fa148b3aa 100644
--- a/commands/memtest.c
+++ b/commands/memtest.c
@@ -15,6 +15,7 @@
static int do_test_one_area(struct mem_test_resource *r, int bus_only,
unsigned cache_flag)
{
+ unsigned flags = MEMTEST_VERBOSE;
int ret;
printf("Testing memory space: %pa -> %pa:\n",
@@ -22,14 +23,14 @@ static int do_test_one_area(struct mem_test_resource *r, int bus_only,
remap_range((void *)r->r->start, resource_size(r->r), cache_flag);
- ret = mem_test_bus_integrity(r->r->start, r->r->end);
+ ret = mem_test_bus_integrity(r->r->start, r->r->end, flags);
if (ret < 0)
return ret;
if (bus_only)
return 0;
- ret = mem_test_moving_inversions(r->r->start, r->r->end);
+ ret = mem_test_moving_inversions(r->r->start, r->r->end, flags);
if (ret < 0)
return ret;
printf("done.\n\n");
diff --git a/commands/memtester/Makefile b/commands/memtester/Makefile
new file mode 100644
index 0000000000..b410813af7
--- /dev/null
+++ b/commands/memtester/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += tests.o memtester.o
diff --git a/commands/memtester/memtester.c b/commands/memtester/memtester.c
new file mode 100644
index 0000000000..f4adbfc855
--- /dev/null
+++ b/commands/memtester/memtester.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * memtester version 4
+ *
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ *
+ */
+
+#define __version__ "4.3.0"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <fs.h>
+
+#include "types.h"
+#include "sizes.h"
+#include "tests.h"
+
+#define EXIT_FAIL_NONSTARTER COMMAND_ERROR
+#define EXIT_FAIL_ADDRESSLINES 0x02
+#define EXIT_FAIL_OTHERTEST 0x04
+
+static struct test tests[] = {
+ { "Random Value", test_random_value },
+ { "Compare XOR", test_xor_comparison },
+ { "Compare SUB", test_sub_comparison },
+ { "Compare MUL", test_mul_comparison },
+ { "Compare DIV",test_div_comparison },
+ { "Compare OR", test_or_comparison },
+ { "Compare AND", test_and_comparison },
+ { "Sequential Increment", test_seqinc_comparison },
+ { "Solid Bits", test_solidbits_comparison },
+ { "Block Sequential", test_blockseq_comparison },
+ { "Checkerboard", test_checkerboard_comparison },
+ { "Bit Spread", test_bitspread_comparison },
+ { "Bit Flip", test_bitflip_comparison },
+ { "Walking Ones", test_walkbits1_comparison },
+ { "Walking Zeroes", test_walkbits0_comparison },
+ { "8-bit Writes", test_8bit_wide_random },
+ { "16-bit Writes", test_16bit_wide_random },
+ { NULL, NULL }
+};
+
+/* Function declarations */
+
+/* Global vars - so tests have access to this information */
+int memtester_use_phys;
+off_t memtester_physaddrbase;
+
+static int do_memtester(int argc, char **argv) {
+ ul loops, loop, i;
+ size_t wantmb, wantbytes, bufsize,
+ halflen, count;
+ void *buf, *aligned;
+ ulv *bufa, *bufb;
+ int exit_code = 0, ret;
+ int memfd = 0, opt;
+ size_t maxbytes = -1; /* addressable memory, in bytes */
+ size_t maxmb = (maxbytes >> 20) + 1; /* addressable memory, in MB */
+ /* Device to mmap memory from with -p, default is normal core */
+ char *device_name = "/dev/mem";
+ struct stat statbuf;
+ int device_specified = 0;
+ ul testmask = 0;
+
+ memtester_use_phys = 0;
+ memtester_physaddrbase = 0;
+
+ printf("memtester version " __version__ " (%d-bit)\n", UL_LEN);
+ printf("Copyright (C) 2001-2012 Charles Cazabon.\n");
+ printf("Licensed under the GNU General Public License version 2 (only).\n");
+ printf("\n");
+
+ while ((opt = getopt(argc, argv, "p:d:m:")) != -1) {
+ ull t;
+
+ switch (opt) {
+ case 'm':
+ if (kstrtoul(optarg, 0, &testmask)) {
+ printf("error parsing MEMTESTER_TEST_MASK %s: %s\n",
+ optarg, strerror(errno));
+ return COMMAND_ERROR_USAGE;
+ }
+ printf("using testmask 0x%lx\n", testmask);
+ break;
+ case 'p':
+ if (kstrtoull(optarg, 0, &t)) {
+ printf("failed to parse physaddrbase arg; should be hex "
+ "address (0x123...)\n");
+ return COMMAND_ERROR_USAGE;
+ }
+ memtester_physaddrbase = (off_t)t;
+ memtester_use_phys = 1;
+ break;
+ case 'd':
+ if (stat(optarg,&statbuf)) {
+ printf("can not use %s as device: %s\n", optarg,
+ strerror(errno));
+ return COMMAND_ERROR_USAGE;
+ } else {
+ if (!S_ISCHR(statbuf.st_mode) && !S_ISBLK(statbuf.st_mode)) {
+ printf("can not mmap non-char device %s\n",
+ optarg);
+ return COMMAND_ERROR_USAGE;
+ } else {
+ device_name = optarg;
+ device_specified = 1;
+ }
+ }
+ break;
+ default: /* '?' */
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+ if (device_specified && !memtester_use_phys) {
+ printf("for mem device, physaddrbase (-p) must be specified\n");
+ return COMMAND_ERROR_USAGE;
+ }
+
+ if (optind >= argc) {
+ printf("need memory argument, in MB\n");
+ return COMMAND_ERROR_USAGE;
+ }
+
+ wantbytes = (size_t) strtoull_suffix(argv[optind], 0, 0);
+ if (wantbytes < 2 * sizeof(ul)) {
+ printf("need at least %zuB of memory to test\n", 2 * sizeof(ul));
+ return COMMAND_ERROR_USAGE;
+ }
+ wantmb = (wantbytes >> 20);
+ optind++;
+ if (wantmb > maxmb) {
+ printf("This system can only address %llu MB.\n", (ull) maxmb);
+ return EXIT_FAIL_NONSTARTER;
+ }
+
+ if (optind >= argc) {
+ loops = 0;
+ } else {
+ if (kstrtoul(argv[optind], 0, &loops)) {
+ printf("failed to parse number of loops");
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ printf("want %lluMB (%llu bytes)\n", (ull) wantmb, (ull) wantbytes);
+ buf = NULL;
+
+ if (memtester_use_phys) {
+ memfd = open(device_name, O_RDWR);
+ if (memfd == -1) {
+ printf("failed to open %s for physical memory: %s\n",
+ device_name, strerror(errno));
+ return EXIT_FAIL_NONSTARTER;
+ }
+ buf = memmap(memfd, PROT_READ | PROT_WRITE) + memtester_physaddrbase;
+ if (buf == MAP_FAILED) {
+ printf("failed to mmap %s for physical memory: %s\n",
+ device_name, strerror(errno));
+ close(memfd);
+ return EXIT_FAIL_NONSTARTER;
+ }
+
+ bufsize = wantbytes; /* accept no less */
+ } else {
+ buf = malloc(wantbytes);
+ if (!buf)
+ return -ENOMEM;
+
+ printf("got %lluMB (%llu bytes)\n", (ull) wantbytes >> 20,
+ (ull) wantbytes);
+ }
+ bufsize = wantbytes;
+ aligned = buf;
+
+ printf("buffer @ 0x%p\n", buf);
+
+ halflen = bufsize / 2;
+ count = halflen / sizeof(ul);
+ bufa = (ulv *) aligned;
+ bufb = (ulv *) ((size_t) aligned + halflen);
+
+ for(loop=1; ((!loops) || loop <= loops); loop++) {
+ printf("Loop %lu", loop);
+ if (loops) {
+ printf("/%lu", loops);
+ }
+ printf(":\n");
+ printf(" %-20s: ", "Stuck Address");
+ ret = test_stuck_address(aligned, bufsize / sizeof(ul));
+ if (!ret) {
+ printf("ok\n");
+ } else if (ret == -EINTR) {
+ goto out;
+ } else {
+ exit_code |= EXIT_FAIL_ADDRESSLINES;
+ }
+ for (i=0;;i++) {
+ if (!tests[i].name) break;
+ /* If using a custom testmask, only run this test if the
+ bit corresponding to this test was set by the user.
+ */
+ if (testmask && (!((1 << i) & testmask))) {
+ continue;
+ }
+ printf(" %-20s: ", tests[i].name);
+ ret = tests[i].fp(bufa, bufb, count);
+ if (!ret) {
+ printf("ok\n");
+ } else if (ret == -EINTR) {
+ goto out;
+ } else {
+ exit_code |= EXIT_FAIL_OTHERTEST;
+ }
+ }
+ printf("\n");
+ }
+out:
+ if (memtester_use_phys)
+ close(memfd);
+ else
+ free(buf);
+ printf("Done.\n");
+ if (!exit_code)
+ return 0;
+ printf("%s FAILED: 0x%x\n", argv[0], exit_code);
+ return COMMAND_ERROR;
+}
+
+BAREBOX_CMD_HELP_START(memtester)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_TEXT("-p PHYSADDR")
+BAREBOX_CMD_HELP_TEXT(" tells memtester to test a specific region of memory starting at physical")
+BAREBOX_CMD_HELP_TEXT(" address PHYSADDR (given in hex), by mmaping a device specified by the -d")
+BAREBOX_CMD_HELP_TEXT(" option (below, or /dev/mem by default).")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("-d DEVICE")
+BAREBOX_CMD_HELP_TEXT(" a device to mmap")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("-m TESTMASK")
+BAREBOX_CMD_HELP_TEXT(" bitmask to select desired tests")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("MEMORY ")
+BAREBOX_CMD_HELP_TEXT(" the amount of memory to allocate and test in bytes. You")
+BAREBOX_CMD_HELP_TEXT(" can include a suffix of K, M, or G to indicate kilobytes, ")
+BAREBOX_CMD_HELP_TEXT(" megabytes, or gigabytes respectively.")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("ITERATIONS")
+BAREBOX_CMD_HELP_TEXT(" (optional) number of loops to iterate through. Default is infinite.")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(memtester)
+ .cmd = do_memtester,
+ BAREBOX_CMD_DESC("memory stress-testing")
+ BAREBOX_CMD_OPTS("[-p PHYSADDR [-d DEVICE]] [-m TESTMASK] <MEMORY>[k|M|G] [ITERATIONS]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MEM)
+ BAREBOX_CMD_HELP(cmd_memtester_help)
+BAREBOX_CMD_END
diff --git a/commands/memtester/memtester.h b/commands/memtester/memtester.h
new file mode 100644
index 0000000000..a683cd9d65
--- /dev/null
+++ b/commands/memtester/memtester.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple (yet, for some reason, very effective) memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ *
+ * This file contains the declarations for external variables from the main file.
+ * See other comments in that file.
+ *
+ */
+
+#include <types.h>
+
+/* extern declarations. */
+
+extern int memtester_use_phys;
+extern off_t memtester_physaddrbase;
+
diff --git a/commands/memtester/sizes.h b/commands/memtester/sizes.h
new file mode 100644
index 0000000000..569b3361e9
--- /dev/null
+++ b/commands/memtester/sizes.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ *
+ * This file contains some macro definitions for handling 32/64 bit platforms.
+ *
+ */
+
+#include <linux/limits.h>
+
+#define rand32() random32()
+
+#ifdef CONFIG_64BIT
+ #define rand64() (((ul) rand32()) << 32 | ((ul) rand32()))
+ #define rand_ul() rand64()
+ #define UL_ONEBITS 0xffffffffffffffffUL
+ #define UL_LEN 64
+ #define CHECKERBOARD1 0x5555555555555555
+ #define CHECKERBOARD2 0xaaaaaaaaaaaaaaaa
+ #define UL_BYTE(x) (((ul)x | (ul)x<<8 | (ul)x<<16 | (ul)x<<24 | (ul)x<<32 | (ul)x<<40 | (ul)x<<48 | (ul)x<<56))
+#else
+ #define rand_ul() rand32()
+ #define UL_ONEBITS 0xffffffff
+ #define UL_LEN 32
+ #define CHECKERBOARD1 0x55555555
+ #define CHECKERBOARD2 0xaaaaaaaa
+ #define UL_BYTE(x) ((x | x << 8 | x << 16 | x << 24))
+#endif
+
+
diff --git a/commands/memtester/tests.c b/commands/memtester/tests.c
new file mode 100644
index 0000000000..ca83c4a764
--- /dev/null
+++ b/commands/memtester/tests.c
@@ -0,0 +1,495 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ *
+ * This file contains the functions for the actual tests, called from the
+ * main routine in memtester.c. See other comments in that file.
+ *
+ */
+
+#include <common.h>
+#include <types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/limits.h>
+
+#include "types.h"
+#include "sizes.h"
+#include "memtester.h"
+#include "tests.h"
+
+static char progress[] = "-\\|/";
+#define PROGRESSLEN 4
+#define PROGRESSOFTEN 2500
+#define ONE 0x00000001L
+
+static mword8_t mword8;
+static mword16_t mword16;
+
+/* Function definitions. */
+
+static int compare_regions(ulv *bufa, ulv *bufb, size_t count) {
+ int r = 0;
+ size_t i;
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ off_t physaddr;
+
+ if (ctrlc())
+ return -EINTR;
+
+ for (i = 0; i < count; i++, p1++, p2++) {
+ if (*p1 != *p2) {
+ if (memtester_use_phys) {
+ physaddr = memtester_physaddrbase + (i * sizeof(ul));
+ printf("FAILURE: 0x%08lx != 0x%08lx at physical address "
+ "0x%08lx.\n",
+ (ul) *p1, (ul) *p2, physaddr);
+ } else {
+ printf("FAILURE: 0x%08lx != 0x%08lx at offset 0x%08lx.\n",
+ (ul) *p1, (ul) *p2, (ul) (i * sizeof(ul)));
+ }
+ /* printf("Skipping to next test..."); */
+ r = -1;
+ }
+ }
+ return r;
+}
+
+int test_stuck_address(ulv *bufa, size_t count) {
+ ulv *p1 = bufa;
+ unsigned int j;
+ size_t i;
+ off_t physaddr;
+
+ printf(" ");
+ for (j = 0; j < 16; j++) {
+ if (ctrlc())
+ return -EINTR;
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ p1 = (ulv *) bufa;
+ printf("setting %3u", j);
+ for (i = 0; i < count; i++) {
+ *p1 = ((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1);
+ *p1++;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ printf("testing %3u", j);
+ p1 = (ulv *) bufa;
+ for (i = 0; i < count; i++, p1++) {
+ if (*p1 != (((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1))) {
+ if (memtester_use_phys) {
+ physaddr = memtester_physaddrbase + (i * sizeof(ul));
+ printf("FAILURE: possible bad address line at physical "
+ "address 0x%08lx.\n",
+ physaddr);
+ } else {
+ printf("FAILURE: possible bad address line at offset "
+ "0x%08lx.\n",
+ (ul) (i * sizeof(ul)));
+ }
+ printf("Skipping to next test...\n");
+ return -1;
+ }
+ }
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
+ return 0;
+}
+
+int test_random_value(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ ul j = 0;
+ size_t i;
+
+ putchar(' ');
+ for (i = 0; i < count; i++) {
+ *p1++ = *p2++ = rand_ul();
+ if (!(i % PROGRESSOFTEN)) {
+ putchar('\b');
+ putchar(progress[++j % PROGRESSLEN]);
+ }
+ }
+ printf("\b \b");
+ return compare_regions(bufa, bufb, count);
+}
+
+int test_xor_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ size_t i;
+ ul q = rand_ul();
+
+ for (i = 0; i < count; i++) {
+ *p1++ ^= q;
+ *p2++ ^= q;
+ }
+ return compare_regions(bufa, bufb, count);
+}
+
+int test_sub_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ size_t i;
+ ul q = rand_ul();
+
+ for (i = 0; i < count; i++) {
+ *p1++ -= q;
+ *p2++ -= q;
+ }
+ return compare_regions(bufa, bufb, count);
+}
+
+int test_mul_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ size_t i;
+ ul q = rand_ul();
+
+ for (i = 0; i < count; i++) {
+ *p1++ *= q;
+ *p2++ *= q;
+ }
+ return compare_regions(bufa, bufb, count);
+}
+
+int test_div_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ size_t i;
+ ul q = rand_ul();
+
+ for (i = 0; i < count; i++) {
+ if (!q) {
+ q++;
+ }
+ *p1++ /= q;
+ *p2++ /= q;
+ }
+ return compare_regions(bufa, bufb, count);
+}
+
+int test_or_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ size_t i;
+ ul q = rand_ul();
+
+ for (i = 0; i < count; i++) {
+ *p1++ |= q;
+ *p2++ |= q;
+ }
+ return compare_regions(bufa, bufb, count);
+}
+
+int test_and_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ size_t i;
+ ul q = rand_ul();
+
+ for (i = 0; i < count; i++) {
+ *p1++ &= q;
+ *p2++ &= q;
+ }
+ return compare_regions(bufa, bufb, count);
+}
+
+int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ size_t i;
+ ul q = rand_ul();
+
+ for (i = 0; i < count; i++) {
+ *p1++ = *p2++ = (i + q);
+ }
+ return compare_regions(bufa, bufb, count);
+}
+
+int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ unsigned int j;
+ ul q;
+ size_t i;
+ int ret;
+
+ printf(" ");
+ for (j = 0; j < 64; j++) {
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ q = (j % 2) == 0 ? UL_ONEBITS : 0;
+ printf("setting %3u", j);
+ p1 = (ulv *) bufa;
+ p2 = (ulv *) bufb;
+ for (i = 0; i < count; i++) {
+ *p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ printf("testing %3u", j);
+ ret = compare_regions(bufa, bufb, count);
+ if (ret)
+ return ret;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
+ return 0;
+}
+
+int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ unsigned int j;
+ ul q;
+ size_t i;
+ int ret;
+
+ printf(" ");
+ for (j = 0; j < 64; j++) {
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2;
+ printf("setting %3u", j);
+ p1 = (ulv *) bufa;
+ p2 = (ulv *) bufb;
+ for (i = 0; i < count; i++) {
+ *p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ printf("testing %3u", j);
+ ret = compare_regions(bufa, bufb, count);
+ if (ret)
+ return ret;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
+ return 0;
+}
+
+int test_blockseq_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ unsigned int j;
+ size_t i;
+ int ret;
+
+ printf(" ");
+ for (j = 0; j < 256; j++) {
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ p1 = (ulv *) bufa;
+ p2 = (ulv *) bufb;
+ printf("setting %3u", j);
+ for (i = 0; i < count; i++) {
+ *p1++ = *p2++ = (ul) UL_BYTE(j);
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ printf("testing %3u", j);
+ ret = compare_regions(bufa, bufb, count);
+ if (ret)
+ return ret;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
+ return 0;
+}
+
+int test_walkbits0_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ unsigned int j;
+ size_t i;
+ int ret;
+
+ printf(" ");
+ for (j = 0; j < UL_LEN * 2; j++) {
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ p1 = (ulv *) bufa;
+ p2 = (ulv *) bufb;
+ printf("setting %3u", j);
+ for (i = 0; i < count; i++) {
+ if (j < UL_LEN) { /* Walk it up. */
+ *p1++ = *p2++ = ONE << j;
+ } else { /* Walk it back down. */
+ *p1++ = *p2++ = ONE << (UL_LEN * 2 - j - 1);
+ }
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ printf("testing %3u", j);
+ ret = compare_regions(bufa, bufb, count);
+ if (ret)
+ return ret;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
+ return 0;
+}
+
+int test_walkbits1_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ unsigned int j;
+ size_t i;
+ int ret;
+
+ printf(" ");
+ for (j = 0; j < UL_LEN * 2; j++) {
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ p1 = (ulv *) bufa;
+ p2 = (ulv *) bufb;
+ printf("setting %3u", j);
+ for (i = 0; i < count; i++) {
+ if (j < UL_LEN) { /* Walk it up. */
+ *p1++ = *p2++ = UL_ONEBITS ^ (ONE << j);
+ } else { /* Walk it back down. */
+ *p1++ = *p2++ = UL_ONEBITS ^ (ONE << (UL_LEN * 2 - j - 1));
+ }
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ printf("testing %3u", j);
+ ret = compare_regions(bufa, bufb, count);
+ if (ret)
+ return ret;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
+ return 0;
+}
+
+int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ unsigned int j;
+ size_t i;
+ int ret;
+
+ printf(" ");
+ for (j = 0; j < UL_LEN * 2; j++) {
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ p1 = (ulv *) bufa;
+ p2 = (ulv *) bufb;
+ printf("setting %3u", j);
+ for (i = 0; i < count; i++) {
+ if (j < UL_LEN) { /* Walk it up. */
+ *p1++ = *p2++ = (i % 2 == 0)
+ ? (ONE << j) | (ONE << (j + 2))
+ : UL_ONEBITS ^ ((ONE << j)
+ | (ONE << (j + 2)));
+ } else { /* Walk it back down. */
+ *p1++ = *p2++ = (i % 2 == 0)
+ ? (ONE << (UL_LEN * 2 - 1 - j)) | (ONE << (UL_LEN * 2 + 1 - j))
+ : UL_ONEBITS ^ (ONE << (UL_LEN * 2 - 1 - j)
+ | (ONE << (UL_LEN * 2 + 1 - j)));
+ }
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ printf("testing %3u", j);
+ ret = compare_regions(bufa, bufb, count);
+ if (ret)
+ return ret;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
+ return 0;
+}
+
+int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count) {
+ ulv *p1 = bufa;
+ ulv *p2 = bufb;
+ unsigned int j, k;
+ ul q;
+ size_t i;
+ int ret;
+
+ printf(" ");
+ for (k = 0; k < UL_LEN; k++) {
+ q = ONE << k;
+ for (j = 0; j < 8; j++) {
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ q = ~q;
+ printf("setting %3u", k * 8 + j);
+ p1 = (ulv *) bufa;
+ p2 = (ulv *) bufb;
+ for (i = 0; i < count; i++) {
+ *p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b");
+ printf("testing %3u", k * 8 + j);
+ ret = compare_regions(bufa, bufb, count);
+ if (ret)
+ return -1;
+ }
+ }
+ printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b");
+ return 0;
+}
+
+int test_8bit_wide_random(ulv* bufa, ulv* bufb, size_t count) {
+ u8v *p1, *t;
+ ulv *p2;
+ int attempt;
+ unsigned int b, j = 0;
+ size_t i;
+ int ret;
+
+ putchar(' ');
+ for (attempt = 0; attempt < 2; attempt++) {
+ if (attempt & 1) {
+ p1 = (u8v *) bufa;
+ p2 = bufb;
+ } else {
+ p1 = (u8v *) bufb;
+ p2 = bufa;
+ }
+ for (i = 0; i < count; i++) {
+ t = mword8.bytes;
+ *p2++ = mword8.val = rand_ul();
+ for (b=0; b < UL_LEN/8; b++) {
+ *p1++ = *t++;
+ }
+ if (!(i % PROGRESSOFTEN)) {
+ putchar('\b');
+ putchar(progress[++j % PROGRESSLEN]);
+ }
+ }
+ ret = compare_regions(bufa, bufb, count);
+ if (ret)
+ return ret;
+ }
+ printf("\b \b");
+ return 0;
+}
+
+int test_16bit_wide_random(ulv* bufa, ulv* bufb, size_t count) {
+ u16v *p1, *t;
+ ulv *p2;
+ int attempt;
+ unsigned int b, j = 0;
+ size_t i;
+ int ret;
+
+ putchar( ' ' );
+ for (attempt = 0; attempt < 2; attempt++) {
+ if (attempt & 1) {
+ p1 = (u16v *) bufa;
+ p2 = bufb;
+ } else {
+ p1 = (u16v *) bufb;
+ p2 = bufa;
+ }
+ for (i = 0; i < count; i++) {
+ t = mword16.u16s;
+ *p2++ = mword16.val = rand_ul();
+ for (b = 0; b < UL_LEN/16; b++) {
+ *p1++ = *t++;
+ }
+ if (!(i % PROGRESSOFTEN)) {
+ putchar('\b');
+ putchar(progress[++j % PROGRESSLEN]);
+ }
+ }
+ ret = compare_regions(bufa, bufb, count);
+ if (ret)
+ return ret;
+ }
+ printf("\b \b");
+ return 0;
+}
diff --git a/commands/memtester/tests.h b/commands/memtester/tests.h
new file mode 100644
index 0000000000..427651e189
--- /dev/null
+++ b/commands/memtester/tests.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple yet very effective memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ *
+ * This file contains the declarations for the functions for the actual tests,
+ * called from the main routine in memtester.c. See other comments in that
+ * file.
+ *
+ */
+
+/* Function declaration. */
+
+int test_stuck_address(unsigned long volatile *bufa, size_t count);
+int test_random_value(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_xor_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_sub_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_mul_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_div_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_or_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_and_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_seqinc_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_solidbits_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_checkerboard_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_blockseq_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_walkbits0_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_walkbits1_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_bitspread_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_bitflip_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_8bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_16bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+
diff --git a/commands/memtester/types.h b/commands/memtester/types.h
new file mode 100644
index 0000000000..0291610d2c
--- /dev/null
+++ b/commands/memtester/types.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
+ * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2010 Charles Cazabon <charlesc-memtester@pyropus.ca>
+ *
+ * This file contains typedefs, structure, and union definitions.
+ *
+ */
+
+#include "sizes.h"
+
+typedef unsigned long ul;
+typedef unsigned long long ull;
+typedef unsigned long volatile ulv;
+typedef unsigned char volatile u8v;
+typedef unsigned short volatile u16v;
+
+struct test {
+ char *name;
+ int (*fp)(ulv *, ulv *, size_t);
+};
+
+typedef union {
+ unsigned char bytes[UL_LEN/8];
+ ul val;
+} mword8_t;
+
+typedef union {
+ unsigned short u16s[UL_LEN/16];
+ ul val;
+} mword16_t;
diff --git a/commands/menu.c b/commands/menu.c
index 7a01aff280..e0fe09b508 100644
--- a/commands/menu.c
+++ b/commands/menu.c
@@ -406,64 +406,65 @@ end:
return 1;
}
-static const __maybe_unused char cmd_menu_help[] =
-"Manage Menu:\n"
-" -m menu\n"
-" -l list\n"
-" -s show\n"
+BAREBOX_CMD_HELP_START(menu)
+BAREBOX_CMD_HELP_TEXT("Manage Menu:")
+BAREBOX_CMD_HELP_OPT ("-m", "menu")
+BAREBOX_CMD_HELP_OPT ("-l", "list")
+BAREBOX_CMD_HELP_OPT ("-s", "show")
+BAREBOX_CMD_HELP_TEXT("")
#if defined(CONFIG_CMD_MENU_MANAGEMENT)
-"Advanced menu management:\n"
-" -e menu entry\n"
-" -a add\n"
-" -r remove\n"
-" -S select\n"
+BAREBOX_CMD_HELP_TEXT("Advanced menu management:")
+BAREBOX_CMD_HELP_OPT ("-e", "menu entry")
+BAREBOX_CMD_HELP_OPT ("-a", "add")
+BAREBOX_CMD_HELP_OPT ("-r", "remove")
+BAREBOX_CMD_HELP_OPT ("-S", "select")
+BAREBOX_CMD_HELP_TEXT("")
#endif
-"\n"
-"Show menu:\n"
-" (-A auto select delay)\n"
-" (-d auto select description)\n"
-" menu -s -m MENU [-A delay] [-d auto_display]\n"
-"\n"
-"List menu:\n"
-" menu -l\n"
-"\n"
+BAREBOX_CMD_HELP_TEXT("Show menu:")
+BAREBOX_CMD_HELP_OPT ("-A", "auto select delay")
+BAREBOX_CMD_HELP_OPT ("-d", "auto select description")
+BAREBOX_CMD_HELP_TEXT("\tmenu -s -m MENU [-A delay] [-d auto_display]")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("List menu:")
+BAREBOX_CMD_HELP_TEXT("\tmenu -l\n")
+BAREBOX_CMD_HELP_TEXT("")
#if defined(CONFIG_CMD_MENU_MANAGEMENT)
-"Add a menu:\n"
-" menu -a -m NAME -d DESC\n"
-"\n"
-"Remove a menu:\n"
-" menu -r -m NAME\n"
-"\n"
-"Add an entry:\n"
-" (-R for do no exit the menu after executing the command)\n"
-" (-b for box style 1 for selected)\n"
-" (and optional -c for the command to run when we change the state)\n"
-" menu -e -a -m MENU -c COMMAND [-R] [-b 0|1] -d DESC\n"
-
-"Add a submenu entry:\n"
-" (-R is not needed)\n"
-" (-b for box style 1 for selected)\n"
-" (and -c is not needed)\n"
-" menu -e -a -m MENU -u submenu -d [-b 0|1] DESC\n"
-"\n"
-"Remove an entry:\n"
-" menu -e -r -m NAME -n ENTRY\n"
-"\n"
-"Select an entry:\n"
-" menu -m <menu> -S -n ENTRY\n"
-"\n"
-"List menu:\n"
-" menu -e -l [menu]\n"
-"\n"
-"Menu examples:\n"
-" menu -a -m boot -d \"Boot Menu\"\n"
-" menu -e -a -m boot -c boot -d \"Boot\"\n"
-" menu -e -a -m boot -c reset -d \"Reset\"\n"
+BAREBOX_CMD_HELP_TEXT("Add a menu:")
+BAREBOX_CMD_HELP_TEXT("\tmenu -a -m NAME -d DESC")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Remove a menu:")
+BAREBOX_CMD_HELP_TEXT("\tmenu -r -m NAME")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Add an entry:")
+BAREBOX_CMD_HELP_TEXT("\t(-R for do no exit the menu after executing the command)")
+BAREBOX_CMD_HELP_TEXT("\t(-b for box style 1 for selected)")
+BAREBOX_CMD_HELP_TEXT("\t(and optional -c for the command to run when we change the state)")
+BAREBOX_CMD_HELP_TEXT("\tmenu -e -a -m MENU -c COMMAND [-R] [-b 0|1] -d DESC")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Add a submenu entry:")
+BAREBOX_CMD_HELP_TEXT("\t(-R is not needed)")
+BAREBOX_CMD_HELP_TEXT("\t(-b for box style 1 for selected)")
+BAREBOX_CMD_HELP_TEXT("\t(and -c is not needed)")
+BAREBOX_CMD_HELP_TEXT("\tmenu -e -a -m MENU -u submenu -d [-b 0|1] DESC")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Remove an entry:")
+BAREBOX_CMD_HELP_TEXT("\tmenu -e -r -m NAME -n ENTRY")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Select an entry:")
+BAREBOX_CMD_HELP_TEXT("\tmenu -m <menu> -S -n ENTRY")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("List menu:")
+BAREBOX_CMD_HELP_TEXT("\tmenu -e -l [menu]")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Menu examples:")
+BAREBOX_CMD_HELP_TEXT("\tmenu -a -m boot -d \"Boot Menu\"")
+BAREBOX_CMD_HELP_TEXT("\tmenu -e -a -m boot -c boot -d \"Boot\"")
+BAREBOX_CMD_HELP_TEXT("\tmenu -e -a -m boot -c reset -d \"Reset\"")
#else
-"Menu example:\n"
+BAREBOX_CMD_HELP_TEXT("Menu example:")
#endif
-" menu -s -m boot\n"
-;
+BAREBOX_CMD_HELP_TEXT("\tmenu -s -m boot")
+BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(menu)
.cmd = do_menu,
diff --git a/commands/miitool.c b/commands/miitool.c
index 47494f5089..24e383736a 100644
--- a/commands/miitool.c
+++ b/commands/miitool.c
@@ -217,7 +217,7 @@ static int show_basic_mii(struct mii_bus *mii, struct phy_device *phydev,
return 0;
}
-static void mdiobus_show(struct device_d *dev, const char *phydevname,
+static void mdiobus_show(struct device *dev, const char *phydevname,
int verbose)
{
struct mii_bus *mii = to_mii_bus(dev);
diff --git a/commands/mipi_dbi.c b/commands/mipi_dbi.c
new file mode 100644
index 0000000000..b9b665b721
--- /dev/null
+++ b/commands/mipi_dbi.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: © 2022 Ahmad Fatoum
+
+#include <common.h>
+#include <command.h>
+#include <getopt.h>
+#include <video/mipi_dbi.h>
+#include <video/mipi_display.h>
+
+static int mipi_dbi_command_show(struct mipi_dbi *dbi, int cmd)
+{
+ u8 val[4];
+ int ret;
+ size_t len;
+
+ if (!mipi_dbi_command_is_read(dbi, cmd))
+ return -EACCES;
+
+ len = mipi_dbi_command_read_len(cmd);
+
+ printf("%02x: ", cmd);
+ ret = mipi_dbi_command_buf(dbi, cmd, val, len);
+ if (ret) {
+ printf("XX\n");
+ return ret;
+ }
+ printf("%*phN\n", (int)len, val);
+
+ return 0;
+}
+
+static int do_mipi_dbi(int argc, char *argv[])
+{
+ struct mipi_dbi *dbi;
+ int opt, ret, i;
+ bool write = false;
+ u8 cmd, val[4];
+
+ dbi = list_first_entry_or_null(&mipi_dbi_list, struct mipi_dbi, list);
+
+ while ((opt = getopt(argc, argv, "wld:")) > 0) {
+ struct mipi_dbi *tmp;
+
+ switch (opt) {
+ case 'w':
+ write = true;
+ break;
+ case 'l':
+ list_for_each_entry(tmp, &mipi_dbi_list, list)
+ printf("%s\n", mipi_dbi_name(tmp));
+ return 0;
+ case 'd':
+ dbi = NULL;
+ list_for_each_entry(tmp, &mipi_dbi_list, list) {
+ if (!strcmp(optarg, mipi_dbi_name(tmp))) {
+ dbi = tmp;
+ break;
+ }
+ }
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (!dbi)
+ return -ENODEV;
+
+ if (optind == argc) {
+ for (cmd = 0; cmd < 255; cmd++)
+ mipi_dbi_command_show(dbi, cmd);
+ return 0;
+ }
+
+ ret = kstrtou8(argv[optind++], 16, &cmd);
+ if (ret < 0)
+ return ret;
+
+ if (optind == argc && !write)
+ return mipi_dbi_command_show(dbi, cmd);
+
+ for (i = optind; i < argc; i++) {
+ ret = kstrtou8(argv[optind + i], 16, &val[i]);
+ if (ret < 0)
+ return ret;
+ }
+
+ return mipi_dbi_command_buf(dbi, cmd, val, argc - optind);
+}
+
+BAREBOX_CMD_HELP_START(mipi_dbi)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-l\t", "list all MIPI DBI devices")
+BAREBOX_CMD_HELP_OPT ("-d DEVICE", "select specific device (default is first registered)")
+BAREBOX_CMD_HELP_OPT ("-w", "issue write command")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(mipi_dbi)
+ .cmd = do_mipi_dbi,
+ BAREBOX_CMD_DESC("write/read from MIPI DBI SPI device")
+ BAREBOX_CMD_OPTS("[-wld] [REG] [DATA...]")
+ BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_HELP(cmd_mipi_dbi_help)
+BAREBOX_CMD_END
diff --git a/commands/mkdir.c b/commands/mkdir.c
index e7153b8732..01fc0b083b 100644
--- a/commands/mkdir.c
+++ b/commands/mkdir.c
@@ -37,7 +37,7 @@ static int do_mkdir(int argc, char *argv[])
ret = mkdir(argv[optind], 0);
}
if (ret) {
- printf("could not create %s: %s\n", argv[optind], errno_str());
+ printf("could not create %s: %m\n", argv[optind]);
return 1;
}
optind++;
diff --git a/commands/mm.c b/commands/mm.c
index f6d66320fb..8755a0f2c9 100644
--- a/commands/mm.c
+++ b/commands/mm.c
@@ -16,7 +16,7 @@
static int do_mem_mm(int argc, char *argv[])
{
- int ret = 0;
+ int ret;
int fd;
char *filename = "/dev/mem";
int mode = O_RWSIZE_4;
@@ -40,8 +40,10 @@ static int do_mem_mm(int argc, char *argv[])
mask = simple_strtoull(argv[optind++], NULL, 0);
fd = open_and_lseek(filename, mode | O_RDWR | O_CREAT, adr);
- if (fd < 0)
+ if (fd < 0) {
+ printf("Could not open \"%s\": %m\n", filename);
return 1;
+ }
switch (mode) {
case O_RWSIZE_1:
@@ -65,9 +67,9 @@ static int do_mem_mm(int argc, char *argv[])
goto out_write;
break;
case O_RWSIZE_4:
+ ret = pread(fd, &val32, 4, adr);
if (ret < 0)
goto out_read;
- ret = pread(fd, &val32, 4, adr);
val32 &= ~mask;
val32 |= (value & mask);
ret = pwrite(fd, &val32, 4, adr);
@@ -75,9 +77,9 @@ static int do_mem_mm(int argc, char *argv[])
goto out_write;
break;
case O_RWSIZE_8:
+ ret = pread(fd, &val64, 8, adr);
if (ret < 0)
goto out_read;
- ret = pread(fd, &val64, 8, adr);
val64 &= ~mask;
val64 |= (value & mask);
ret = pwrite(fd, &val64, 8, adr);
@@ -116,7 +118,7 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(mm)
.cmd = do_mem_mm,
BAREBOX_CMD_DESC("memory modify with mask")
- BAREBOX_CMD_OPTS("[-bwld] ADDR VAL MASK")
+ BAREBOX_CMD_OPTS("[-bwlq] [-d FILE] ADDR VAL MASK")
BAREBOX_CMD_GROUP(CMD_GRP_MEM)
BAREBOX_CMD_HELP(cmd_mm_help)
BAREBOX_CMD_END
diff --git a/commands/mmc.c b/commands/mmc.c
index c696e7b881..fa01b89cdf 100644
--- a/commands/mmc.c
+++ b/commands/mmc.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <command.h>
#include <mci.h>
#include <stdio.h>
@@ -63,23 +65,6 @@ static int mmc_partitioning_complete(struct mci *mci)
return ret;
}
-static u8 *mci_get_ext_csd(struct mci *mci)
-{
- u8 *ext_csd;
- int ret;
-
- ext_csd = xmalloc(512);
-
- ret = mci_send_ext_csd(mci, ext_csd);
- if (ret) {
- printf("Failure to read EXT_CSD register\n");
- free(ext_csd);
- return ERR_PTR(-EIO);
- }
-
- return ext_csd;
-}
-
/* enh_area [-c] /dev/mmcX */
static int do_mmc_enh_area(int argc, char *argv[])
{
@@ -93,6 +78,7 @@ static int do_mmc_enh_area(int argc, char *argv[])
while ((opt = getopt(argc, argv, "c")) > 0) {
switch (opt) {
case 'c':
+ printf("Use -c to complete the partitioning is deprecated, use separate partition_complete command instead\n");
set_completed = 1;
break;
}
@@ -145,6 +131,95 @@ error:
return COMMAND_ERROR;
}
+static int do_mmc_write_reliability(int argc, char *argv[])
+{
+ const char *devpath;
+ struct mci *mci;
+ u8 *ext_csd;
+
+ if (argc - optind != 1) {
+ printf("Usage: mmc write_reliability /dev/mmcX\n");
+ return COMMAND_ERROR_USAGE;
+ }
+
+ devpath = argv[optind];
+
+ mci = mci_get_device_by_devpath(devpath);
+ if (!mci) {
+ printf("Failure to open %s as mci device\n", devpath);
+ return COMMAND_ERROR;
+ }
+
+ ext_csd = mci_get_ext_csd(mci);
+ if (IS_ERR(ext_csd))
+ return COMMAND_ERROR;
+
+ if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED]) {
+ printf("Partitioning already finalized\n");
+ goto error;
+ }
+
+ if (!(ext_csd[EXT_CSD_WR_REL_PARAM] & EXT_CSD_EN_REL_WR)) {
+ printf("Device doesn't support the enhanced definition of reliable write\n");
+ goto error;
+ }
+
+ if (!(ext_csd[EXT_CSD_WR_REL_PARAM] & EXT_CSD_HS_CTRL_REL)) {
+ printf("Device doesn't support WR_REL_SET writes\n");
+ goto error;
+ }
+
+ /*
+ * Host has one opportunity to write all of the bits. Separate writes to
+ * individual bits are not permitted so set all bits for now.
+ */
+ if ((ext_csd[EXT_CSD_WR_REL_SET] & 0x1f) != 0x1f) {
+ int ret;
+
+ ret = mci_switch(mci, EXT_CSD_WR_REL_SET, 0x1f);
+ if (ret) {
+ printf("Failure to write to EXT_CSD_WR_REL_SET\n");
+ goto error;
+ }
+ }
+
+ free(ext_csd);
+
+ return COMMAND_SUCCESS;
+
+error:
+ free(ext_csd);
+ return COMMAND_ERROR;
+}
+
+static int do_mmc_partition_complete(int argc, char *argv[])
+{
+ const char *devpath;
+ struct mci *mci;
+ int ret;
+
+ if (argc - optind != 1) {
+ printf("Usage: mmc partition_complete /dev/mmcX\n");
+ return COMMAND_ERROR_USAGE;
+ }
+
+ devpath = argv[optind];
+
+ mci = mci_get_device_by_devpath(devpath);
+ if (!mci) {
+ printf("Failure to open %s as mci device\n", devpath);
+ return COMMAND_ERROR_USAGE;
+ }
+
+ ret = mmc_partitioning_complete(mci);
+ if (ret)
+ return COMMAND_ERROR;
+
+ printf("Now power cycle the device to let it reconfigure itself.\n");
+
+ return COMMAND_SUCCESS;
+}
+
static struct {
const char *cmd;
int (*func)(int argc, char *argv[]);
@@ -152,6 +227,12 @@ static struct {
{
.cmd = "enh_area",
.func = do_mmc_enh_area,
+ }, {
+ .cmd = "write_reliability",
+ .func = do_mmc_write_reliability,
+ }, {
+ .cmd = "partition_complete",
+ .func = do_mmc_partition_complete,
}
};
@@ -186,11 +267,16 @@ BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("The subcommand enh_area creates an enhanced area of")
BAREBOX_CMD_HELP_TEXT("maximal size.")
BAREBOX_CMD_HELP_TEXT("Note, with -c this is an irreversible action.")
-BAREBOX_CMD_HELP_OPT("-c", "complete partitioning")
+BAREBOX_CMD_HELP_OPT("-c", "complete partitioning (deprecated)")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("The subcommand write_reliability enable write reliability")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("The subcommand partition_complete set PARTITION_SETTING_COMPLETED (irreversible action)")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(mmc)
.cmd = do_mmc,
- BAREBOX_CMD_OPTS("enh_area [-c] /dev/mmcX")
+ BAREBOX_CMD_OPTS("partition_complete|write_reliability|enh_area [-c] /dev/mmcX")
+ BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_mmc_help)
BAREBOX_CMD_END
diff --git a/commands/mmc_extcsd.c b/commands/mmc_extcsd.c
index 7ae068348d..f67c48404a 100644
--- a/commands/mmc_extcsd.c
+++ b/commands/mmc_extcsd.c
@@ -1427,7 +1427,7 @@ static int print_field(u8 *reg, int index)
case EXT_CSD_MAX_ENH_SIZE_MULT:
tmp = get_field_val(EXT_CSD_HC_WP_GRP_SIZE, 0, 0xFF);
- tmp = tmp + get_field_val(EXT_CSD_HC_ERASE_GRP_SIZE, 0, 0xFF);
+ tmp = tmp * get_field_val(EXT_CSD_HC_ERASE_GRP_SIZE, 0, 0xFF);
tmp64 *= tmp;
tmp64 *= SZ_512K;
printf("\tMax Enhanced Area: %llu B\n", tmp64);
diff --git a/commands/mount.c b/commands/mount.c
index ff1d8bc5e5..fddd770dc9 100644
--- a/commands/mount.c
+++ b/commands/mount.c
@@ -13,7 +13,7 @@
static int do_mount(int argc, char *argv[])
{
int opt, verbose = 0;
- struct driver_d *drv;
+ struct driver *drv;
const char *type = NULL;
const char *mountpoint, *devstr;
const char *fsoptions = NULL;
@@ -36,7 +36,7 @@ static int do_mount(int argc, char *argv[])
}
if (argc == optind) {
- struct fs_device_d *fsdev;
+ struct fs_device *fsdev;
for_each_fs_device(fsdev) {
printf("%s on %s type %s\n",
@@ -48,7 +48,7 @@ static int do_mount(int argc, char *argv[])
if (verbose) {
printf("\nSupported filesystems:\n\n");
bus_for_each_driver(&fs_bus, drv) {
- struct fs_driver_d * fsdrv = drv_to_fs_driver(drv);
+ struct fs_driver * fsdrv = drv_to_fs_driver(drv);
printf("%s\n", fsdrv->drv.name);
}
}
diff --git a/commands/mw.c b/commands/mw.c
index 5bd4bdd58f..915f549216 100644
--- a/commands/mw.c
+++ b/commands/mw.c
@@ -39,8 +39,10 @@ static int do_mem_mw(int argc, char *argv[])
adr = strtoull_suffix(argv[optind++], NULL, 0);
fd = open_and_lseek(filename, mode | O_WRONLY | O_CREAT, adr);
- if (fd < 0)
+ if (fd < 0) {
+ printf("Could not open \"%s\": %m\n", filename);
return 1;
+ }
while (optind < argc) {
u8 val8;
@@ -110,12 +112,17 @@ BAREBOX_CMD_HELP_OPT ("-l", "long access (32 bit)")
BAREBOX_CMD_HELP_OPT ("-q", "quad access (64 bit)")
BAREBOX_CMD_HELP_OPT ("-d FILE", "write file (default /dev/mem)")
BAREBOX_CMD_HELP_OPT ("-x", "swap bytes")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Memory regions can be specified in two different forms: START+SIZE")
+BAREBOX_CMD_HELP_TEXT("or START-END, If START is omitted it defaults to 0x100")
+BAREBOX_CMD_HELP_TEXT("Sizes can be specified as decimal, or if prefixed with 0x as hexadecimal.")
+BAREBOX_CMD_HELP_TEXT("An optional suffix of k, M or G is for kbytes, Megabytes or Gigabytes.")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(mw)
.cmd = do_mem_mw,
BAREBOX_CMD_DESC("memory write")
- BAREBOX_CMD_OPTS("[-bwldx] REGION DATA...")
+ BAREBOX_CMD_OPTS("[-bwlqx] [-d FILE] REGION DATA...")
BAREBOX_CMD_GROUP(CMD_GRP_MEM)
BAREBOX_CMD_HELP(cmd_mw_help)
BAREBOX_CMD_END
diff --git a/commands/nand-bitflip.c b/commands/nand-bitflip.c
index 7335f77379..1395021ec0 100644
--- a/commands/nand-bitflip.c
+++ b/commands/nand-bitflip.c
@@ -10,6 +10,25 @@
#include <linux/mtd/mtd.h>
#include <mtd/mtd-peb.h>
+static int bitflip_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, void *buf)
+{
+ int ret_code;
+
+ if (mtd->_read_oob) {
+ struct mtd_oob_ops ops = {
+ .len = len,
+ .datbuf = buf,
+ };
+
+ ret_code = mtd->_read_oob(mtd, from, &ops);
+ } else {
+ ret_code = mtd->_read(mtd, from, len, retlen, buf);
+ }
+
+ return ret_code;
+}
+
static int do_nand_bitflip(int argc, char *argv[])
{
int opt, ret, fd;
@@ -34,7 +53,7 @@ static int do_nand_bitflip(int argc, char *argv[])
block = simple_strtoul(optarg, NULL, 0);
break;
case 'o':
- offset = simple_strtoull(optarg, NULL, 0);
+ offset = strtoull_suffix(optarg, NULL, 0);
break;
case 'c':
check = 1;
@@ -77,7 +96,7 @@ static int do_nand_bitflip(int argc, char *argv[])
buf = xzalloc(meminfo.writesize);
roffset = (loff_t)block * meminfo.mtd->erasesize + offset;
- ret = meminfo.mtd->read(meminfo.mtd, roffset, meminfo.writesize, &r, buf);
+ ret = bitflip_mtd_read(meminfo.mtd, roffset, meminfo.writesize, &r, buf);
if (ret > 0) {
printf("page at block %d, offset 0x%08llx has %d bitflips%s\n",
block, offset, ret,
diff --git a/commands/nand.c b/commands/nand.c
index ed2864fb7b..d07444aee0 100644
--- a/commands/nand.c
+++ b/commands/nand.c
@@ -13,6 +13,7 @@
#include <ioctl.h>
#include <nand.h>
#include <linux/mtd/mtd-abi.h>
+#include <linux/mtd/mtd.h>
#include <fcntl.h>
#include <libgen.h>
@@ -130,6 +131,8 @@ static int do_nand(int argc, char *argv[])
loff_t ofs;
int bad = 0;
+ printf("---- bad blocks ----\n");
+
for (ofs = 0; ofs < mtdinfo.size; ofs += mtdinfo.erasesize) {
if (ioctl(fd, MEMGETBADBLOCK, &ofs)) {
printf("Block at 0x%08llx is bad\n", ofs);
@@ -139,6 +142,8 @@ static int do_nand(int argc, char *argv[])
if (!bad)
printf("No bad blocks\n");
+
+ mtd_print_oob_info(mtdinfo.mtd);
}
out:
@@ -160,7 +165,7 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(nand)
.cmd = do_nand,
BAREBOX_CMD_DESC("NAND flash handling")
- BAREBOX_CMD_OPTS("[-adb] NANDDEV")
+ BAREBOX_CMD_OPTS("[-adbgi] NANDDEV")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_nand_help)
BAREBOX_CMD_END
diff --git a/commands/nandtest.c b/commands/nandtest.c
index bfe4c4c0ed..4a7db9cc74 100644
--- a/commands/nandtest.c
+++ b/commands/nandtest.c
@@ -169,8 +169,10 @@ static int erase_and_write(loff_t ofs, unsigned char *data,
printf("\ncompare failed. seed %d\n", seed);
for (i = 0; i < meminfo.erasesize; i++) {
if (data[i] != rbuf[i])
- printf("Byte 0x%x is %02x should be %02x\n",
- i, rbuf[i], data[i]);
+ printf("Block 0x%llx byte 0x%0x (page 0x%x offset 0x%x) is %02x should be %02x\n",
+ div64_ul(ofs, meminfo.erasesize), i,
+ i / meminfo.writesize, i % meminfo.writesize,
+ rbuf[i], data[i]);
}
return ret;
}
@@ -178,12 +180,14 @@ static int erase_and_write(loff_t ofs, unsigned char *data,
}
/* Print stats of nandtest. */
-static void print_stats(int nr_passes, int length)
+static void print_stats(int nr_passes, loff_t length)
{
unsigned int i;
+ uint64_t blocks = (uint64_t)length;
+
+ do_div(blocks, meminfo.erasesize);
printf("-------- Summary --------\n");
- printf("Tested blocks : %d\n", (length/meminfo.erasesize)
- * nr_passes);
+ printf("Tested blocks : %lld\n", blocks * nr_passes);
for (i = 0; i < MAX_ECC_BITS; i++)
printf("ECC %d bit error(s) : %u\n", i + 1, ecc_stats[i]);
diff --git a/commands/nv.c b/commands/nv.c
index 8d4192402c..c60bb41677 100644
--- a/commands/nv.c
+++ b/commands/nv.c
@@ -55,11 +55,8 @@ static int do_nv(int argc, char *argv[])
for (i = 0; i < argc; i++) {
int ret;
- value = strchr(argv[0], '=');
- if (value) {
- *value = 0;
- value++;
- }
+
+ value = parse_assignment(argv[i]) ?: "";
if (do_remove) {
ret = nvvar_remove(argv[i]);
diff --git a/commands/nvmem.c b/commands/nvmem.c
new file mode 100644
index 0000000000..a0e3d092e3
--- /dev/null
+++ b/commands/nvmem.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: © 2021 Ahmad Fatoum, Pengutronix
+
+#include <common.h>
+#include <command.h>
+#include <linux/nvmem-consumer.h>
+
+static int do_nvmem(int argc, char *argv[])
+{
+ nvmem_devices_print();
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(nvmem)
+BAREBOX_CMD_HELP_TEXT("Usage: nvmem")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(nvmem)
+ .cmd = do_nvmem,
+ BAREBOX_CMD_DESC("list nvmem devices")
+ BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_HELP(cmd_nvmem_help)
+BAREBOX_CMD_END
diff --git a/commands/of_compatible.c b/commands/of_compatible.c
new file mode 100644
index 0000000000..d8704d50bb
--- /dev/null
+++ b/commands/of_compatible.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: © 2023 Ahmad Fatoum <a.fatoum@pengutronix.de>
+
+#include <common.h>
+#include <libfile.h>
+#include <fdt.h>
+#include <of.h>
+#include <command.h>
+#include <complete.h>
+#include <errno.h>
+#include <getopt.h>
+
+static int do_of_compatible(int argc, char *argv[])
+{
+ int opt;
+ int ret = 0;
+ bool fix = false, kernel_compat = false;
+ struct device_node *root = NULL, *node, *of_free = NULL;
+ char **compats, **compat, *dtbfile = NULL;
+ const char *nodename = "/";
+
+ while ((opt = getopt(argc, argv, "f:n:Fk")) > 0) {
+ switch (opt) {
+ case 'f':
+ dtbfile = optarg;
+ break;
+ case 'n':
+ nodename = optarg;
+ break;
+ case 'F':
+ fix = true;
+ break;
+ case 'k':
+ kernel_compat = true;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (argc - optind < 1)
+ return COMMAND_ERROR_USAGE;
+
+ compats = &argv[optind];
+
+ if (dtbfile) {
+ root = of_read_file(dtbfile);
+ if (IS_ERR(root))
+ return PTR_ERR(root);
+
+ of_free = root;
+ } else {
+ root = of_get_root_node();
+
+ /* copy internal device tree to apply fixups onto it */
+ if (fix)
+ root = of_free = of_dup(root);
+ }
+
+ if (fix)
+ of_fix_tree(root);
+
+ node = of_find_node_by_path_or_alias(root, nodename);
+ if (!node) {
+ printf("Cannot find nodepath %s\n", nodename);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ ret = COMMAND_ERROR;
+
+ if (kernel_compat) {
+ const char *compat_override;
+
+ if (node->parent) {
+ printf("-k only valid for root node\n");
+ ret = COMMAND_ERROR_USAGE;
+ goto out;
+ }
+
+ compat_override = barebox_get_of_machine_compatible() ?: "";
+ for (compat = compats; *compat; compat++) {
+ if (strcmp(*compat, compat_override) == 0) {
+ ret = COMMAND_SUCCESS;
+ goto out;
+ }
+ }
+ }
+
+ for (compat = compats; *compat; compat++) {
+ int score;
+
+ score = of_device_is_compatible(node, *compat);
+ if (score > 0) {
+ ret = COMMAND_SUCCESS;
+ break;
+ }
+ }
+
+out:
+ of_delete_node(of_free);
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(of_compatible)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-f dtb", "work on dtb instead of internal devicetree")
+BAREBOX_CMD_HELP_OPT ("-F", "apply fixups on devicetree before compare")
+BAREBOX_CMD_HELP_OPT ("-n node", "node path or alias to compare its compatible (default is /)")
+BAREBOX_CMD_HELP_OPT ("-k", "compare $global.of.kernel.add_machine_compatible as well")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(of_compatible)
+ .cmd = do_of_compatible,
+ BAREBOX_CMD_DESC("Check DT node's compatible")
+ BAREBOX_CMD_OPTS("[-fFnk] [COMPATS..]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+ BAREBOX_CMD_HELP(cmd_of_compatible_help)
+BAREBOX_CMD_END
diff --git a/commands/of_diff.c b/commands/of_diff.c
index 8acfd42a6b..623b033c73 100644
--- a/commands/of_diff.c
+++ b/commands/of_diff.c
@@ -16,74 +16,57 @@
static struct device_node *get_tree(const char *filename, struct device_node *root)
{
struct device_node *node;
- void *fdt;
- size_t size;
- int ret;
if (!strcmp(filename, "-")) {
- node = of_get_root_node();
- if (!node)
- return ERR_PTR(-ENOENT);
-
- return of_copy_node(NULL, node);
+ node = of_dup(root) ?: ERR_PTR(-ENOENT);
+ if (IS_ERR(node))
+ printf("Cannot duplicate live tree: %pe\n", node);
+ } else if (!strcmp(filename, "+")) {
+ return NULL;
+ } else {
+ node = of_read_file(filename);
}
- if (!strcmp(filename, "+")) {
- node = of_get_root_node();
- if (!node)
- return ERR_PTR(-ENOENT);
+ return node;
+}
- node = of_copy_node(NULL, root);
+static struct device_node *get_tree_fixed(const struct device_node *root)
+{
+ struct device_node *node;
+ node = of_dup(root);
+ if (!IS_ERR(node))
of_fix_tree(node);
- return node;
- }
-
- ret = read_file_2(filename, &size, &fdt, FILESIZE_MAX);
- if (ret)
- return ERR_PTR(ret);
-
- node = of_unflatten_dtb(fdt);
-
- free(fdt);
-
return node;
}
static int do_of_diff(int argc, char *argv[])
{
- int ret = 0;
+ int ret = COMMAND_ERROR;
struct device_node *a, *b, *root;
- if (argc < 3)
+ if (argc != 3)
return COMMAND_ERROR_USAGE;
root = of_get_root_node();
a = get_tree(argv[1], root);
b = get_tree(argv[2], root);
- if (IS_ERR(a)) {
- printf("Cannot read %s: %s\n", argv[1], strerrorp(a));
- ret = COMMAND_ERROR;
- a = NULL;
- goto out;
- }
+ if (!a && !b)
+ return COMMAND_ERROR_USAGE;
- if (IS_ERR(b)) {
- printf("Cannot read %s: %s\n", argv[2], strerrorp(b));
- ret = COMMAND_ERROR;
- b = NULL;
- goto out;
- }
+ if (!a)
+ a = get_tree_fixed(b);
+ if (!b)
+ b = get_tree_fixed(a);
- of_diff(a, b, 0);
+ if (!IS_ERR(a) && !IS_ERR(b))
+ ret = of_diff(a, b, 0) ? COMMAND_ERROR : COMMAND_SUCCESS;
- ret = 0;
-out:
- if (a && a != root)
+ if (!IS_ERR(a) && a != root)
of_delete_node(a);
- if (b && b != root)
+ if (!IS_ERR(b) && b != root)
of_delete_node(b);
return ret;
@@ -93,7 +76,7 @@ BAREBOX_CMD_HELP_START(of_diff)
BAREBOX_CMD_HELP_TEXT("This command prints a diff between two given device trees.")
BAREBOX_CMD_HELP_TEXT("The device trees are given as dtb files or:")
BAREBOX_CMD_HELP_TEXT("'-' to compare against the barebox live tree, or")
-BAREBOX_CMD_HELP_TEXT("'+' to compare against the fixed barebox live tree")
+BAREBOX_CMD_HELP_TEXT("'+' to compare against the other device tree after fixups")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(of_diff)
diff --git a/commands/of_display_timings.c b/commands/of_display_timings.c
index 27b91f311a..232074fce7 100644
--- a/commands/of_display_timings.c
+++ b/commands/of_display_timings.c
@@ -67,29 +67,9 @@ static int do_of_display_timings(int argc, char *argv[])
/* Check if external dtb given */
if (dtbfile) {
- void *fdt;
- size_t size;
-
- fdt = read_file(dtbfile, &size);
- if (!fdt) {
- pr_err("unable to read %s: %s\n", dtbfile,
- strerror(errno));
- return -errno;
- }
-
- if (file_detect_type(fdt, size) != filetype_oftree) {
- pr_err("%s is not a oftree file.\n", dtbfile);
- free(fdt);
- return -EINVAL;
- }
-
- root = of_unflatten_dtb(fdt);
-
- free(fdt);
-
+ root = of_read_file(dtbfile);
if (IS_ERR(root))
return PTR_ERR(root);
-
} else {
root = of_get_root_node();
}
@@ -98,9 +78,9 @@ static int do_of_display_timings(int argc, char *argv[])
int found = 0;
const char *node = "display-timings";
- for_each_node_by_name_from(display, root, node) {
+ for_each_node_by_name_address_from(display, root, node) {
for_each_child_of_node(display, timings) {
- printf("%s\n", timings->full_name);
+ printf("%pOF\n", timings);
found = 1;
}
}
@@ -113,13 +93,13 @@ static int do_of_display_timings(int argc, char *argv[])
int found = 0;
const char *node = "display-timings";
- for_each_node_by_name_from(display, root, node) {
+ for_each_node_by_name_address_from(display, root, node) {
timings = of_parse_phandle_from(display, root,
"native-mode", 0);
if (!timings)
continue;
- printf("%s\n", timings->full_name);
+ printf("%pOF\n", timings);
found = 1;
}
diff --git a/commands/of_dump.c b/commands/of_dump.c
index 6792af3afc..2508d4ce11 100644
--- a/commands/of_dump.c
+++ b/commands/of_dump.c
@@ -21,10 +21,13 @@ static void of_print_nodenames(struct device_node *node)
{
struct device_node *n;
- printf("%s\n", node->full_name);
+ printf("%pOF\n", node);
- list_for_each_entry(n, &node->children, parent_list)
+ list_for_each_entry(n, &node->children, parent_list) {
+ if (ctrlc())
+ return;
of_print_nodenames(n);
+ }
}
static int do_of_dump(int argc, char *argv[])
@@ -34,11 +37,11 @@ static int do_of_dump(int argc, char *argv[])
int fix = 0;
struct device_node *root = NULL, *node, *of_free = NULL;
char *dtbfile = NULL;
- size_t size;
const char *nodename;
- int names_only = 0;
+ unsigned maxpropsize = ~0;
+ int names_only = 0, properties_only = 0;
- while ((opt = getopt(argc, argv, "Ff:n")) > 0) {
+ while ((opt = getopt(argc, argv, "Ff:npP:")) > 0) {
switch (opt) {
case 'f':
dtbfile = optarg;
@@ -49,6 +52,14 @@ static int do_of_dump(int argc, char *argv[])
case 'n':
names_only = 1;
break;
+ case 'p':
+ properties_only = 1;
+ break;
+ case 'P':
+ ret = kstrtouint(optarg, 0, &maxpropsize);
+ if (ret)
+ return ret;
+ break;
default:
return COMMAND_ERROR_USAGE;
}
@@ -60,49 +71,21 @@ static int do_of_dump(int argc, char *argv[])
nodename = argv[optind];
if (dtbfile) {
- void *fdt;
-
- fdt = read_file(dtbfile, &size);
- if (!fdt) {
- printf("unable to read %s: %s\n", dtbfile, strerror(errno));
- return -errno;
- }
-
- root = of_unflatten_dtb(fdt);
-
- free(fdt);
-
- if (IS_ERR(root)) {
- ret = PTR_ERR(root);
- goto out;
- }
+ root = of_read_file(dtbfile);
+ if (IS_ERR(root))
+ return PTR_ERR(root);
of_free = root;
} else {
root = of_get_root_node();
- if (fix) {
- /* create a copy of internal devicetree */
- void *fdt;
- fdt = of_flatten_dtb(root);
- root = of_unflatten_dtb(fdt);
-
- free(fdt);
-
- if (IS_ERR(root)) {
- ret = PTR_ERR(root);
- goto out;
- }
-
- of_free = root;
- }
+ /* copy internal device tree to apply fixups onto it */
+ if (fix)
+ root = of_free = of_dup(root);
}
- if (fix) {
- ret = of_fix_tree(root);
- if (ret)
- goto out;
- }
+ if (fix)
+ of_fix_tree(root);
node = of_find_node_by_path_or_alias(root, nodename);
if (!node) {
@@ -111,14 +94,15 @@ static int do_of_dump(int argc, char *argv[])
goto out;
}
- if (names_only)
+ if (names_only && !properties_only)
of_print_nodenames(node);
+ else if (properties_only && !names_only)
+ of_print_properties(node, maxpropsize);
else
- of_print_nodes(node, 0);
+ of_print_nodes(node, 0, maxpropsize);
out:
- if (of_free)
- of_delete_node(of_free);
+ of_delete_node(of_free);
return ret;
}
@@ -128,12 +112,14 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-f dtb", "work on dtb instead of internal devicetree")
BAREBOX_CMD_HELP_OPT ("-F", "return fixed devicetree")
BAREBOX_CMD_HELP_OPT ("-n", "Print node names only, no properties")
+BAREBOX_CMD_HELP_OPT ("-p", "Print properties only, no child nodes")
+BAREBOX_CMD_HELP_OPT ("-P len", "print only len property bytes")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(of_dump)
.cmd = do_of_dump,
BAREBOX_CMD_DESC("dump devicetree nodes")
- BAREBOX_CMD_OPTS("[-fFn] [NODE]")
+ BAREBOX_CMD_OPTS("[-fFnpP] [NODE]")
BAREBOX_CMD_GROUP(CMD_GRP_MISC)
BAREBOX_CMD_COMPLETE(devicetree_file_complete)
BAREBOX_CMD_HELP(cmd_of_dump_help)
diff --git a/commands/of_fixup.c b/commands/of_fixup.c
new file mode 100644
index 0000000000..d667afb5b1
--- /dev/null
+++ b/commands/of_fixup.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * of_fixup.c - List and remove OF fixups
+ */
+
+#include <common.h>
+#include <kallsyms.h>
+#include <of.h>
+#include <command.h>
+#include <malloc.h>
+#include <complete.h>
+#include <getopt.h>
+#include <string.h>
+
+static int do_of_fixup(int argc, char *argv[])
+{
+ struct of_fixup *of_fixup;
+ int opt, enable = -1;
+ bool did_fixup = false;
+
+ while ((opt = getopt(argc, argv, "ed")) > 0) {
+ switch (opt) {
+ case 'e':
+ enable = 1;
+ break;
+ case 'd':
+ enable = 0;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if ((enable < 0 && argc > 0) || (enable >= 0 && argc == 0))
+ return COMMAND_ERROR_USAGE;
+
+ list_for_each_entry(of_fixup, &of_fixup_list, list) {
+ int i;
+ ulong addr = (ulong)of_fixup->fixup;
+ char sym[KSYM_SYMBOL_LEN];
+ const char *name;
+
+ name = kallsyms_lookup(addr, NULL, NULL, NULL, sym);
+ if (!name) {
+ sprintf(sym, "<0x%lx>", addr);
+ name = sym;
+ }
+
+ if (enable == -1) {
+ printf("%s(0x%p)%s\n", name, of_fixup->context,
+ of_fixup->disabled ? " [DISABLED]" : "");
+ continue;
+ }
+
+ for (i = 0; i < argc; i++) {
+ if (strcmp(name, argv[i]) != 0)
+ continue;
+
+ of_fixup->disabled = !enable;
+ did_fixup = true;
+ }
+ }
+
+ if (argc && !did_fixup) {
+ printf("none of the specified fixups found\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(of_fixup)
+BAREBOX_CMD_HELP_TEXT("Disable or re-enable an already registered fixup for the device tree.")
+BAREBOX_CMD_HELP_TEXT("Call without arguments to list all fixups")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-d", "disable fixup")
+BAREBOX_CMD_HELP_OPT("-e", "re-enable fixup")
+BAREBOX_CMD_HELP_OPT("fixups", "List of fixups to enable or disable")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(of_fixup)
+ .cmd = do_of_fixup,
+ BAREBOX_CMD_DESC("list and enable/disable fixups")
+ BAREBOX_CMD_OPTS("[-de] [fixups...]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+ BAREBOX_CMD_HELP(cmd_of_fixup_help)
+BAREBOX_CMD_END
diff --git a/commands/of_overlay.c b/commands/of_overlay.c
index aa4b6484ca..2013c4b278 100644
--- a/commands/of_overlay.c
+++ b/commands/of_overlay.c
@@ -10,45 +10,46 @@
#include <getopt.h>
#include <libfile.h>
#include <of.h>
+#include <linux/clk.h>
static int do_of_overlay(int argc, char *argv[])
{
- int opt, ret;
- struct fdt_header *fdt;
+ int ret;
struct device_node *overlay;
- const char *search_path = NULL;
+ bool live_tree = false;
+ int opt;
- while ((opt = getopt(argc, argv, "S:")) > 0) {
+ while ((opt = getopt(argc, argv, "l")) > 0) {
switch (opt) {
- case 'S':
- search_path = optarg;
+ case 'l':
+ live_tree = true;
break;
- default:
- return COMMAND_ERROR_USAGE;
}
}
if (argc != optind + 1)
return COMMAND_ERROR_USAGE;
- fdt = read_file(argv[optind], NULL);
- if (!fdt) {
- printf("cannot read %s\n", argv[optind]);
+ if (live_tree && !IS_ENABLED(CONFIG_OF_OVERLAY_LIVE)) {
+ printf("Support for live tree overlays is disabled. Enable CONFIG_OF_OVERLAY_LIVE\n");
return 1;
}
- overlay = of_unflatten_dtb(fdt);
- free(fdt);
+ overlay = of_read_file(argv[optind]);
if (IS_ERR(overlay))
return PTR_ERR(overlay);
- if (search_path) {
- ret = of_firmware_load_overlay(overlay, search_path);
+ if (live_tree) {
+ ret = of_overlay_apply_tree(of_get_root_node(), overlay);
if (ret)
goto err;
+
+ of_clk_init();
+ of_probe();
+ } else {
+ ret = of_register_overlay(overlay);
}
- ret = of_register_overlay(overlay);
if (ret) {
printf("cannot apply oftree overlay: %s\n", strerror(-ret));
goto err;
@@ -62,14 +63,21 @@ err:
}
BAREBOX_CMD_HELP_START(of_overlay)
+BAREBOX_CMD_HELP_TEXT("Register a device tree overlay file (dtbo) with barebox.")
+BAREBOX_CMD_HELP_TEXT("By default the overlay is registered as a fixup and the")
+BAREBOX_CMD_HELP_TEXT("overlay will then be applied to the Linux device tree.")
+BAREBOX_CMD_HELP_TEXT("With -l given the overlay is applied to the barebox live")
+BAREBOX_CMD_HELP_TEXT("tree instead. This involves probing new devices added in")
+BAREBOX_CMD_HELP_TEXT("the overlay file.")
+BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
-BAREBOX_CMD_HELP_OPT("-S path", "load firmware using this search path")
+BAREBOX_CMD_HELP_OPT("-l", "apply to barebox live tree")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(of_overlay)
.cmd = do_of_overlay,
- BAREBOX_CMD_DESC("register device tree overlay as fixup")
- BAREBOX_CMD_OPTS("[-S path] FILE")
+ BAREBOX_CMD_DESC("register device tree overlay")
+ BAREBOX_CMD_OPTS("[-l] FILE")
BAREBOX_CMD_GROUP(CMD_GRP_MISC)
BAREBOX_CMD_HELP(cmd_of_overlay_help)
BAREBOX_CMD_END
diff --git a/commands/of_property.c b/commands/of_property.c
index 3d5097165b..0c914c55c6 100644
--- a/commands/of_property.c
+++ b/commands/of_property.c
@@ -4,6 +4,7 @@
/* of_property.c - device tree property handling support */
#include <common.h>
+#include <libfile.h>
#include <environment.h>
#include <fdt.h>
#include <of.h>
@@ -18,7 +19,7 @@
#include <init.h>
#include <xfuncs.h>
-static int of_parse_prop_cells(char * const *newval, int count, char *data, int *len)
+static int of_parse_prop_cells(struct device_node *root, char * const *newval, int count, char *data, int *len)
{
char *cp;
unsigned long tmp; /* holds converted values */
@@ -60,7 +61,7 @@ static int of_parse_prop_cells(char * const *newval, int count, char *data, int
str = xzalloc(len + 1);
strncpy(str, cp, len);
- n = of_find_node_by_path_or_alias(NULL, str);
+ n = of_find_node_by_path_or_alias(root, str);
if (!n)
printf("Cannot find node '%s'\n", str);
@@ -164,7 +165,7 @@ static int of_parse_prop_string(char * const *newval, int count, char *data, int
* data: A bytestream to be placed in the property
* len: The length of the resulting bytestream
*/
-static int of_parse_prop(char * const *newval, int count, char *data, int *len)
+static int of_parse_prop(struct device_node *root, char * const *newval, int count, char *data, int *len)
{
char *newp; /* temporary newval char pointer */
@@ -177,7 +178,7 @@ static int of_parse_prop(char * const *newval, int count, char *data, int *len)
switch (*newp) {
case '<':
- return of_parse_prop_cells(newval, count, data, len);
+ return of_parse_prop_cells(root, newval, count, data, len);
case '[':
return of_parse_prop_stream(newval, count, data, len);
default:
@@ -302,8 +303,12 @@ static int do_of_property(int argc, char *argv[])
int set = 0;
int fixup = 0;
char *path, *propname;
+ char *dtbfile = NULL;
+ int ret = 0;
+ struct fdt_header *fdt = NULL;
+ struct device_node *root = NULL;
- while ((opt = getopt(argc, argv, "dsf")) > 0) {
+ while ((opt = getopt(argc, argv, "dsfe:")) > 0) {
switch (opt) {
case 'd':
delete = 1;
@@ -314,6 +319,9 @@ static int do_of_property(int argc, char *argv[])
case 'f':
fixup = 1;
break;
+ case 'e':
+ dtbfile = optarg;
+ break;
default:
return COMMAND_ERROR_USAGE;
}
@@ -327,8 +335,16 @@ static int do_of_property(int argc, char *argv[])
debug("path: %s propname: %s\n", path, propname);
+ if ( !(set || delete))
+ return COMMAND_ERROR_USAGE;
+
+ if (dtbfile) {
+ root = of_read_file(dtbfile);
+ if (IS_ERR(root))
+ return PTR_ERR(root);
+ }
+
if (set) {
- int ret;
int len;
void *data;
@@ -340,10 +356,10 @@ static int do_of_property(int argc, char *argv[])
if (!data)
return -ENOMEM;
- ret = of_parse_prop(&argv[optind + 2], argc - optind - 2, data, &len);
+ ret = of_parse_prop(root, &argv[optind + 2], argc - optind - 2, data, &len);
if (ret) {
free(data);
- return ret;
+ goto out;
}
if (fixup) {
@@ -351,21 +367,36 @@ static int do_of_property(int argc, char *argv[])
if (ret)
free(data);
} else {
- ret = do_of_property_set_now(NULL, path, propname, data, len);
+ ret = do_of_property_set_now(root, path, propname, data, len);
free(data);
}
- return ret;
- }
+ if (ret)
+ goto out;
- if (delete) {
+ } else if (delete) {
if (fixup)
- return do_of_property_delete_fixup(path, propname);
+ ret = do_of_property_delete_fixup(path, propname);
else
- return do_of_property_delete_now(NULL, path, propname);
+ ret = do_of_property_delete_now(root, path, propname);
+
+ if (ret)
+ goto out;
}
- return COMMAND_ERROR_USAGE;
+ if (root && !fixup) {
+ fdt = of_flatten_dtb(root);
+
+ ret = write_file(dtbfile, fdt, fdt32_to_cpu(fdt->totalsize));
+
+ free(fdt);
+ }
+
+out:
+
+ of_delete_node(root);
+
+ return ret;
}
BAREBOX_CMD_HELP_START(of_property)
@@ -373,6 +404,7 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-s", "set property to value")
BAREBOX_CMD_HELP_OPT ("-d", "delete property")
BAREBOX_CMD_HELP_OPT ("-f", "set/delete as a fixup (defer the action until booting)")
+BAREBOX_CMD_HELP_OPT ("-e dtb", "set/delete/fixup from external dtb")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Valid formats for values:")
BAREBOX_CMD_HELP_TEXT("<0x00112233 4 05> - an array of cells. cells not beginning with a digit are")
@@ -384,8 +416,8 @@ BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(of_property)
.cmd = do_of_property,
BAREBOX_CMD_DESC("handle device tree properties")
- BAREBOX_CMD_OPTS("[-sd] [-f] NODE [PROPERTY] [VALUES]")
+ BAREBOX_CMD_OPTS("[-sd] [-e] [-f] NODE [PROPERTY] [VALUES]")
BAREBOX_CMD_GROUP(CMD_GRP_MISC)
- BAREBOX_CMD_COMPLETE(devicetree_complete)
+ BAREBOX_CMD_COMPLETE(devicetree_file_complete)
BAREBOX_CMD_HELP(cmd_of_property_help)
BAREBOX_CMD_END
diff --git a/commands/oftree.c b/commands/oftree.c
index 1d902f2830..76227a10b0 100644
--- a/commands/oftree.c
+++ b/commands/oftree.c
@@ -31,7 +31,6 @@
static int do_oftree(int argc, char *argv[])
{
struct fdt_header *fdt = NULL;
- size_t size;
int opt;
int probe = 0;
char *load = NULL;
@@ -76,16 +75,7 @@ static int do_oftree(int argc, char *argv[])
}
if (load) {
- fdt = read_file(load, &size);
- if (!fdt) {
- printf("unable to read %s\n", load);
- return 1;
- }
-
- root = of_unflatten_dtb(fdt);
-
- free(fdt);
-
+ root = of_read_file(load);
if (IS_ERR(root))
return PTR_ERR(root);
diff --git a/commands/parted.c b/commands/parted.c
new file mode 100644
index 0000000000..6af18cdc57
--- /dev/null
+++ b/commands/parted.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <common.h>
+#include <command.h>
+#include <block.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <disks.h>
+#include <linux/sizes.h>
+#include <partitions.h>
+#include <linux/math64.h>
+
+static struct partition_desc *gpdesc;
+static bool table_needs_write;
+static const char *gunit_str = "KiB";
+static uint64_t gunit = 1024;
+
+struct unit {
+ const char *str;
+ uint64_t size;
+};
+
+static struct unit units[] = {
+ { .str = "B", .size = 1 },
+ { .str = "s", .size = 512 },
+ { .str = "KiB", .size = SZ_1K },
+ { .str = "MiB", .size = SZ_1M },
+ { .str = "GiB", .size = SZ_1G },
+ { .str = "TiB", .size = SZ_1T },
+ { .str = "KB", .size = 1000ULL },
+ { .str = "MB", .size = 1000ULL * 1000 },
+ { .str = "GB", .size = 1000ULL * 1000 * 1000 },
+ { .str = "TB", .size = 1000ULL * 1000 * 1000 * 1000 },
+ { .str = "k", .size = SZ_1K },
+ { .str = "K", .size = SZ_1K },
+ { .str = "M", .size = SZ_1M },
+ { .str = "G", .size = SZ_1G },
+};
+
+static int parted_strtoull(const char *str, uint64_t *val, uint64_t *mult)
+{
+ char *end;
+ int i;
+
+ *val = simple_strtoull(str, &end, 0);
+
+ if (!*end) {
+ *mult = 0;
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(units); i++) {
+ if (!strcmp(end, units[i].str)) {
+ *mult = units[i].size;
+ return 0;
+ }
+ }
+
+ printf("Error: Cannot read \"%s\" as number\n", str);
+
+ return -EINVAL;
+}
+
+static struct partition_desc *pdesc_get(struct block_device *blk)
+{
+ if (gpdesc)
+ return gpdesc;
+
+ gpdesc = partition_table_read(blk);
+ if (!gpdesc) {
+ printf("Cannot read partition table\n");
+ return NULL;
+ }
+
+ return gpdesc;
+}
+
+static int do_unit(struct block_device *blk, int argc, char *argv[])
+{
+ int i;
+
+ if (argc < 2) {
+ printf("Error: missing unit\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(units); i++) {
+ if (!strcmp(units[i].str, argv[1])) {
+ gunit_str = units[i].str;
+ gunit = units[i].size;
+ return 2;
+ }
+ }
+
+ printf("invalid unit: %s\n", argv[1]);
+
+ return -EINVAL;
+}
+
+static int do_print(struct block_device *blk, int argc, char *argv[])
+{
+ struct partition_desc *pdesc;
+ struct partition *part;
+
+ pdesc = pdesc_get(blk);
+ if (!pdesc) {
+ printf("Error: Cannot get partition table from %s\n", blk->cdev.name);
+ return -EINVAL;
+ }
+
+ printf("Disk /dev/%s: %s\n", blk->cdev.name,
+ size_human_readable(blk->num_blocks << SECTOR_SHIFT));
+ printf("Partition Table: %s\n", pdesc->parser->name);
+
+ printf("Number Start End Size Name\n");
+
+ list_for_each_entry(part, &pdesc->partitions, list) {
+ uint64_t start = part->first_sec << SECTOR_SHIFT;
+ uint64_t size = part->size << SECTOR_SHIFT;
+ uint64_t end = start + size - SECTOR_SIZE;
+
+ printf(" %3d %10llu%-3s %10llu%-3s %10llu%-3s %-36s\n",
+ part->num,
+ div64_u64(start, gunit), gunit_str,
+ div64_u64(end, gunit), gunit_str,
+ div64_u64(size, gunit), gunit_str,
+ part->name);
+ }
+
+ return 1;
+}
+
+static int do_mkpart(struct block_device *blk, int argc, char *argv[])
+{
+ struct partition_desc *pdesc;
+ uint64_t start, end;
+ const char *name, *fs_type;
+ int ret;
+ uint64_t mult;
+
+ if (argc < 5) {
+ printf("Error: Missing required arguments\n");
+ return -EINVAL;
+ }
+
+ name = argv[1];
+ fs_type = argv[2];
+
+ ret = parted_strtoull(argv[3], &start, &mult);
+ if (ret)
+ return ret;
+
+ ret = parted_strtoull(argv[4], &end, &mult);
+ if (ret)
+ return ret;
+
+ if (!mult)
+ mult = gunit;
+
+ start *= mult;
+ end *= mult;
+
+ /* If not on sector boundaries move start up and end down */
+ start = ALIGN(start, SECTOR_SIZE);
+ end = ALIGN_DOWN(end, SECTOR_SIZE);
+
+ /* convert to LBA */
+ start >>= SECTOR_SHIFT;
+ end >>= SECTOR_SHIFT;
+
+ /*
+ * When unit is >= KB then substract one sector for user convenience.
+ * It allows to start the next partition where the previous ends
+ */
+ if (mult >= 1000)
+ end -= 1;
+
+ pdesc = pdesc_get(blk);
+ if (!pdesc)
+ return -EINVAL;
+
+ ret = partition_create(pdesc, name, fs_type, start, end);
+
+ if (!ret)
+ table_needs_write = true;
+
+ return ret < 0 ? ret : 5;
+}
+
+static int do_rmpart(struct block_device *blk, int argc, char *argv[])
+{
+ struct partition_desc *pdesc;
+ unsigned long num;
+ int ret;
+
+ if (argc < 2) {
+ printf("Error: Expecting a partition number.\n");
+ return -EINVAL;
+ }
+
+ ret = kstrtoul(argv[1], 0, &num);
+ if (ret)
+ return ret;
+
+ pdesc = pdesc_get(blk);
+ if (!pdesc)
+ return -EINVAL;
+
+ ret = partition_remove(pdesc, num);
+ if (ret)
+ return ret;
+
+ table_needs_write = true;
+
+ return 2;
+}
+
+static int do_mklabel(struct block_device *blk, int argc, char *argv[])
+{
+ struct partition_desc *pdesc;
+
+ if (argc < 2) {
+ printf("Error: Expecting a disk label type.\n");
+ return -EINVAL;
+ }
+
+ pdesc = partition_table_new(blk, argv[1]);
+ if (IS_ERR(pdesc)) {
+ printf("Error: Cannot create partition table: %pe\n", pdesc);
+ return PTR_ERR(pdesc);
+ }
+
+ table_needs_write = true;
+
+ if (gpdesc)
+ partition_table_free(gpdesc);
+ gpdesc = pdesc;
+
+ return 2;
+}
+
+static int do_refresh(struct block_device *blk, int argc, char *argv[])
+{
+ struct partition_desc *pdesc;
+
+ pdesc = pdesc_get(blk);
+ if (!pdesc)
+ return -EINVAL;
+
+ table_needs_write = true;
+
+ return 1;
+}
+
+struct parted_command {
+ const char *name;
+ int (*command)(struct block_device *blk, int argc, char *argv[]);
+};
+
+struct parted_command parted_commands[] = {
+ {
+ .name = "mkpart",
+ .command = do_mkpart,
+ }, {
+ .name = "print",
+ .command = do_print,
+ }, {
+ .name = "rm",
+ .command = do_rmpart,
+ }, {
+ .name = "mklabel",
+ .command = do_mklabel,
+ }, {
+ .name = "unit",
+ .command = do_unit,
+ }, {
+ .name = "refresh",
+ .command = do_refresh,
+ },
+};
+
+static int parted_run_command(struct block_device *blk, int argc, char *argv[])
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(parted_commands); i++) {
+ struct parted_command *cmd = &parted_commands[i];
+
+ if (!strcmp(argv[0], cmd->name))
+ return cmd->command(blk, argc, argv);
+ }
+
+ printf("No such command: %s\n", argv[0]);
+
+ return COMMAND_ERROR;
+}
+
+static int do_parted(int argc, char *argv[])
+{
+ struct cdev *cdev;
+ struct block_device *blk;
+ int ret = 0;
+
+ table_needs_write = false;
+ gpdesc = NULL;
+
+ if (argc < 3)
+ return COMMAND_ERROR_USAGE;
+
+ cdev = cdev_open_by_name(argv[1], O_RDWR);
+ if (!cdev) {
+ printf("Cannot open %s\n", argv[1]);
+ return COMMAND_ERROR;
+ }
+
+ blk = cdev_get_block_device(cdev);
+ if (!blk) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ argc -= 2;
+ argv += 2;
+
+ while (argc) {
+ debug("---> run command %s\n", argv[0]);
+ ret = parted_run_command(blk, argc, argv);
+ if (ret < 0)
+ break;
+
+ argc -= ret;
+ argv += ret;
+
+ ret = 0;
+ }
+
+ if (!ret && gpdesc && table_needs_write)
+ ret = partition_table_write(gpdesc);
+
+err:
+ if (gpdesc)
+ partition_table_free(gpdesc);
+
+ cdev_close(cdev);
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(parted)
+BAREBOX_CMD_HELP_TEXT("parted is a partition manipulation program with a behaviour similar to")
+BAREBOX_CMD_HELP_TEXT("GNU Parted")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("commands:")
+BAREBOX_CMD_HELP_OPT ("print", "print partitions")
+BAREBOX_CMD_HELP_OPT ("mklabel <type>", "create a new partition table")
+BAREBOX_CMD_HELP_OPT ("rm <num>", "remove a partition")
+BAREBOX_CMD_HELP_OPT ("mkpart <name> <fstype> <start> <end>", "create a new partition")
+BAREBOX_CMD_HELP_OPT ("unit <unit>", "change display/input units")
+BAREBOX_CMD_HELP_OPT ("refresh", "refresh a partition table")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("<unit> can be one of \"s\" (sectors), \"B\" (bytes), \"kB\", \"MB\", \"GB\", \"TB\",")
+BAREBOX_CMD_HELP_TEXT("\"KiB\", \"MiB\", \"GiB\" or \"TiB\"")
+BAREBOX_CMD_HELP_TEXT("<type> must be \"gpt\"")
+BAREBOX_CMD_HELP_TEXT("<fstype> can be one of \"ext2\", \"ext3\", \"ext4\", \"fat16\", \"fat32\" or \"bbenv\"")
+BAREBOX_CMD_HELP_TEXT("<name> for MBR partition tables can be one of \"primary\", \"extended\" or")
+BAREBOX_CMD_HELP_TEXT("\"logical\". For GPT this is a name string.")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(parted)
+ .cmd = do_parted,
+ BAREBOX_CMD_DESC("edit partition tables")
+ BAREBOX_CMD_OPTS("<device> [command [options...]...]")
+ BAREBOX_CMD_GROUP(CMD_GRP_FILE)
+ BAREBOX_CMD_HELP(cmd_parted_help)
+BAREBOX_CMD_END
diff --git a/commands/partition.c b/commands/partition.c
index 44ee0359bf..14f400ccb4 100644
--- a/commands/partition.c
+++ b/commands/partition.c
@@ -16,7 +16,6 @@
#include <complete.h>
#include <driver.h>
#include <malloc.h>
-#include <partition.h>
#include <errno.h>
#include <xfuncs.h>
#include <fs.h>
diff --git a/commands/pm_domain.c b/commands/pm_domain.c
new file mode 100644
index 0000000000..ec8b769df1
--- /dev/null
+++ b/commands/pm_domain.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <command.h>
+#include <pm_domain.h>
+
+static int do_pm_domain(int argc, char *argv[])
+{
+ pm_genpd_print();
+
+ return 0;
+}
+
+BAREBOX_CMD_START(pm_domain)
+ .cmd = do_pm_domain,
+ BAREBOX_CMD_DESC("list power domains")
+ BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+BAREBOX_CMD_END
diff --git a/commands/pwm.c b/commands/pwm.c
new file mode 100644
index 0000000000..5d41fa8ff4
--- /dev/null
+++ b/commands/pwm.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: © 2023 Marc Reilly <marc@cpdesign.com.au>
+
+/* pwm - pwm commands */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <pwm.h>
+
+#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
+#define HZ_FROM_NANOSECONDS(x) (1000000000UL/(x))
+
+static bool is_equal_state(struct pwm_state *state1, struct pwm_state *state2)
+{
+ return (state1->period_ns == state2->period_ns)
+ && (state1->duty_ns == state2->duty_ns)
+ && (state1->polarity == state2->polarity)
+ && (state1->p_enable == state2->p_enable);
+}
+
+static int do_pwm_cmd(int argc, char *argv[])
+{
+ struct pwm_device *pwm = NULL;
+ struct pwm_state state, orig_state;
+ int error = 0;
+ char *devname = NULL;
+ int duty = -1, period = -1;
+ int freq = -1, width = -1;
+ bool invert_polarity = false, stop = false;
+ bool use_default_width = false;
+ bool verbose = false;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "ld:D:P:f:w:F:isv")) > 0) {
+ switch (opt) {
+ case 'l':
+ pwm_print();
+ return 0;
+ case 'd':
+ devname = optarg;
+ break;
+ case 'D':
+ duty = simple_strtol(optarg, NULL, 0);
+ break;
+ case 'P':
+ period = simple_strtol(optarg, NULL, 0);
+ break;
+ case 'F':
+ /* convenience option for changing frequency without
+ * having to specify duty width */
+ use_default_width = true;
+ /* fallthrough */
+ case 'f':
+ freq = simple_strtol(optarg, NULL, 0);
+ break;
+ case 'w':
+ width = simple_strtol(optarg, NULL, 0);
+ break;
+ case 'i':
+ invert_polarity = true;
+ break;
+ case 's':
+ stop = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (!devname) {
+ printf(" need to specify a device\n");
+ return COMMAND_ERROR;
+ }
+
+ if ((freq == 0) || (period == 0)) {
+ printf(" period or freqency needs to be non-zero\n");
+ return COMMAND_ERROR;
+ }
+
+ if (freq >= 0 && period >= 0) {
+ printf(" specify period or frequency, not both\n");
+ return COMMAND_ERROR;
+ }
+
+ if (duty >= 0 && width >= 0) {
+ printf(" specify duty or width, not both\n");
+ return COMMAND_ERROR;
+ }
+
+ if (width > 100) {
+ printf(" width (%% duty cycle) can't be more than 100%%\n");
+ return COMMAND_ERROR;
+ }
+
+ pwm = pwm_request(devname);
+ if (!pwm) {
+ printf(" pwm device %s not found\n", devname);
+ return -ENODEV;
+ }
+
+ pwm_get_state(pwm, &state);
+
+ /* argc will be at least 3 with a valid devname */
+ if (verbose || (argc <= 3)) {
+ printf("pwm params for '%s':\n", devname);
+ printf(" period : %u (ns)\n", state.period_ns);
+ printf(" duty : %u (ns)\n", state.duty_ns);
+ printf(" enabled : %d\n", state.p_enable);
+ printf(" polarity : %s\n", state.polarity == 0 ? "Normal" : "Inverted");
+ if (state.period_ns)
+ printf(" freq : %lu (Hz)\n", HZ_FROM_NANOSECONDS(state.period_ns));
+ else
+ printf(" freq : -\n");
+
+ pwm_free(pwm);
+ return 0;
+ }
+
+ if ((state.period_ns == 0) && (freq < 0) && (period < 0)) {
+ printf(" need to know some timing info: freq or period\n");
+ pwm_free(pwm);
+ return COMMAND_ERROR;
+ }
+
+ orig_state = state;
+
+ if (invert_polarity)
+ state.polarity = invert_polarity;
+
+ /* period */
+ if (freq > 0) {
+ state.p_enable = true;
+ state.period_ns = HZ_TO_NANOSECONDS(freq);
+ if (use_default_width && (width < 0)) {
+ width = 50;
+ }
+ } else if (period > 0) {
+ state.p_enable = true;
+ state.period_ns = period;
+ }
+
+ /* duty */
+ if (width >= 0) {
+ pwm_set_relative_duty_cycle(&state, width, 100);
+ } else if (duty >= 0) {
+ state.duty_ns = duty;
+ }
+
+ if (state.duty_ns > state.period_ns) {
+ printf(" duty_ns must not be greater than period_ns\n");
+ }
+
+ /* only set the state if its changed */
+ if (!is_equal_state(&orig_state, & state))
+ error = pwm_apply_state(pwm, &state);
+
+ if (error < 0)
+ printf(" error while applying state: %d\n", error);
+
+ /* stop handled as an additional step on purpose, allows turning off
+ * output (eg if duty => 0) and stopping in one command
+ */
+ if (stop > 0) {
+ state.p_enable = false;
+ error = pwm_apply_state(pwm, &state);
+ if (error < 0)
+ printf(" error while stopping: %d\n", error);
+ }
+
+ pwm_free(pwm);
+
+ return error;
+}
+
+BAREBOX_CMD_HELP_START(pwm)
+BAREBOX_CMD_HELP_TEXT("Sets pwm device parameters, or shows current value.")
+BAREBOX_CMD_HELP_TEXT(" Specify the pwm device by device name.")
+BAREBOX_CMD_HELP_TEXT(" If no other parameters are given, or if args has '-v',")
+BAREBOX_CMD_HELP_TEXT(" then show the current values only.")
+BAREBOX_CMD_HELP_TEXT(" Timings can either be specified via period + duty (on) duration,")
+BAREBOX_CMD_HELP_TEXT(" or via frequency. Duty can be given either as a percentage or time.")
+BAREBOX_CMD_HELP_TEXT(" If a parameter is not specified, the current value will be used")
+BAREBOX_CMD_HELP_TEXT(" where possible.")
+BAREBOX_CMD_HELP_TEXT(" To set an output to inactive state, set the duty to 0.")
+BAREBOX_CMD_HELP_TEXT(" (although note this will not by itself stop the pwm running.)")
+BAREBOX_CMD_HELP_TEXT(" Stopping the pwm device does not necessarily set the output to inactive,")
+BAREBOX_CMD_HELP_TEXT(" but stop is handled last, so can be done in addition to other changes.")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-l\t", "list registered PWMs")
+BAREBOX_CMD_HELP_OPT("-d <name>", "device name (eg 'pwm0')")
+BAREBOX_CMD_HELP_OPT("-D <duty_ns>", "duty cycle (ns)")
+BAREBOX_CMD_HELP_OPT("-P <period_ns>", "period (ns)")
+BAREBOX_CMD_HELP_OPT("-f <freq_hz>", "frequency (Hz)")
+BAREBOX_CMD_HELP_OPT("-w <duty_%>", "duty cycle (%) - the on 'width' of each cycle")
+BAREBOX_CMD_HELP_OPT("-i\t", "line inverted polarity")
+BAREBOX_CMD_HELP_OPT("-s\t", "stop (disable) the pwm device")
+BAREBOX_CMD_HELP_OPT("-v\t", "print current values")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(pwm)
+ .cmd = do_pwm_cmd,
+ BAREBOX_CMD_DESC("pwm")
+ BAREBOX_CMD_OPTS("[-ldDPfwisv]")
+ BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_HELP(cmd_pwm_help)
+BAREBOX_CMD_END
diff --git a/commands/readf.c b/commands/readf.c
index 8dd5a2b55a..d9d1b51243 100644
--- a/commands/readf.c
+++ b/commands/readf.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <fs.h>
diff --git a/commands/readline.c b/commands/readline.c
index ef54b5e92f..57c8fbd7bc 100644
--- a/commands/readline.c
+++ b/commands/readline.c
@@ -4,25 +4,33 @@
#include <common.h>
#include <command.h>
#include <malloc.h>
+#include <slice.h>
#include <xfuncs.h>
#include <environment.h>
static int do_readline(int argc, char *argv[])
{
- char *buf = xzalloc(CONFIG_CBSIZE);
+ char *buf;
if (argc < 3)
return COMMAND_ERROR_USAGE;
- if (readline(argv[1], buf, CONFIG_CBSIZE) < 0) {
+ buf = xzalloc(CONFIG_CBSIZE);
+
+ command_slice_release();
+
+ if (readline(argv[1], buf, CONFIG_CBSIZE - 1) < 0) {
+ command_slice_acquire();
free(buf);
- return 1;
+ return COMMAND_ERROR;
}
+ command_slice_acquire();
+
setenv(argv[2], buf);
free(buf);
- return 0;
+ return COMMAND_SUCCESS;
}
BAREBOX_CMD_HELP_START(readline)
diff --git a/commands/readlink.c b/commands/readlink.c
index fdcf175f56..55f8249028 100644
--- a/commands/readlink.c
+++ b/commands/readlink.c
@@ -31,7 +31,7 @@ static int do_readlink(int argc, char *argv[])
return COMMAND_ERROR_USAGE;
if (canonicalize) {
- char *buf = canonicalize_path(argv[optind]);
+ char *buf = canonicalize_path(AT_FDCWD, argv[optind]);
struct stat s;
if (!buf)
@@ -50,7 +50,7 @@ static int do_readlink(int argc, char *argv[])
return 0;
err:
- setenv(argv[optind + 1], "");
+ unsetenv(argv[optind + 1]);
return 1;
}
diff --git a/commands/regulator.c b/commands/regulator.c
index 3e2595f8bf..3e38b61646 100644
--- a/commands/regulator.c
+++ b/commands/regulator.c
@@ -6,16 +6,53 @@
#include <common.h>
#include <command.h>
#include <regulator.h>
+#include <getopt.h>
static int do_regulator(int argc, char *argv[])
{
- regulators_print();
+ struct regulator *chosen;
+ unsigned flags = 0;
+ int opt, ret;
+ while ((opt = getopt(argc, argv, "e:d:D")) > 0) {
+ switch (opt) {
+ case 'e':
+ case 'd':
+ chosen = regulator_get_name(optarg);
+ if (IS_ERR_OR_NULL(chosen)) {
+ printf("regulator not found\n");
+ return COMMAND_ERROR;
+ }
+
+ ret = opt == 'e' ? regulator_enable(chosen)
+ : regulator_disable(chosen);
+ regulator_put(chosen);
+ return ret;
+ case 'D':
+ flags |= REGULATOR_PRINT_DEVS;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ regulators_print(flags);
return 0;
}
+BAREBOX_CMD_HELP_START(regulator)
+ BAREBOX_CMD_HELP_TEXT("List and control regulators.")
+ BAREBOX_CMD_HELP_TEXT("Without options, displays regulator info")
+ BAREBOX_CMD_HELP_TEXT("Options:")
+ BAREBOX_CMD_HELP_OPT("-e REGULATOR\t", "enable REGULATOR")
+ BAREBOX_CMD_HELP_OPT("-d REGULATOR\t", "disable REGULATOR")
+ BAREBOX_CMD_HELP_OPT("-D\t", "list provider devices of regulators")
+BAREBOX_CMD_HELP_END
+
BAREBOX_CMD_START(regulator)
.cmd = do_regulator,
- BAREBOX_CMD_DESC("list regulators")
- BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+ BAREBOX_CMD_DESC("list and control regulators")
+ BAREBOX_CMD_OPTS("[-edD] [REGULATOR]")
+ BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_HELP(cmd_regulator_help)
BAREBOX_CMD_END
diff --git a/commands/reset.c b/commands/reset.c
index fe54e2f9b4..88e677afab 100644
--- a/commands/reset.c
+++ b/commands/reset.c
@@ -12,12 +12,12 @@
static int cmd_reset(int argc, char *argv[])
{
struct restart_handler *rst;
- int opt, shutdown_flag;
+ int opt, shutdown_flag, flags = 0;
const char *name = NULL;
shutdown_flag = 1;
- while ((opt = getopt(argc, argv, "flr:")) > 0) {
+ while ((opt = getopt(argc, argv, "flwr:")) > 0) {
switch (opt) {
case 'f':
shutdown_flag = 0;
@@ -25,6 +25,9 @@ static int cmd_reset(int argc, char *argv[])
case 'l':
restart_handlers_print();
return 0;
+ case 'w':
+ flags |= RESTART_FLAG_WARM_BOOTROM;
+ break;
case 'r':
name = optarg;
break;
@@ -33,9 +36,9 @@ static int cmd_reset(int argc, char *argv[])
}
}
- rst = restart_handler_get_by_name(name);
- if (!rst && name) {
- printf("reset '%s' does not exist\n", name);
+ rst = restart_handler_get_by_name(name, flags);
+ if (!rst && (name || flags)) {
+ printf("No matching restart handler found\n");
return COMMAND_ERROR;
}
@@ -57,13 +60,14 @@ BAREBOX_CMD_HELP_START(reset)
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT("-f", "force RESET, don't call shutdown")
BAREBOX_CMD_HELP_OPT("-l", "list reset handlers")
+BAREBOX_CMD_HELP_OPT("-w", "only consider warm BootROM reboot-mode-preserving resets")
BAREBOX_CMD_HELP_OPT("-r RESET", "use reset handler named RESET")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(reset)
.cmd = cmd_reset,
BAREBOX_CMD_DESC("perform RESET of the CPU")
- BAREBOX_CMD_OPTS("[-flr]")
+ BAREBOX_CMD_OPTS("[-flrw]")
BAREBOX_CMD_GROUP(CMD_GRP_BOOT)
BAREBOX_CMD_HELP(cmd_reset_help)
BAREBOX_CMD_COMPLETE(empty_complete)
diff --git a/commands/rm.c b/commands/rm.c
index ba52b185cb..c35cf2d2d4 100644
--- a/commands/rm.c
+++ b/commands/rm.c
@@ -12,13 +12,16 @@
static int do_rm(int argc, char *argv[])
{
- int i, opt, recursive = 0;
+ int i, opt, recursive = 0, force = 0;
- while ((opt = getopt(argc, argv, "r")) > 0) {
+ while ((opt = getopt(argc, argv, "rf")) > 0) {
switch (opt) {
case 'r':
recursive = 1;
break;
+ case 'f':
+ force = 1;
+ break;
default:
return COMMAND_ERROR_USAGE;
}
@@ -37,8 +40,10 @@ static int do_rm(int argc, char *argv[])
else
ret = unlink(argv[i]);
if (ret) {
- printf("could not remove %s: %s\n", argv[i], errno_str());
- return 1;
+ if (!force || ret != -ENOENT)
+ printf("could not remove %s: %m\n", argv[i]);
+ if (!force)
+ return 1;
}
i++;
}
@@ -49,12 +54,13 @@ static int do_rm(int argc, char *argv[])
BAREBOX_CMD_HELP_START(rm)
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-r", "remove directories and their contents recursively")
+BAREBOX_CMD_HELP_OPT ("-f", "ignore nonexistent files")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(rm)
.cmd = do_rm,
BAREBOX_CMD_DESC("remove files")
- BAREBOX_CMD_OPTS("[-r] FILES...")
+ BAREBOX_CMD_OPTS("[-rf] FILES...")
BAREBOX_CMD_GROUP(CMD_GRP_FILE)
BAREBOX_CMD_HELP(cmd_rm_help)
BAREBOX_CMD_END
diff --git a/commands/rmdir.c b/commands/rmdir.c
index e1cd5dc548..44793ca56e 100644
--- a/commands/rmdir.c
+++ b/commands/rmdir.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <fs.h>
@@ -12,7 +14,7 @@ static int do_rmdir(int argc, char *argv[])
while (i < argc) {
if (rmdir(argv[i])) {
- printf("could not remove %s: %s\n", argv[i], errno_str());
+ printf("could not remove %s: %m\n", argv[i]);
return 1;
}
i++;
diff --git a/commands/selftest.c b/commands/selftest.c
new file mode 100644
index 0000000000..bb62575aa7
--- /dev/null
+++ b/commands/selftest.c
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#define pr_fmt(fmt) "selftest: " fmt
+
+#include <common.h>
+#include <command.h>
+#include <getopt.h>
+#include <bselftest.h>
+#include <complete.h>
+
+static int run_selftest(const char *match, bool list)
+{
+ struct selftest *test;
+ int matches = 0;
+ int err = 0;
+
+ list_for_each_entry(test, &selftests, list) {
+ if (list) {
+ printf("%s\n", test->name);
+ matches++;
+ continue;
+ }
+
+ if (match && strcmp(test->name, match))
+ continue;
+
+ err |= selftest_run(test);
+ matches++;
+ }
+
+ if (!matches) {
+ if (match) {
+ printf("No tests matching '%s' found.\n", match);
+ return -EINVAL;
+ }
+
+ printf("No tests found.\n");
+ }
+
+ return err;
+}
+
+static int do_selftest(int argc, char *argv[])
+{
+ bool list = false;
+ int i, err = 0;
+ int opt;
+
+ while((opt = getopt(argc, argv, "l")) > 0) {
+ switch(opt) {
+ case 'l':
+ list = true;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (optind == argc) {
+ err = run_selftest(NULL, list);
+ } else {
+ for (i = optind; i < argc; i++) {
+ err = run_selftest(argv[i], list);
+ if (err)
+ goto out;
+ }
+ }
+
+out:
+ return err ? COMMAND_ERROR : COMMAND_SUCCESS;
+}
+
+BAREBOX_CMD_HELP_START(selftest)
+BAREBOX_CMD_HELP_TEXT("Run enabled barebox self-tests")
+BAREBOX_CMD_HELP_TEXT("If run without arguments, all tests are run")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-l", "list available tests")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(selftest)
+ .cmd = do_selftest,
+ BAREBOX_CMD_DESC("Run selftests")
+ BAREBOX_CMD_OPTS("[-l] [tests..]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+ BAREBOX_CMD_HELP(cmd_selftest_help)
+BAREBOX_CMD_END
diff --git a/commands/setenv.c b/commands/setenv.c
index ad26770655..99604c35c3 100644
--- a/commands/setenv.c
+++ b/commands/setenv.c
@@ -9,20 +9,22 @@
static int do_setenv(int argc, char *argv[])
{
- char *equal;
+ char *val;
+ int ret;
if (argc < 2)
return COMMAND_ERROR_USAGE;
- equal = strrchr(argv[1], '=');
- if (equal) {
- equal[0] = '\0';
- if (equal[1])
- argv[2] = &equal[1];
- }
+ val = parse_assignment(argv[1]);
+ if (val)
+ argv[2] = val;
+ if (argv[2])
+ ret = setenv(argv[1], argv[2]);
+ else
+ ret = unsetenv(argv[1]);
- return setenv(argv[1], argv[2]) ? COMMAND_ERROR : COMMAND_SUCCESS;
+ return ret ? COMMAND_ERROR : COMMAND_SUCCESS;
}
BAREBOX_CMD_HELP_START(setenv)
diff --git a/commands/smc.c b/commands/smc.c
index 2a53e1b647..3143065582 100644
--- a/commands/smc.c
+++ b/commands/smc.c
@@ -9,14 +9,15 @@
#include <asm/psci.h>
#include <asm/secure.h>
+#include <asm/barebox-arm.h>
#include <linux/arm-smccc.h>
-#define STACK_SIZE 100
+#define HANDSHAKE_STACK_SIZE 100
#define HANDSHAKE_MAGIC 0xBA12EB0C
#define ERROR_MAGIC 0xDEADBEEF
struct cpu_context {
- unsigned long stack[STACK_SIZE];
+ unsigned long stack[HANDSHAKE_STACK_SIZE];
long handshake;
};
@@ -35,12 +36,12 @@ static void noinline cpu_handshake(long *handshake)
;
}
-static void __naked second_entry(unsigned long arg0)
+static void NAKED second_entry(unsigned long arg0)
{
struct cpu_context *context = (void*)arg0;
arm_cpu_lowlevel_init();
- arm_setup_stack((unsigned long)&context->stack[STACK_SIZE]);
+ arm_setup_stack((unsigned long)&context->stack[HANDSHAKE_STACK_SIZE]);
barrier();
cpu_handshake(&context->handshake);
@@ -110,6 +111,11 @@ static int do_smc(int argc, char *argv[])
printf("found psci version %ld.%ld\n", res.a0 >> 16, res.a0 & 0xffff);
break;
case 'c':
+ if (IS_ENABLED(CONFIG_CPU_64)) {
+ printf("CPU bootstrap test not supported for ARMv8\n");
+ return COMMAND_ERROR;
+ }
+
if (!context)
context = dma_alloc_coherent(sizeof(*context),
DMA_ADDRESS_BROKEN);
diff --git a/commands/spd_decode.c b/commands/spd_decode.c
index e8ee339a91..fa8fe86cf8 100644
--- a/commands/spd_decode.c
+++ b/commands/spd_decode.c
@@ -16,13 +16,12 @@
static int do_spd_decode(int argc, char *argv[])
{
int ret;
- size_t size;
void *data;
if (argc != 2)
return COMMAND_ERROR_USAGE;
- ret = read_file_2(argv[1], &size, &data, 256);
+ ret = read_file_2(argv[1], NULL, &data, 256);
if (ret && ret != -EFBIG) {
printf("unable to read %s: %s\n", argv[1], strerror(-ret));
return COMMAND_ERROR;
diff --git a/commands/splash.c b/commands/splash.c
index abd82873cb..2eb7c5dc39 100644
--- a/commands/splash.c
+++ b/commands/splash.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <errno.h>
@@ -54,9 +56,8 @@ static int do_splash(int argc, char *argv[])
sc = fb_open(fbdev);
if (IS_ERR(sc)) {
- int ret = -PTR_ERR(sc);
- printf("fb_open: %s\n", strerror(ret));
- return ret;
+ printf("fb_open: %pe\n", sc);
+ return COMMAND_ERROR;
}
buf = gui_screen_render_buffer(sc);
diff --git a/commands/stacksmash.c b/commands/stacksmash.c
new file mode 100644
index 0000000000..e200fa5a1c
--- /dev/null
+++ b/commands/stacksmash.c
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <common.h>
+#include <command.h>
+#include <complete.h>
+#include <linux/compiler.h>
+#include <string.h>
+
+static noinline void stack_overflow_frame(void)
+{
+ volatile int length = 512;
+ char a[128] = {};
+
+ /*
+ * In order to avoid having the compiler optimize away the stack smashing
+ * we need to do a little something here.
+ */
+ OPTIMIZER_HIDE_VAR(length);
+
+ memset(a, 0xa5, length);
+
+ printf("We have smashed our stack as this should not exceed 128: sizeof(a) = %zu\n",
+ strlen(a));
+}
+
+static noinline void stack_overflow_region(u64 i)
+{
+ volatile char a[1024] = {};
+
+ if (ctrlc())
+ return;
+
+ RELOC_HIDE(&a, 0);
+
+ stack_overflow_region(0);
+
+ printf("%*ph", 1024, a);
+}
+
+static int do_stacksmash(int argc, char *argv[])
+{
+ if (argc != 2)
+ return COMMAND_ERROR_USAGE;
+
+ if (!strcmp(argv[1], "frame"))
+ stack_overflow_frame();
+ else if (!strcmp(argv[1], "region"))
+ stack_overflow_region(0);
+
+ panic("Stack smashing of %s not caught\n", argv[1]);
+}
+BAREBOX_CMD_START(stacksmash)
+ .cmd = do_stacksmash,
+ BAREBOX_CMD_DESC("Run stack smashing tests")
+ BAREBOX_CMD_OPTS("[frame | region]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+BAREBOX_CMD_END
diff --git a/commands/stat.c b/commands/stat.c
new file mode 100644
index 0000000000..10662005cd
--- /dev/null
+++ b/commands/stat.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: © 2022 Ahmad Fatoum, Pengutronix
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <linux/stat.h>
+#include <errno.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <stringlist.h>
+
+static int do_stat(int argc, char *argv[])
+{
+ int (*statfn)(int dirfd, const char *, struct stat *) = lstatat;
+ int ret, opt, dirfd = AT_FDCWD, extra_flags = 0, exitcode = 0;
+ char **filename;
+ struct stat st;
+
+ while((opt = getopt(argc, argv, "Lc:C:")) > 0) {
+ switch(opt) {
+ case 'L':
+ statfn = statat;
+ break;
+ case 'C':
+ extra_flags |= O_CHROOT;
+ fallthrough;
+ case 'c':
+ dirfd = open(optarg, O_PATH | extra_flags);
+ if (dirfd < 0)
+ return dirfd;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (optind == argc)
+ return COMMAND_ERROR_USAGE;
+
+ for (filename = &argv[optind]; *filename; filename++) {
+ ret = statfn(dirfd, *filename, &st);
+
+ if (ret) {
+ printf("%s: %s: %m\n", argv[0], *filename);
+ exitcode = COMMAND_ERROR;
+ continue;
+ }
+
+ stat_print(dirfd, *filename, &st);
+ }
+
+ close(dirfd);
+
+ return exitcode;
+}
+
+BAREBOX_CMD_HELP_START(stat)
+BAREBOX_CMD_HELP_TEXT("Display status information about the specified files")
+BAREBOX_CMD_HELP_TEXT("or directories.")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-L", "follow links")
+BAREBOX_CMD_HELP_OPT ("-c DIR", "lookup file relative to directory DIR")
+BAREBOX_CMD_HELP_OPT ("-C DIR", "change root to DIR before file lookup")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(stat)
+ .cmd = do_stat,
+ BAREBOX_CMD_DESC("display file status")
+ BAREBOX_CMD_OPTS("[-LcC] [FILEDIR...]")
+ BAREBOX_CMD_GROUP(CMD_GRP_FILE)
+ BAREBOX_CMD_HELP(cmd_stat_help)
+BAREBOX_CMD_END
diff --git a/commands/state.c b/commands/state.c
index e7cb9902f7..56ef93b19f 100644
--- a/commands/state.c
+++ b/commands/state.c
@@ -53,6 +53,9 @@ static int do_state(int argc, char *argv[])
ret = state_save(state);
}
+ if (ret == -ENOMEDIUM)
+ ret = 0;
+
return ret;
}
diff --git a/commands/test.c b/commands/test.c
index c845cec017..13005b97de 100644
--- a/commands/test.c
+++ b/commands/test.c
@@ -9,11 +9,13 @@
*/
#include <common.h>
#include <command.h>
+#include <fnmatch.h>
#include <fs.h>
#include <linux/stat.h>
typedef enum {
OPT_EQUAL,
+ OPT_EQUAL_BASH,
OPT_NOT_EQUAL,
OPT_ARITH_EQUAL,
OPT_ARITH_NOT_EQUAL,
@@ -36,6 +38,7 @@ typedef enum {
static char *test_options[] = {
[OPT_EQUAL] = "=",
+ [OPT_EQUAL_BASH] = "==",
[OPT_NOT_EQUAL] = "!=",
[OPT_ARITH_EQUAL] = "-eq",
[OPT_ARITH_NOT_EQUAL] = "-ne",
@@ -67,19 +70,81 @@ static int parse_opt(const char *opt)
return -1;
}
+static int string_comp(const char *left_op, const char *right_op, bool bash_test)
+{
+ if (bash_test)
+ return fnmatch(right_op, left_op, 0);
+
+ return strcmp(left_op, right_op);
+}
+
+static int parse_number(const char *str, long *num, bool signedcmp)
+{
+ int ret;
+
+ ret = signedcmp ? kstrtol(str, 0, num) : kstrtoul(str, 0, num);
+ if (ret)
+ printf("test: %s: integer expression expected\n", str);
+
+ return ret;
+}
+
+#define __do_arith_cmp(x, op, y, signedcmp) \
+ ((signedcmp) ? (long)(x) op (long)(y) : (x) op (y))
+
+static int arith_comp(const char *a_str, const char *b_str, int op)
+{
+ ulong a, b;
+ bool signedcmp = a_str[0] == '-' || b_str[0] == '-';
+ int ret;
+
+ ret = parse_number(a_str, &a, signedcmp);
+ if (ret)
+ return ret;
+
+ ret = parse_number(b_str, &b, signedcmp);
+ if (ret)
+ return ret;
+
+ switch (op) {
+ case OPT_ARITH_EQUAL:
+ return __do_arith_cmp(a, ==, b, signedcmp);
+ case OPT_ARITH_NOT_EQUAL:
+ return __do_arith_cmp(a, !=, b, signedcmp);
+ case OPT_ARITH_GREATER_EQUAL:
+ return __do_arith_cmp(a, >=, b, signedcmp);
+ case OPT_ARITH_GREATER_THAN:
+ return __do_arith_cmp(a, >, b, signedcmp);
+ case OPT_ARITH_LESS_EQUAL:
+ return __do_arith_cmp(a, <=, b, signedcmp);
+ case OPT_ARITH_LESS_THAN:
+ return __do_arith_cmp(a, <, b, signedcmp);
+ }
+
+ return -EINVAL;
+}
+
static int do_test(int argc, char *argv[])
{
char **ap;
int left, adv, expr, last_expr, neg, last_cmp, opt, zero;
- ulong a, b;
struct stat statbuf;
+ bool bash_test = false;
if (*argv[0] == '[') {
- if (*argv[argc - 1] != ']') {
- printf("[: missing `]'\n");
- return 1;
- }
argc--;
+ if (!strncmp(argv[0], "[[", 2)) {
+ if (strncmp(argv[argc], "]]", 2) != 0) {
+ printf("[[: missing `]]'\n");
+ return 1;
+ }
+ bash_test = true;
+ } else {
+ if (*argv[argc] != ']') {
+ printf("[: missing `]'\n");
+ return 1;
+ }
+ }
}
/* args? */
@@ -179,32 +244,24 @@ static int do_test(int argc, char *argv[])
if (left < 3)
break;
- a = simple_strtol(ap[0], NULL, 0);
- b = simple_strtol(ap[2], NULL, 0);
- switch (parse_opt(ap[1])) {
+ opt = parse_opt(ap[1]);
+ switch (opt) {
case OPT_EQUAL:
- expr = strcmp(ap[0], ap[2]) == 0;
+ case OPT_EQUAL_BASH:
+ expr = string_comp(ap[0], ap[2], bash_test) == 0;
break;
case OPT_NOT_EQUAL:
- expr = strcmp(ap[0], ap[2]) != 0;
+ expr = string_comp(ap[0], ap[2], bash_test) != 0;
break;
case OPT_ARITH_EQUAL:
- expr = a == b;
- break;
case OPT_ARITH_NOT_EQUAL:
- expr = a != b;
- break;
case OPT_ARITH_LESS_THAN:
- expr = a < b;
- break;
case OPT_ARITH_LESS_EQUAL:
- expr = a <= b;
- break;
case OPT_ARITH_GREATER_THAN:
- expr = a > b;
- break;
case OPT_ARITH_GREATER_EQUAL:
- expr = a >= b;
+ expr = arith_comp(ap[0], ap[2], opt);
+ if (expr < 0)
+ return 1;
break;
default:
expr = 1;
@@ -233,7 +290,7 @@ out:
return expr;
}
-static const char * const test_aliases[] = { "[", NULL};
+static const char * const test_aliases[] = { "[", "[[", NULL};
BAREBOX_CMD_HELP_START(test)
BAREBOX_CMD_HELP_TEXT("Options:")
diff --git a/commands/tftp.c b/commands/tftp.c
index 48ff00c621..6ac822c9e8 100644
--- a/commands/tftp.c
+++ b/commands/tftp.c
@@ -21,15 +21,24 @@ static int do_tftpb(int argc, char *argv[])
char *source, *dest, *freep;
int opt;
int tftp_push = 0;
+ int port = -1;
int ret;
IPaddr_t ip;
char ip4_str[sizeof("255.255.255.255")];
+ char mount_opts[sizeof("port=12345")];
- while ((opt = getopt(argc, argv, "p")) > 0) {
+ while ((opt = getopt(argc, argv, "pP:")) > 0) {
switch(opt) {
case 'p':
tftp_push = 1;
break;
+ case 'P':
+ port = simple_strtoul(optarg, NULL, 0);
+ if (port <= 0 || port > 0xffff) {
+ pr_err("invalid port '%s'\n", optarg);
+ return COMMAND_ERROR_USAGE;
+ }
+ break;
default:
return COMMAND_ERROR_USAGE;
}
@@ -59,7 +68,13 @@ static int do_tftpb(int argc, char *argv[])
ip = net_get_serverip();
sprintf(ip4_str, "%pI4", &ip);
- ret = mount(ip4_str, "tftp", TFTP_MOUNT_PATH, NULL);
+
+ if (port >= 0)
+ sprintf(mount_opts, "port=%u", port);
+ else
+ mount_opts[0] = '\0';
+
+ ret = mount(ip4_str, "tftp", TFTP_MOUNT_PATH, mount_opts);
if (ret)
goto err_rmdir;
@@ -84,12 +99,13 @@ BAREBOX_CMD_HELP_TEXT("server address is taken from the environment (ethX.server
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-p", "push to TFTP server")
+BAREBOX_CMD_HELP_OPT ("-P PORT", "tftp server port number")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(tftp)
.cmd = do_tftpb,
BAREBOX_CMD_DESC("load (or save) a file using TFTP")
- BAREBOX_CMD_OPTS("[-p] SOURCE [DEST]")
+ BAREBOX_CMD_OPTS("[-p] [-P <port>] SOURCE [DEST]")
BAREBOX_CMD_GROUP(CMD_GRP_NET)
BAREBOX_CMD_HELP(cmd_tftp_help)
BAREBOX_CMD_END
diff --git a/commands/time.c b/commands/time.c
index 29000d96d8..a3f2704071 100644
--- a/commands/time.c
+++ b/commands/time.c
@@ -1,29 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <clock.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <malloc.h>
+#include <getopt.h>
static int do_time(int argc, char *argv[])
{
- int i;
+ int opt;
unsigned char *buf;
u64 start, end, diff64;
- unsigned long diff;
- int len = 1; /* '\0' */
-
- if (argc < 2)
- return COMMAND_ERROR_USAGE;
+ bool nanoseconds = false;
+
+ while ((opt = getopt(argc, argv, "+n")) > 0) {
+ switch (opt) {
+ case 'n':
+ nanoseconds = true;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
- for (i = 1; i < argc; i++)
- len += strlen(argv[i]) + 1;
+ argv += optind;
+ argc -= optind;
- buf = xzalloc(len);
+ if (argc < 1)
+ return COMMAND_ERROR_USAGE;
- for (i = 1; i < argc; i++) {
- strcat(buf, argv[i]);
- strcat(buf, " ");
- }
+ buf = strjoin(" ", argv, argc);
start = get_time_ns();
@@ -33,11 +40,10 @@ static int do_time(int argc, char *argv[])
diff64 = end - start;
- do_div(diff64, 1000000);
-
- diff = diff64;
+ if (!nanoseconds)
+ do_div(diff64, 1000000);
- printf("time: %lums\n", diff);
+ printf("time: %llu%cs\n", diff64, nanoseconds ? 'n' : 'm');
free(buf);
@@ -47,12 +53,14 @@ static int do_time(int argc, char *argv[])
BAREBOX_CMD_HELP_START(time)
BAREBOX_CMD_HELP_TEXT("Note: This command depends on COMMAND being interruptible,")
BAREBOX_CMD_HELP_TEXT("otherwise the timer may overrun resulting in incorrect results")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-n", "output elapsed time in nanoseconds")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(time)
.cmd = do_time,
BAREBOX_CMD_DESC("measure execution duration of a command")
- BAREBOX_CMD_OPTS("COMMAND")
+ BAREBOX_CMD_OPTS("[-n] COMMAND")
BAREBOX_CMD_GROUP(CMD_GRP_MISC)
BAREBOX_CMD_HELP(cmd_time_help)
BAREBOX_CMD_END
diff --git a/commands/trigger.c b/commands/trigger.c
index c1402b66f0..d2802080b9 100644
--- a/commands/trigger.c
+++ b/commands/trigger.c
@@ -16,7 +16,7 @@
static int do_trigger(int argc, char *argv[])
{
- struct led *led = NULL;
+ struct led *led;
int opt, ret = 0;
int cmd = LED_COMMAND_SHOW_INFO;
enum led_trigger trigger;
@@ -35,9 +35,6 @@ static int do_trigger(int argc, char *argv[])
}
}
- if (optind < argc)
- led = led_by_name_or_number(argv[optind]);
-
switch (cmd) {
case LED_COMMAND_SHOW_INFO:
led_triggers_show_info();
diff --git a/commands/tutorial.c b/commands/tutorial.c
new file mode 100644
index 0000000000..afe5b66f0b
--- /dev/null
+++ b/commands/tutorial.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: (c) 2021 Ahmad Fatoum
+
+#include <common.h>
+#include <command.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <complete.h>
+#include <sys/stat.h>
+#include <glob.h>
+#include <getopt.h>
+#include <magicvar.h>
+#include <globalvar.h>
+
+static int next_step;
+BAREBOX_MAGICVAR(global.tutorial.step, "Next tutorial step.");
+
+#define BUFSIZE 1024
+
+static glob_t steps;
+
+static int register_tutorial_vars(void)
+{
+ char *oldcwd;
+ int ret = 0;
+
+ oldcwd = pushd("/env/data/tutorial");
+ if (!oldcwd)
+ return 0;
+
+ ret = glob("*", 0, NULL, &steps);
+ if (ret)
+ goto out;
+
+ ret = globalvar_add_simple_enum("tutorial.step", &next_step,
+ (const char **)steps.gl_pathv, steps.gl_pathc);
+
+out:
+ popd(oldcwd);
+ return ret;
+
+}
+postenvironment_initcall(register_tutorial_vars);
+
+static int print_tutorial_step(const char *step)
+{
+ bool highlight = false;
+ int fd, ret, i;
+ char *buf;
+
+ fd = open(step, O_RDONLY);
+ if (fd < 0) {
+ printf("could not open /env/data/tutorial/%s\n", step);
+ return -errno;
+ }
+
+ buf = malloc(BUFSIZE);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ printf("%s\n", step);
+
+ while((ret = read(fd, buf, BUFSIZE)) > 0) {
+ for(i = 0; i < ret; i++) {
+ if (buf[i] != '`') {
+ putchar(buf[i]);
+ continue;
+ }
+
+ puts(highlight ? "\e[0m" : "\e[1;31m");
+ highlight = !highlight;
+ }
+ }
+
+ free(buf);
+out:
+ close(fd);
+
+ return ret;
+}
+
+static int do_tutorial_next(int argc, char *argv[])
+{
+ int opt, i;
+ char *oldcwd;
+ ssize_t ret = 0;
+ bool is_prev = *argv[0] == 'p';
+
+ while ((opt = getopt(argc, argv, "rh")) > 0) {
+ switch (opt) {
+ case 'r':
+ if (steps.gl_pathc) {
+ globalvar_remove("tutorial.step");
+ next_step = 0;
+ globfree(&steps);
+ steps.gl_pathc = 0;
+ }
+ ret = register_tutorial_vars();
+ if (ret == 0 && steps.gl_pathc == 0)
+ ret = -ENOENT;
+ if (ret)
+ printf("could not load /env/data/tutorial/\n");
+ return ret;
+ case 'h':
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (optind > argc + 1)
+ return COMMAND_ERROR_USAGE;
+
+ oldcwd = pushd("/env/data/tutorial");
+ if (!oldcwd)
+ return ret;
+
+ if (is_prev)
+ next_step = next_step > 0 ? next_step - 1 : 0;
+
+ if (optind == argc) {
+ ret = print_tutorial_step(steps.gl_pathv[next_step]);
+ if (ret == 0 && !is_prev)
+ next_step = (next_step + 1) % steps.gl_pathc;
+ } else {
+ for (i = optind; i < argc; i++) {
+ ret = print_tutorial_step(argv[i]);
+ if (ret)
+ break;
+ }
+ }
+
+ popd(oldcwd);
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(next)
+BAREBOX_CMD_HELP_TEXT("Help navigate the barebox tutorial")
+BAREBOX_CMD_HELP_TEXT("Without a parameter, the next or previous tutorial step is printed")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-h\t", "show usage text")
+BAREBOX_CMD_HELP_OPT("-r\t", "rewind and reload tutorial")
+BAREBOX_CMD_HELP_END
+
+static __maybe_unused const char *const prev_alias[] = { "prev", NULL};
+
+BAREBOX_CMD_START(next)
+ .cmd = do_tutorial_next,
+ .aliases = prev_alias,
+ BAREBOX_CMD_DESC("navigate the barebox tutorial")
+ BAREBOX_CMD_OPTS("[-hr] [STEP]")
+ BAREBOX_CMD_HELP(cmd_next_help)
+ BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+ BAREBOX_CMD_COMPLETE(tutorial_complete)
+BAREBOX_CMD_END
diff --git a/commands/ubi.c b/commands/ubi.c
index f37684102d..6abd054af3 100644
--- a/commands/ubi.c
+++ b/commands/ubi.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <fs.h>
@@ -304,8 +306,8 @@ static int do_ubirmvol(int argc, char *argv[])
desc = ubi_open_volume_nm(ubinum, argv[2], UBI_EXCLUSIVE);
if (IS_ERR(desc)) {
+ printf("failed to open volume %s: %pe\n", argv[2], desc);
ret = PTR_ERR(desc);
- printf("failed to open volume %s: %s\n", argv[2], strerror(-ret));
goto err;
}
diff --git a/commands/ubsan.c b/commands/ubsan.c
index 620b4774c3..4a9716139c 100644
--- a/commands/ubsan.c
+++ b/commands/ubsan.c
@@ -102,6 +102,8 @@ static void test_ubsan_object_size_mismatch(void)
volatile long long *ptr, val2;
ptr = (long long *)&val;
+ OPTIMIZER_HIDE_VAR(ptr);
+
val2 = *ptr;
}
diff --git a/commands/uimage.c b/commands/uimage.c
index 982da7101a..72b827b5b2 100644
--- a/commands/uimage.c
+++ b/commands/uimage.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <image.h>
@@ -11,7 +13,7 @@
static int uimage_fd;
-static int uimage_flush(void *buf, unsigned int len)
+static long uimage_flush(void *buf, unsigned long len)
{
return write_full(uimage_fd, buf, len);
}
@@ -19,7 +21,7 @@ static int uimage_flush(void *buf, unsigned int len)
static int do_uimage(int argc, char *argv[])
{
struct uimage_handle *handle;
- int ret;
+ int ret = 0;
int verify = 0;
int fd;
int opt;
@@ -84,7 +86,7 @@ static int do_uimage(int argc, char *argv[])
err:
uimage_close(handle);
- return ret ? 1 : 0;
+ return ret ? COMMAND_ERROR : COMMAND_SUCCESS;
}
BAREBOX_CMD_HELP_START(uimage)
diff --git a/commands/uptime.c b/commands/uptime.c
new file mode 100644
index 0000000000..d67538631c
--- /dev/null
+++ b/commands/uptime.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <command.h>
+#include <clock.h>
+#include <getopt.h>
+#include <linux/math64.h>
+
+#define NSEC_PER_MINUTE (NSEC_PER_SEC * 60LL)
+#define NSEC_PER_HOUR (NSEC_PER_MINUTE * 60LL)
+#define NSEC_PER_DAY (NSEC_PER_HOUR * 24LL)
+#define NSEC_PER_WEEK (NSEC_PER_DAY * 7LL)
+
+static bool print_with_unit(u64 val, const char *unit, bool comma)
+{
+ if (!val)
+ return comma;
+
+ printf("%s%llu %s%s", comma ? ", " : "", val, unit, val > 1 ? "s" : "");
+ return true;
+}
+
+static int do_uptime(int argc, char *argv[])
+{
+ u64 timestamp, weeks, days, hours, minutes;
+ bool comma = false;
+ int opt;
+
+ timestamp = get_time_ns();
+
+ while((opt = getopt(argc, argv, "n")) > 0) {
+ switch(opt) {
+ case 'n':
+ printf("up %lluns\n", timestamp);
+ return 0;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (optind != argc)
+ return COMMAND_ERROR_USAGE;
+
+ printf("up ");
+
+ weeks = div64_u64_rem(timestamp, NSEC_PER_WEEK, &timestamp);
+ days = div64_u64_rem(timestamp, NSEC_PER_DAY, &timestamp);
+ hours = div64_u64_rem(timestamp, NSEC_PER_HOUR, &timestamp);
+ minutes = div64_u64_rem(timestamp, NSEC_PER_MINUTE, &timestamp);
+
+ comma = print_with_unit(weeks, "week", false);
+ comma = print_with_unit(days, "day", comma);
+ comma = print_with_unit(hours, "hour", comma);
+ comma = print_with_unit(minutes, "minute", comma);
+
+ if (!comma) {
+ u64 seconds = div64_u64_rem(timestamp, NSEC_PER_SEC, &timestamp);
+ print_with_unit(seconds, "second", false);
+ }
+
+ printf("\n");
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(uptime)
+BAREBOX_CMD_HELP_TEXT("This command formats the number of elapsed nanoseconds")
+BAREBOX_CMD_HELP_TEXT("as measured with the current clocksource")
+BAREBOX_CMD_HELP_TEXT("Note: Timekeeping is co-operative. If long running code does")
+BAREBOX_CMD_HELP_TEXT("not use delay/is_timeout/get_time_ns/getchar functions")
+BAREBOX_CMD_HELP_TEXT("timer may overrun resulting in incorrect results")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-n", "output elapsed time in nanoseconds")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(uptime)
+ .cmd = do_uptime,
+ BAREBOX_CMD_DESC("Tell how long barebox has been running")
+ BAREBOX_CMD_OPTS("[-n]")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_HELP(cmd_uptime_help)
+BAREBOX_CMD_END
diff --git a/commands/usb.c b/commands/usb.c
index ca8d3e0d52..0588ba6968 100644
--- a/commands/usb.c
+++ b/commands/usb.c
@@ -6,7 +6,7 @@
#include <common.h>
#include <command.h>
#include <complete.h>
-#include <usb/usb.h>
+#include <linux/usb/usb.h>
#include <getopt.h>
/* shows the device tree recursively */
diff --git a/commands/usbgadget.c b/commands/usbgadget.c
index 9133402f52..e69660fde5 100644
--- a/commands/usbgadget.c
+++ b/commands/usbgadget.c
@@ -12,32 +12,35 @@
#include <getopt.h>
#include <fs.h>
#include <xfuncs.h>
-#include <usb/usbserial.h>
-#include <usb/dfu.h>
-#include <usb/gadget-multi.h>
+#include <linux/usb/usbserial.h>
+#include <linux/usb/dfu.h>
+#include <linux/usb/gadget-multi.h>
static int do_usbgadget(int argc, char *argv[])
{
+ struct usbgadget_funcs funcs = {};
int opt;
- bool acm = false, dfu = false, fastboot = false, export_bbu = false;
- const char *fastboot_opts = NULL, *dfu_opts = NULL;
- while ((opt = getopt(argc, argv, "asdA::D::b")) > 0) {
+ while ((opt = getopt(argc, argv, "asdA::D::S::b")) > 0) {
switch (opt) {
case 'a':
case 's':
- acm = true;
+ funcs.flags |= USBGADGET_ACM;
break;
case 'D':
- dfu = true;
- dfu_opts = optarg;
+ funcs.flags |= USBGADGET_DFU;
+ funcs.dfu_opts = optarg;
break;
case 'A':
- fastboot = true;
- fastboot_opts = optarg;
+ funcs.flags |= USBGADGET_FASTBOOT;
+ funcs.fastboot_opts = optarg;
+ break;
+ case 'S':
+ funcs.flags |= USBGADGET_MASS_STORAGE;
+ funcs.ums_opts = optarg;
break;
case 'b':
- export_bbu = true;
+ funcs.flags |= USBGADGET_EXPORT_BBU;
break;
case 'd':
usb_multi_unregister();
@@ -47,8 +50,8 @@ static int do_usbgadget(int argc, char *argv[])
}
}
- return usbgadget_register(dfu, dfu_opts, fastboot, fastboot_opts, acm,
- export_bbu);
+
+ return usbgadget_register(&funcs);
}
BAREBOX_CMD_HELP_START(usbgadget)
@@ -58,16 +61,19 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-a\t", "Create CDC ACM function")
BAREBOX_CMD_HELP_OPT ("-A <desc>", "Create Android Fastboot function. If 'desc' is not provided, "
"try to use 'global.fastboot.partitions' variable.")
-BAREBOX_CMD_HELP_OPT ("-b\t", "include registered barebox update handlers (fastboot specific)")
+BAREBOX_CMD_HELP_OPT ("-b\t", "include registered barebox update handlers (fastboot specific,"
+ "exported as 'bbu-<update_handler_name>' partitions)")
BAREBOX_CMD_HELP_OPT ("-D <desc>", "Create DFU function. If 'desc' is not provided, "
"try to use 'global.usbgadget.dfu_function' variable.")
+BAREBOX_CMD_HELP_OPT ("-S <desc>", "Create USB Mass Storage function. If 'desc' is not provided,"
+ "fallback directly to 'global.system.partitions' variable.")
BAREBOX_CMD_HELP_OPT ("-d\t", "Disable the currently running gadget")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(usbgadget)
.cmd = do_usbgadget,
BAREBOX_CMD_DESC("Create USB Gadget multifunction device")
- BAREBOX_CMD_OPTS("[-asdAD]")
+ BAREBOX_CMD_OPTS("[-adADS]")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_usbgadget_help)
BAREBOX_CMD_END
diff --git a/commands/usbserial.c b/commands/usbserial.c
index 567018c233..17a4afec42 100644
--- a/commands/usbserial.c
+++ b/commands/usbserial.c
@@ -11,7 +11,7 @@
#include <getopt.h>
#include <fs.h>
#include <xfuncs.h>
-#include <usb/usbserial.h>
+#include <linux/usb/usbserial.h>
static int do_usbserial(int argc, char *argv[])
{
diff --git a/commands/version.c b/commands/version.c
index 764c208767..0ad8e587de 100644
--- a/commands/version.c
+++ b/commands/version.c
@@ -7,7 +7,7 @@
static int do_version(int argc, char *argv[])
{
- printf ("\n%s\n", version_string);
+ printf ("\n%s\n\n", version_string);
return 0;
}
diff --git a/commands/wd.c b/commands/wd.c
index c186244b2b..11f888133a 100644
--- a/commands/wd.c
+++ b/commands/wd.c
@@ -18,11 +18,13 @@ static int do_wd(int argc, char *argv[])
int opt;
int rc;
- while ((opt = getopt(argc, argv, "d:")) > 0) {
+ while ((opt = getopt(argc, argv, "d:x")) > 0) {
switch (opt) {
case 'd':
wd = watchdog_get_by_name(optarg);
break;
+ case 'x':
+ return watchdog_inhibit_all();
default:
return COMMAND_ERROR_USAGE;
}
@@ -66,12 +68,13 @@ BAREBOX_CMD_HELP_TEXT("When TIME is 0, the watchdog gets disabled,")
BAREBOX_CMD_HELP_TEXT("Without a parameter the watchdog will be re-triggered.")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT("-d DEVICE\t", "watchdog name (default is highest priority watchdog)")
+BAREBOX_CMD_HELP_OPT("-x\t", "inhibit all watchdogs (i.e. disable or autopoll if possible)")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(wd)
.cmd = do_wd,
BAREBOX_CMD_DESC("enable/disable/trigger the watchdog")
- BAREBOX_CMD_OPTS("[-d DEVICE] [TIME]")
+ BAREBOX_CMD_OPTS("[-d DEVICE] [-x] [TIME]")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_wd_help)
BAREBOX_CMD_COMPLETE(device_complete)