aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/cmd
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/cmd
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/cmd')
-rw-r--r--roms/u-boot/cmd/.gitignore6
-rw-r--r--roms/u-boot/cmd/Kconfig2383
-rw-r--r--roms/u-boot/cmd/Makefile255
-rw-r--r--roms/u-boot/cmd/ab_select.c56
-rw-r--r--roms/u-boot/cmd/abootimg.c260
-rw-r--r--roms/u-boot/cmd/acpi.c200
-rw-r--r--roms/u-boot/cmd/adc.c159
-rw-r--r--roms/u-boot/cmd/addrmap.c35
-rw-r--r--roms/u-boot/cmd/adtimg.c244
-rw-r--r--roms/u-boot/cmd/aes.c111
-rw-r--r--roms/u-boot/cmd/arm/Makefile7
-rw-r--r--roms/u-boot/cmd/arm/exception.c61
-rw-r--r--roms/u-boot/cmd/arm/exception64.c33
-rw-r--r--roms/u-boot/cmd/armflash.c300
-rw-r--r--roms/u-boot/cmd/avb.c476
-rw-r--r--roms/u-boot/cmd/axi.c355
-rw-r--r--roms/u-boot/cmd/bcb.c392
-rw-r--r--roms/u-boot/cmd/bdinfo.c142
-rw-r--r--roms/u-boot/cmd/bedbug.c414
-rw-r--r--roms/u-boot/cmd/bind.c257
-rw-r--r--roms/u-boot/cmd/binop.c154
-rw-r--r--roms/u-boot/cmd/blk_common.c99
-rw-r--r--roms/u-boot/cmd/blkcache.c87
-rw-r--r--roms/u-boot/cmd/blob.c124
-rw-r--r--roms/u-boot/cmd/bloblist.c40
-rw-r--r--roms/u-boot/cmd/bmp.c281
-rw-r--r--roms/u-boot/cmd/boot.c70
-rw-r--r--roms/u-boot/cmd/bootcount.c61
-rw-r--r--roms/u-boot/cmd/bootefi.c684
-rw-r--r--roms/u-boot/cmd/booti.c160
-rw-r--r--roms/u-boot/cmd/bootm.c554
-rw-r--r--roms/u-boot/cmd/bootmenu.c542
-rw-r--r--roms/u-boot/cmd/bootstage.c96
-rw-r--r--roms/u-boot/cmd/bootz.c111
-rw-r--r--roms/u-boot/cmd/broadcom/Makefile6
-rw-r--r--roms/u-boot/cmd/broadcom/chimp_boot.c37
-rw-r--r--roms/u-boot/cmd/broadcom/chimp_handshake.c33
-rw-r--r--roms/u-boot/cmd/broadcom/nitro_image_load.c125
-rw-r--r--roms/u-boot/cmd/btrfs.c27
-rw-r--r--roms/u-boot/cmd/button.c86
-rw-r--r--roms/u-boot/cmd/cache.c117
-rw-r--r--roms/u-boot/cmd/cbfs.c230
-rw-r--r--roms/u-boot/cmd/clk.c119
-rw-r--r--roms/u-boot/cmd/clone.c128
-rw-r--r--roms/u-boot/cmd/cls.c35
-rw-r--r--roms/u-boot/cmd/config.c45
-rw-r--r--roms/u-boot/cmd/conitrace.c52
-rw-r--r--roms/u-boot/cmd/console.c53
-rw-r--r--roms/u-boot/cmd/cpu.c117
-rw-r--r--roms/u-boot/cmd/cramfs.c213
-rw-r--r--roms/u-boot/cmd/cros_ec.c570
-rw-r--r--roms/u-boot/cmd/dataflash_mmc_mux.c48
-rw-r--r--roms/u-boot/cmd/date.c251
-rw-r--r--roms/u-boot/cmd/demo.c133
-rw-r--r--roms/u-boot/cmd/dfu.c115
-rw-r--r--roms/u-boot/cmd/diag.c59
-rw-r--r--roms/u-boot/cmd/disk.c132
-rw-r--r--roms/u-boot/cmd/dm.c118
-rw-r--r--roms/u-boot/cmd/echo.c43
-rw-r--r--roms/u-boot/cmd/eeprom.c456
-rw-r--r--roms/u-boot/cmd/efi.c282
-rw-r--r--roms/u-boot/cmd/efidebug.c1787
-rw-r--r--roms/u-boot/cmd/elf.c309
-rw-r--r--roms/u-boot/cmd/ethsw.c1103
-rw-r--r--roms/u-boot/cmd/exit.c23
-rw-r--r--roms/u-boot/cmd/ext2.c53
-rw-r--r--roms/u-boot/cmd/ext4.c91
-rw-r--r--roms/u-boot/cmd/extension_board.c167
-rw-r--r--roms/u-boot/cmd/fastboot.c164
-rw-r--r--roms/u-boot/cmd/fat.c137
-rw-r--r--roms/u-boot/cmd/fdt.c1109
-rw-r--r--roms/u-boot/cmd/flash.c705
-rw-r--r--roms/u-boot/cmd/fpga.c469
-rw-r--r--roms/u-boot/cmd/fpgad.c100
-rw-r--r--roms/u-boot/cmd/fs.c113
-rw-r--r--roms/u-boot/cmd/fs_uuid.c25
-rw-r--r--roms/u-boot/cmd/fuse.c146
-rw-r--r--roms/u-boot/cmd/gettime.c39
-rw-r--r--roms/u-boot/cmd/gpio.c270
-rw-r--r--roms/u-boot/cmd/gpt.c1072
-rw-r--r--roms/u-boot/cmd/hash.c56
-rw-r--r--roms/u-boot/cmd/help.c40
-rw-r--r--roms/u-boot/cmd/host.c205
-rw-r--r--roms/u-boot/cmd/i2c.c2075
-rw-r--r--roms/u-boot/cmd/ide.c60
-rw-r--r--roms/u-boot/cmd/ini.c251
-rw-r--r--roms/u-boot/cmd/io.c124
-rw-r--r--roms/u-boot/cmd/iotrace.c129
-rw-r--r--roms/u-boot/cmd/irq.c40
-rw-r--r--roms/u-boot/cmd/itest.c221
-rw-r--r--roms/u-boot/cmd/jffs2.c625
-rw-r--r--roms/u-boot/cmd/led.c142
-rw-r--r--roms/u-boot/cmd/legacy-mtd-utils.c99
-rw-r--r--roms/u-boot/cmd/legacy-mtd-utils.h12
-rw-r--r--roms/u-boot/cmd/legacy_led.c186
-rw-r--r--roms/u-boot/cmd/license.c46
-rw-r--r--roms/u-boot/cmd/load.c1096
-rw-r--r--roms/u-boot/cmd/log.c422
-rw-r--r--roms/u-boot/cmd/lsblk.c53
-rw-r--r--roms/u-boot/cmd/lzmadec.c55
-rw-r--r--roms/u-boot/cmd/mac.c33
-rw-r--r--roms/u-boot/cmd/mbr.c314
-rw-r--r--roms/u-boot/cmd/md5sum.c185
-rw-r--r--roms/u-boot/cmd/mdio.c334
-rw-r--r--roms/u-boot/cmd/mem.c1456
-rw-r--r--roms/u-boot/cmd/mfsl.c387
-rw-r--r--roms/u-boot/cmd/mii.c479
-rw-r--r--roms/u-boot/cmd/misc.c134
-rw-r--r--roms/u-boot/cmd/mmc.c1092
-rw-r--r--roms/u-boot/cmd/mp.c95
-rw-r--r--roms/u-boot/cmd/mtd.c561
-rw-r--r--roms/u-boot/cmd/mtdparts.c2135
-rw-r--r--roms/u-boot/cmd/mux.c184
-rw-r--r--roms/u-boot/cmd/mvebu/Kconfig58
-rw-r--r--roms/u-boot/cmd/mvebu/Makefile8
-rw-r--r--roms/u-boot/cmd/mvebu/bubt.c885
-rw-r--r--roms/u-boot/cmd/mvebu/comphy_rx_training.c57
-rw-r--r--roms/u-boot/cmd/nand.c1022
-rw-r--r--roms/u-boot/cmd/net.c482
-rw-r--r--roms/u-boot/cmd/nvedit.c1585
-rw-r--r--roms/u-boot/cmd/nvedit_efi.c574
-rw-r--r--roms/u-boot/cmd/nvme.c57
-rw-r--r--roms/u-boot/cmd/onenand.c610
-rw-r--r--roms/u-boot/cmd/optee_rpmb.c272
-rw-r--r--roms/u-boot/cmd/osd.c292
-rw-r--r--roms/u-boot/cmd/panic.c23
-rw-r--r--roms/u-boot/cmd/part.c249
-rw-r--r--roms/u-boot/cmd/pcap.c71
-rw-r--r--roms/u-boot/cmd/pci.c811
-rw-r--r--roms/u-boot/cmd/pinmux.c150
-rw-r--r--roms/u-boot/cmd/pmc.c83
-rw-r--r--roms/u-boot/cmd/pmic.c229
-rw-r--r--roms/u-boot/cmd/pstore.c545
-rw-r--r--roms/u-boot/cmd/pvblock.c30
-rw-r--r--roms/u-boot/cmd/pwm.c114
-rw-r--r--roms/u-boot/cmd/pxe.c255
-rw-r--r--roms/u-boot/cmd/pxe_utils.c1479
-rw-r--r--roms/u-boot/cmd/pxe_utils.h91
-rw-r--r--roms/u-boot/cmd/qfw.c191
-rw-r--r--roms/u-boot/cmd/read.c81
-rw-r--r--roms/u-boot/cmd/reginfo.c25
-rw-r--r--roms/u-boot/cmd/regulator.c466
-rw-r--r--roms/u-boot/cmd/reiser.c171
-rw-r--r--roms/u-boot/cmd/remoteproc.c283
-rw-r--r--roms/u-boot/cmd/riscv/Makefile4
-rw-r--r--roms/u-boot/cmd/riscv/exception.c54
-rw-r--r--roms/u-boot/cmd/riscv/sbi.c88
-rw-r--r--roms/u-boot/cmd/rng.c57
-rw-r--r--roms/u-boot/cmd/rockusb.c74
-rw-r--r--roms/u-boot/cmd/rtc.c167
-rw-r--r--roms/u-boot/cmd/sandbox/Makefile3
-rw-r--r--roms/u-boot/cmd/sandbox/exception.c41
-rw-r--r--roms/u-boot/cmd/sata.c127
-rw-r--r--roms/u-boot/cmd/sb.c67
-rw-r--r--roms/u-boot/cmd/scp03.c52
-rw-r--r--roms/u-boot/cmd/scsi.c74
-rw-r--r--roms/u-boot/cmd/setexpr.c518
-rw-r--r--roms/u-boot/cmd/sf.c627
-rw-r--r--roms/u-boot/cmd/sha1sum.c53
-rw-r--r--roms/u-boot/cmd/sleep.c57
-rw-r--r--roms/u-boot/cmd/smccc.c72
-rw-r--r--roms/u-boot/cmd/sound.c90
-rw-r--r--roms/u-boot/cmd/source.c208
-rw-r--r--roms/u-boot/cmd/spi.c174
-rw-r--r--roms/u-boot/cmd/spl.c190
-rw-r--r--roms/u-boot/cmd/sqfs.c42
-rw-r--r--roms/u-boot/cmd/stackprot_test.c26
-rw-r--r--roms/u-boot/cmd/strings.c46
-rw-r--r--roms/u-boot/cmd/sysboot.c138
-rw-r--r--roms/u-boot/cmd/terminal.c77
-rw-r--r--roms/u-boot/cmd/test.c217
-rw-r--r--roms/u-boot/cmd/thordown.c82
-rw-r--r--roms/u-boot/cmd/ti/Kconfig10
-rw-r--r--roms/u-boot/cmd/ti/Makefile8
-rw-r--r--roms/u-boot/cmd/ti/ddr3.c343
-rw-r--r--roms/u-boot/cmd/time.c45
-rw-r--r--roms/u-boot/cmd/timer.c34
-rw-r--r--roms/u-boot/cmd/tlv_eeprom.c1108
-rw-r--r--roms/u-boot/cmd/tpm-common.c387
-rw-r--r--roms/u-boot/cmd/tpm-user-utils.h26
-rw-r--r--roms/u-boot/cmd/tpm-v1.c829
-rw-r--r--roms/u-boot/cmd/tpm-v2.c446
-rw-r--r--roms/u-boot/cmd/tpm_test.c571
-rw-r--r--roms/u-boot/cmd/trace.c119
-rw-r--r--roms/u-boot/cmd/tsi148.c472
-rw-r--r--roms/u-boot/cmd/ubi.c744
-rw-r--r--roms/u-boot/cmd/ubifs.c172
-rw-r--r--roms/u-boot/cmd/ufs.c37
-rw-r--r--roms/u-boot/cmd/universe.c367
-rw-r--r--roms/u-boot/cmd/unlz4.c46
-rw-r--r--roms/u-boot/cmd/unzip.c91
-rw-r--r--roms/u-boot/cmd/usb.c758
-rw-r--r--roms/u-boot/cmd/usb_gadget_sdp.c55
-rw-r--r--roms/u-boot/cmd/usb_mass_storage.c251
-rw-r--r--roms/u-boot/cmd/version.c39
-rw-r--r--roms/u-boot/cmd/virtio.c40
-rw-r--r--roms/u-boot/cmd/w1.c127
-rw-r--r--roms/u-boot/cmd/wdt.c174
-rw-r--r--roms/u-boot/cmd/wol.c33
-rw-r--r--roms/u-boot/cmd/x86/Makefile7
-rw-r--r--roms/u-boot/cmd/x86/cbsysinfo.c394
-rw-r--r--roms/u-boot/cmd/x86/exception.c29
-rw-r--r--roms/u-boot/cmd/x86/fsp.c110
-rw-r--r--roms/u-boot/cmd/x86/hob.c165
-rw-r--r--roms/u-boot/cmd/x86/mtrr.c191
-rw-r--r--roms/u-boot/cmd/ximg.c279
-rw-r--r--roms/u-boot/cmd/yaffs2.c326
-rw-r--r--roms/u-boot/cmd/zfs.c171
-rw-r--r--roms/u-boot/cmd/zip.c43
209 files changed, 57768 insertions, 0 deletions
diff --git a/roms/u-boot/cmd/.gitignore b/roms/u-boot/cmd/.gitignore
new file mode 100644
index 000000000..bab889fd3
--- /dev/null
+++ b/roms/u-boot/cmd/.gitignore
@@ -0,0 +1,6 @@
+config_data.gz
+config_data_gz.h
+config_data_size.h
+license_data.gz
+license_data_gz.h
+license_data_size.h
diff --git a/roms/u-boot/cmd/Kconfig b/roms/u-boot/cmd/Kconfig
new file mode 100644
index 000000000..a9fb4eead
--- /dev/null
+++ b/roms/u-boot/cmd/Kconfig
@@ -0,0 +1,2383 @@
+menu "Command line interface"
+
+config CMDLINE
+ bool "Support U-Boot commands"
+ default y
+ help
+ Enable U-Boot's command-line functions. This provides a means
+ to enter commands into U-Boot for a wide variety of purposes. It
+ also allows scripts (containing commands) to be executed.
+ Various commands and command categorys can be indivdually enabled.
+ Depending on the number of commands enabled, this can add
+ substantially to the size of U-Boot.
+
+config HUSH_PARSER
+ bool "Use hush shell"
+ depends on CMDLINE
+ help
+ This option enables the "hush" shell (from Busybox) as command line
+ interpreter, thus enabling powerful command line syntax like
+ if...then...else...fi conditionals or `&&' and '||'
+ constructs ("shell scripts").
+
+ If disabled, you get the old, much simpler behaviour with a somewhat
+ smaller memory footprint.
+
+config CMDLINE_EDITING
+ bool "Enable command line editing"
+ depends on CMDLINE
+ default y
+ help
+ Enable editing and History functions for interactive command line
+ input operations
+
+config AUTO_COMPLETE
+ bool "Enable auto complete using TAB"
+ depends on CMDLINE
+ default y
+ help
+ Enable auto completion of commands using TAB.
+
+config SYS_LONGHELP
+ bool "Enable long help messages"
+ depends on CMDLINE
+ default y if CMDLINE
+ help
+ Defined when you want long help messages included
+ Do not set this option when short of memory.
+
+config SYS_PROMPT
+ string "Shell prompt"
+ default "Zynq> " if ARCH_ZYNQ
+ default "ZynqMP> " if ARCH_ZYNQMP
+ default "=> "
+ help
+ This string is displayed in the command line to the left of the
+ cursor.
+
+config SYS_PROMPT_HUSH_PS2
+ string "Hush shell secondary prompt"
+ depends on HUSH_PARSER
+ default "> "
+ help
+ This defines the secondary prompt string, which is
+ printed when the command interpreter needs more input
+ to complete a command. Usually "> ".
+
+config SYS_XTRACE
+ bool "Command execution tracer"
+ depends on CMDLINE
+ default y if CMDLINE
+ help
+ This option enables the possiblity to print all commands before
+ executing them and after all variables are evaluated (similar
+ to Bash's xtrace/'set -x' feature).
+ To enable the tracer a variable "xtrace" needs to be defined in
+ the environment.
+
+config BUILD_BIN2C
+ bool
+
+comment "Commands"
+
+menu "Info commands"
+
+config CMD_ACPI
+ bool "acpi"
+ depends on ACPIGEN
+ default y
+ help
+ List and dump ACPI tables. ACPI (Advanced Configuration and Power
+ Interface) is used mostly on x86 for providing information to the
+ Operating System about devices in the system. The tables are set up
+ by the firmware, typically U-Boot but possibly an earlier firmware
+ module, if U-Boot is chain-loaded from something else. ACPI tables
+ can also include code, to perform hardware-specific tasks required
+ by the Operating Systems. This allows some amount of separation
+ between the firmware and OS, and is particularly useful when you
+ want to make hardware changes without the OS needing to be adjusted.
+
+config CMD_ADDRMAP
+ bool "addrmap"
+ depends on ADDR_MAP
+ default y
+ help
+ List non-identity virtual-physical memory mappings for 32-bit CPUs.
+
+config CMD_BDI
+ bool "bdinfo"
+ default y
+ help
+ Print board info
+
+config CMD_CONFIG
+ bool "config"
+ default SANDBOX
+ select BUILD_BIN2C
+ help
+ Print ".config" contents.
+
+ If this option is enabled, the ".config" file contents are embedded
+ in the U-Boot image and can be printed on the console by the "config"
+ command. This provides information of which options are enabled on
+ the running U-Boot.
+
+config CMD_CONSOLE
+ bool "coninfo"
+ default y
+ help
+ Print console devices and information.
+
+config CMD_CPU
+ bool "cpu"
+ depends on CPU
+ help
+ Print information about available CPUs. This normally shows the
+ number of CPUs, type (e.g. manufacturer, architecture, product or
+ internal name) and clock frequency. Other information may be
+ available depending on the CPU driver.
+
+config CMD_LICENSE
+ bool "license"
+ select BUILD_BIN2C
+ help
+ Print GPL license text
+
+config CMD_PMC
+ bool "pmc"
+ help
+ Provides access to the Intel Power-Management Controller (PMC) so
+ that its state can be examined. This does not currently support
+ changing the state but it is still useful for debugging and seeing
+ what is going on.
+
+config CMD_REGINFO
+ bool "reginfo"
+ depends on PPC
+ help
+ Register dump
+
+config CMD_TLV_EEPROM
+ bool "tlv_eeprom"
+ depends on I2C_EEPROM
+ help
+ Display and program the system EEPROM data block in ONIE Tlvinfo
+ format. TLV stands for Type-Length-Value.
+
+config SPL_CMD_TLV_EEPROM
+ bool "tlv_eeprom for SPL"
+ depends on SPL_I2C_EEPROM
+ select SPL_DRIVERS_MISC_SUPPORT
+ help
+ Read system EEPROM data block in ONIE Tlvinfo format from SPL.
+
+config CMD_SBI
+ bool "sbi"
+ depends on RISCV_SMODE && SBI_V02
+ help
+ Display information about the SBI implementation.
+
+endmenu
+
+menu "Boot commands"
+
+config CMD_BOOTD
+ bool "bootd"
+ default y
+ help
+ Run the command stored in the environment "bootcmd", i.e.
+ "bootd" does the same thing as "run bootcmd".
+
+config CMD_BOOTM
+ bool "bootm"
+ default y
+ help
+ Boot an application image from the memory.
+
+config BOOTM_EFI
+ bool "Support booting UEFI FIT images"
+ depends on CMD_BOOTEFI && CMD_BOOTM && FIT
+ default y
+ help
+ Support booting UEFI FIT images via the bootm command.
+
+config CMD_BOOTZ
+ bool "bootz"
+ help
+ Boot the Linux zImage
+
+config CMD_BOOTI
+ bool "booti"
+ depends on ARM64 || RISCV
+ default y
+ help
+ Boot an AArch64 Linux Kernel image from memory.
+
+config BOOTM_LINUX
+ bool "Support booting Linux OS images"
+ depends on CMD_BOOTM || CMD_BOOTZ || CMD_BOOTI
+ default y
+ help
+ Support booting the Linux kernel directly via a command such as bootm
+ or booti or bootz.
+
+config BOOTM_NETBSD
+ bool "Support booting NetBSD (non-EFI) loader images"
+ depends on CMD_BOOTM
+ default y
+ help
+ Support booting NetBSD via the bootm command.
+
+config BOOTM_OPENRTOS
+ bool "Support booting OPENRTOS / FreeRTOS images"
+ depends on CMD_BOOTM
+ help
+ Support booting OPENRTOS / FreeRTOS via the bootm command.
+
+config BOOTM_OSE
+ bool "Support booting Enea OSE images"
+ depends on (ARM && (ARM64 || CPU_V7A || CPU_V7R) || SANDBOX || PPC || X86)
+ depends on CMD_BOOTM
+ help
+ Support booting Enea OSE images via the bootm command.
+
+config BOOTM_PLAN9
+ bool "Support booting Plan9 OS images"
+ depends on CMD_BOOTM
+ default y
+ help
+ Support booting Plan9 images via the bootm command.
+
+config BOOTM_RTEMS
+ bool "Support booting RTEMS OS images"
+ depends on CMD_BOOTM
+ default y
+ help
+ Support booting RTEMS images via the bootm command.
+
+config BOOTM_VXWORKS
+ bool "Support booting VxWorks OS images"
+ depends on CMD_BOOTM
+ default y
+ help
+ Support booting VxWorks images via the bootm command.
+
+config CMD_BOOTEFI
+ bool "bootefi"
+ depends on EFI_LOADER
+ default y
+ help
+ Boot an EFI image from memory.
+
+config CMD_BOOTEFI_HELLO_COMPILE
+ bool "Compile a standard EFI hello world binary for testing"
+ depends on CMD_BOOTEFI && !CPU_V7M
+ default y
+ help
+ This compiles a standard EFI hello world application with U-Boot so
+ that it can be used with the test/py testing framework. This is useful
+ for testing that EFI is working at a basic level, and for bringing
+ up EFI support on a new architecture.
+
+ No additional space will be required in the resulting U-Boot binary
+ when this option is enabled.
+
+config CMD_BOOTEFI_HELLO
+ bool "Allow booting a standard EFI hello world for testing"
+ depends on CMD_BOOTEFI_HELLO_COMPILE
+ default y if CMD_BOOTEFI_SELFTEST
+ help
+ This adds a standard EFI hello world application to U-Boot so that
+ it can be used with the 'bootefi hello' command. This is useful
+ for testing that EFI is working at a basic level, and for bringing
+ up EFI support on a new architecture.
+
+source lib/efi_selftest/Kconfig
+
+config CMD_BOOTMENU
+ bool "bootmenu"
+ select MENU
+ help
+ Add an ANSI terminal boot menu command.
+
+config CMD_ADTIMG
+ bool "adtimg"
+ help
+ Android DTB/DTBO image manipulation commands. Read dtb/dtbo files from
+ image into RAM, dump image structure information, etc. Those dtb/dtbo
+ files should be merged in one dtb further, which needs to be passed to
+ the kernel, as part of a boot process.
+
+config CMD_ABOOTIMG
+ bool "abootimg"
+ depends on ANDROID_BOOT_IMAGE
+ help
+ Android Boot Image manipulation commands. Allows one to extract
+ images contained in boot.img, like kernel, ramdisk, dtb, etc, and
+ obtain corresponding meta-information from boot.img.
+
+ See doc/android/boot-image.rst for details.
+
+config CMD_ELF
+ bool "bootelf, bootvx"
+ default y
+ select LIB_ELF
+ help
+ Boot an ELF/vxWorks image from the memory.
+
+config CMD_FDT
+ bool "Flattened Device Tree utility commands"
+ default y
+ depends on OF_LIBFDT
+ help
+ Do FDT related setup before booting into the Operating System.
+
+config SUPPORT_EXTENSION_SCAN
+ bool
+
+config CMD_EXTENSION
+ bool "Extension board management command"
+ select CMD_FDT
+ depends on SUPPORT_EXTENSION_SCAN
+ help
+ Enables the "extension" command, which allows to detect
+ extension boards connected to the system, and apply
+ corresponding Device Tree overlays.
+
+config CMD_GO
+ bool "go"
+ default y
+ help
+ Start an application at a given address.
+
+config CMD_RUN
+ bool "run"
+ default y
+ help
+ Run the command in the given environment variable.
+
+config CMD_IMI
+ bool "iminfo"
+ default y
+ help
+ Print header information for application image.
+
+config CMD_IMLS
+ bool "imls"
+ help
+ List all images found in flash
+
+config CMD_XIMG
+ bool "imxtract"
+ default y
+ help
+ Extract a part of a multi-image.
+
+config CMD_SPL
+ bool "spl export - Export boot information for Falcon boot"
+ depends on SPL
+ help
+ Falcon mode allows booting directly from SPL into an Operating
+ System such as Linux, thus skipping U-Boot proper. See
+ doc/README.falcon for full information about how to use this
+ command.
+
+config CMD_SPL_NAND_OFS
+ hex "Offset of OS args or dtb for Falcon-mode NAND boot"
+ depends on CMD_SPL && (TPL_NAND_SUPPORT || SPL_NAND_SUPPORT)
+ default 0
+ help
+ This provides the offset of the command line arguments for Linux
+ when booting from NAND in Falcon mode. See doc/README.falcon
+ for full information about how to use this option (and also see
+ board/gateworks/gw_ventana/README for an example).
+
+config CMD_SPL_NOR_OFS
+ hex "Offset of OS args or dtb for Falcon-mode NOR boot"
+ depends on CMD_SPL && SPL_NOR_SUPPORT
+ default 0
+ help
+ This provides the offset of the command line arguments or dtb for
+ Linux when booting from NOR in Falcon mode.
+
+config CMD_SPL_WRITE_SIZE
+ hex "Size of argument area"
+ depends on CMD_SPL
+ default 0x2000
+ help
+ This provides the size of the command-line argument area in NAND
+ flash used by Falcon-mode boot. See the documentation until CMD_SPL
+ for detail.
+
+config CMD_THOR_DOWNLOAD
+ bool "thor - TIZEN 'thor' download"
+ select DFU
+ help
+ Implements the 'thor' download protocol. This is a way of
+ downloading a software update over USB from an attached host.
+ There is no documentation about this within the U-Boot source code
+ but you should be able to find something on the interwebs.
+
+config CMD_ZBOOT
+ bool "zboot - x86 boot command"
+ help
+ With x86 machines it is common to boot a bzImage file which
+ contains both a kernel and a setup.bin file. The latter includes
+ configuration information from the dark ages which x86 boards still
+ need to pick things out of.
+
+ Consider using FIT in preference to this since it supports directly
+ booting both 32- and 64-bit kernels, as well as secure boot.
+ Documentation is available in doc/uImage.FIT/x86-fit-boot.txt
+
+endmenu
+
+menu "Environment commands"
+
+config CMD_ASKENV
+ bool "ask for env variable"
+ help
+ Ask for environment variable
+
+config CMD_EXPORTENV
+ bool "env export"
+ default y
+ help
+ Export environments.
+
+config CMD_IMPORTENV
+ bool "env import"
+ default y
+ help
+ Import environments.
+
+config CMD_EDITENV
+ bool "editenv"
+ default y
+ help
+ Edit environment variable.
+
+config CMD_GREPENV
+ bool "search env"
+ help
+ Allow for searching environment variables
+
+config CMD_SAVEENV
+ bool "saveenv"
+ default y
+ help
+ Save all environment variables into the compiled-in persistent
+ storage.
+
+config CMD_ERASEENV
+ bool "eraseenv"
+ default n
+ depends on CMD_SAVEENV
+ help
+ Erase environment variables from the compiled-in persistent
+ storage.
+
+config CMD_ENV_EXISTS
+ bool "env exists"
+ default y
+ help
+ Check if a variable is defined in the environment for use in
+ shell scripting.
+
+config CMD_ENV_CALLBACK
+ bool "env callbacks - print callbacks and their associated variables"
+ help
+ Some environment variable have callbacks defined by
+ U_BOOT_ENV_CALLBACK. These are called when the variable changes.
+ For example changing "baudrate" adjust the serial baud rate. This
+ command lists the currently defined callbacks.
+
+config CMD_ENV_FLAGS
+ bool "env flags -print variables that have non-default flags"
+ help
+ Some environment variables have special flags that control their
+ behaviour. For example, serial# can only be written once and cannot
+ be deleted. This command shows the variables that have special
+ flags.
+
+config CMD_NVEDIT_EFI
+ bool "env [set|print] -e - set/print UEFI variables"
+ depends on EFI_LOADER
+ imply HEXDUMP
+ help
+ UEFI variables are encoded as some form of U-Boot variables.
+ If enabled, we are allowed to set/print UEFI variables using
+ "env" command with "-e" option without knowing details.
+
+config CMD_NVEDIT_INFO
+ bool "env info - print or evaluate environment information"
+ help
+ Print environment information:
+ - env_valid : is environment valid
+ - env_ready : is environment imported into hash table
+ - env_use_default : is default environment used
+
+ This command can be optionally used for evaluation in scripts:
+ [-d] : evaluate whether default environment is used
+ [-p] : evaluate whether environment can be persisted
+ [-q] : quiet output
+ The result of multiple evaluations will be combined with AND.
+
+config CMD_NVEDIT_LOAD
+ bool "env load"
+ help
+ Load all environment variables from the compiled-in persistent
+ storage.
+
+config CMD_NVEDIT_SELECT
+ bool "env select"
+ help
+ Select the compiled-in persistent storage of environment variables.
+
+endmenu
+
+menu "Memory commands"
+
+config CMD_BINOP
+ bool "binop"
+ help
+ Compute binary operations (xor, or, and) of byte arrays of arbitrary
+ size from memory and store the result in memory or the environment.
+
+config CMD_BLOBLIST
+ bool "bloblist"
+ default y if BLOBLIST
+ help
+ Show information about the bloblist, a collection of binary blobs
+ held in memory that persist between SPL and U-Boot. In the case of
+ x86 devices the bloblist can be used to hold ACPI tables so that they
+ remain available in memory.
+
+config CMD_CRC32
+ bool "crc32"
+ default y
+ select HASH
+ help
+ Compute CRC32.
+
+config CRC32_VERIFY
+ bool "crc32 -v"
+ depends on CMD_CRC32
+ help
+ Add -v option to verify data against a crc32 checksum.
+
+config CMD_EEPROM
+ bool "eeprom - EEPROM subsystem"
+ help
+ (deprecated, needs conversion to driver model)
+ Provides commands to read and write EEPROM (Electrically Erasable
+ Programmable Read Only Memory) chips that are connected over an
+ I2C bus.
+
+config CMD_EEPROM_LAYOUT
+ bool "Enable layout-aware eeprom commands"
+ depends on CMD_EEPROM
+ help
+ (deprecated, needs conversion to driver model)
+ When enabled, additional eeprom sub-commands become available.
+
+ eeprom print - prints the contents of the eeprom in a human-readable
+ way (eeprom layout fields, and data formatted to be fit for human
+ consumption).
+
+ eeprom update - allows user to update eeprom fields by specifying
+ the field name, and providing the new data in a human readable format
+ (same format as displayed by the eeprom print command).
+
+ Both commands can either auto detect the layout, or be told which
+ layout to use.
+
+ Feature API:
+ __weak int parse_layout_version(char *str)
+ - override to provide your own layout name parsing
+ __weak void __eeprom_layout_assign(struct eeprom_layout *layout,
+ int layout_version);
+ - override to setup the layout metadata based on the version
+ __weak int eeprom_layout_detect(unsigned char *data)
+ - override to provide your own algorithm for detecting layout
+ version
+ eeprom_field.c
+ - contains various printing and updating functions for common
+ types of eeprom fields. Can be used for defining
+ custom layouts.
+
+config EEPROM_LAYOUT_HELP_STRING
+ string "Tells user what layout names are supported"
+ depends on CMD_EEPROM_LAYOUT
+ default "<not defined>"
+ help
+ Help printed with the LAYOUT VERSIONS part of the 'eeprom'
+ command's help.
+
+config LOOPW
+ bool "loopw"
+ help
+ Infinite write loop on address range
+
+config CMD_MD5SUM
+ bool "md5sum"
+ default n
+ select MD5
+ help
+ Compute MD5 checksum.
+
+config MD5SUM_VERIFY
+ bool "md5sum -v"
+ default n
+ depends on CMD_MD5SUM
+ help
+ Add -v option to verify data against an MD5 checksum.
+
+config CMD_MEMINFO
+ bool "meminfo"
+ help
+ Display memory information.
+
+config CMD_MEMORY
+ bool "md, mm, nm, mw, cp, cmp, base, loop"
+ default y
+ help
+ Memory commands.
+ md - memory display
+ mm - memory modify (auto-incrementing address)
+ nm - memory modify (constant address)
+ mw - memory write (fill)
+ cp - memory copy
+ cmp - memory compare
+ base - print or set address offset
+ loop - initialize loop on address range
+
+config CMD_MEM_SEARCH
+ bool "ms - Memory search"
+ help
+ Memory-search command
+
+ This allows searching through a region of memory looking for hex
+ data (byte, 16-bit word, 32-bit long, also 64-bit on machines that
+ support it). It is also possible to search for a string. The
+ command accepts a memory range and a list of values to search for.
+ The values need to appear in memory in the same order they are given
+ in the command. At most 10 matches can be returned at a time, but
+ pressing return will show the next 10 matches. Environment variables
+ are set for use with scripting (memmatches, memaddr, mempos).
+
+config CMD_MX_CYCLIC
+ bool "Enable cyclic md/mw commands"
+ depends on CMD_MEMORY
+ help
+ Add the "mdc" and "mwc" memory commands. These are cyclic
+ "md/mw" commands.
+ Examples:
+
+ => mdc.b 10 4 500
+ This command will print 4 bytes (10,11,12,13) each 500 ms.
+
+ => mwc.l 100 12345678 10
+ This command will write 12345678 to address 100 all 10 ms.
+
+config CMD_RANDOM
+ bool "random"
+ default y
+ depends on CMD_MEMORY && (LIB_RAND || LIB_HW_RAND)
+ help
+ random - fill memory with random data
+
+config CMD_MEMTEST
+ bool "memtest"
+ help
+ Simple RAM read/write test.
+
+if CMD_MEMTEST
+
+config SYS_ALT_MEMTEST
+ bool "Alternative test"
+ help
+ Use a more complete alternative memory test.
+
+if SYS_ALT_MEMTEST
+
+config SYS_ALT_MEMTEST_BITFLIP
+ bool "Bitflip test"
+ default y
+ help
+ The alternative memory test includes bitflip test since 2020.07.
+ The bitflip test significantly increases the overall test time.
+ Bitflip test can optionally be disabled here.
+
+endif
+
+config SYS_MEMTEST_START
+ hex "default start address for mtest"
+ default 0
+ help
+ This is the default start address for mtest for simple read/write
+ test. If no arguments are given to mtest, default address is used
+ as start address.
+
+config SYS_MEMTEST_END
+ hex "default end address for mtest"
+ default 0x1000
+ help
+ This is the default end address for mtest for simple read/write
+ test. If no arguments are given to mtest, default address is used
+ as end address.
+
+endif
+
+config CMD_SHA1SUM
+ bool "sha1sum"
+ select SHA1
+ help
+ Compute SHA1 checksum.
+
+config SHA1SUM_VERIFY
+ bool "sha1sum -v"
+ depends on CMD_SHA1SUM
+ help
+ Add -v option to verify data against a SHA1 checksum.
+
+config CMD_STRINGS
+ bool "strings - display strings in memory"
+ help
+ This works similarly to the Unix 'strings' command except that it
+ works with a memory range. String of printable characters found
+ within the range are displayed. The minimum number of characters
+ for a sequence to be considered a string can be provided.
+
+endmenu
+
+menu "Compression commands"
+
+config CMD_LZMADEC
+ bool "lzmadec"
+ default y if CMD_BOOTI
+ select LZMA
+ help
+ Support decompressing an LZMA (Lempel-Ziv-Markov chain algorithm)
+ image from memory.
+
+config CMD_UNLZ4
+ bool "unlz4"
+ default y if CMD_BOOTI
+ select LZ4
+ help
+ Support decompressing an LZ4 image from memory region.
+
+config CMD_UNZIP
+ bool "unzip"
+ default y if CMD_BOOTI
+ select GZIP
+ help
+ Uncompress a zip-compressed memory region.
+
+config CMD_ZIP
+ bool "zip"
+ select GZIP_COMPRESSED
+ help
+ Compress a memory region with zlib deflate method.
+
+endmenu
+
+menu "Device access commands"
+
+config CMD_ARMFLASH
+ #depends on FLASH_CFI_DRIVER
+ bool "armflash"
+ help
+ ARM Ltd reference designs flash partition access
+
+config CMD_ADC
+ bool "adc - Access Analog to Digital Converters info and data"
+ select ADC
+ depends on DM_REGULATOR
+ help
+ Shows ADC device info and permit printing one-shot analog converted
+ data from a named Analog to Digital Converter.
+
+config CMD_BCB
+ bool "bcb"
+ depends on MMC
+ depends on PARTITIONS
+ help
+ Read/modify/write the fields of Bootloader Control Block, usually
+ stored on the flash "misc" partition with its structure defined in:
+ https://android.googlesource.com/platform/bootable/recovery/+/master/
+ bootloader_message/include/bootloader_message/bootloader_message.h
+
+ Some real-life use-cases include (but are not limited to):
+ - Determine the "boot reason" (and act accordingly):
+ https://source.android.com/devices/bootloader/boot-reason
+ - Get/pass a list of commands from/to recovery:
+ https://android.googlesource.com/platform/bootable/recovery
+ - Inspect/dump the contents of the BCB fields
+
+config CMD_BIND
+ bool "bind/unbind - Bind or unbind a device to/from a driver"
+ depends on DM
+ help
+ Bind or unbind a device to/from a driver from the command line.
+ This is useful in situations where a device may be handled by several
+ drivers. For example, this can be used to bind a UDC to the usb ether
+ gadget driver from the command line.
+
+config CMD_CLK
+ bool "clk - Show clock frequencies"
+ help
+ (deprecated)
+ Shows clock frequences by calling a sock_clk_dump() hook function.
+ This is depreated in favour of using the CLK uclass and accessing
+ clock values from associated drivers. However currently no command
+ exists for this.
+
+config CMD_DEMO
+ bool "demo - Demonstration commands for driver model"
+ depends on DM
+ help
+ Provides a 'demo' command which can be used to play around with
+ driver model. To use this properly you will need to enable one or
+ both of the demo devices (DM_DEMO_SHAPE and DM_DEMO_SIMPLE).
+ Otherwise you will always get an empty list of devices. The demo
+ devices are defined in the sandbox device tree, so the easiest
+ option is to use sandbox and pass the -d point to sandbox's
+ u-boot.dtb file.
+
+config CMD_DFU
+ bool "dfu"
+ select DFU
+ help
+ Enables the command "dfu" which is used to have U-Boot create a DFU
+ class device via USB. This command requires that the "dfu_alt_info"
+ environment variable be set and define the alt settings to expose to
+ the host.
+
+config CMD_DM
+ bool "dm - Access to driver model information"
+ depends on DM
+ help
+ Provides access to driver model data structures and information,
+ such as a list of devices, list of uclasses and the state of each
+ device (e.g. activated). This is not required for operation, but
+ can be useful to see the state of driver model for debugging or
+ interest.
+
+config CMD_FASTBOOT
+ bool "fastboot - Android fastboot support"
+ depends on FASTBOOT
+ help
+ This enables the command "fastboot" which enables the Android
+ fastboot mode for the platform. Fastboot is a protocol for
+ downloading images, flashing and device control used on
+ Android devices. Fastboot requires either the network stack
+ enabled or support for acting as a USB device.
+
+ See doc/android/fastboot.rst for more information.
+
+config CMD_FLASH
+ bool "flinfo, erase, protect"
+ default y
+ depends on MTD || FLASH_CFI_DRIVER || MTD_NOR_FLASH
+ help
+ NOR flash support.
+ flinfo - print FLASH memory information
+ erase - FLASH memory
+ protect - enable or disable FLASH write protection
+
+config CMD_FPGA
+ bool "fpga"
+ depends on FPGA
+ default y
+ help
+ FPGA support.
+
+config CMD_FPGA_LOADBP
+ bool "fpga loadbp - load partial bitstream (Xilinx only)"
+ depends on CMD_FPGA
+ help
+ Supports loading an FPGA device from a bitstream buffer containing
+ a partial bitstream.
+
+config CMD_FPGA_LOADFS
+ bool "fpga loadfs - load bitstream from FAT filesystem (Xilinx only)"
+ depends on CMD_FPGA
+ help
+ Supports loading an FPGA device from a FAT filesystem.
+
+config CMD_FPGA_LOADMK
+ bool "fpga loadmk - load bitstream from image"
+ depends on CMD_FPGA
+ help
+ Supports loading an FPGA device from a image generated by mkimage.
+
+config CMD_FPGA_LOADP
+ bool "fpga loadp - load partial bitstream"
+ depends on CMD_FPGA
+ help
+ Supports loading an FPGA device from a bitstream buffer containing
+ a partial bitstream.
+
+config CMD_FPGA_LOAD_SECURE
+ bool "fpga loads - loads secure bitstreams (Xilinx only)"
+ depends on CMD_FPGA
+ help
+ Enables the fpga loads command which is used to load secure
+ (authenticated or encrypted or both) bitstreams on to FPGA.
+
+config CMD_FPGAD
+ bool "fpgad - dump FPGA registers"
+ help
+ (legacy, needs conversion to driver model)
+ Provides a way to dump FPGA registers by calling the board-specific
+ fpga_get_reg() function. This functions similarly to the 'md'
+ command.
+
+config CMD_FUSE
+ bool "fuse - support for the fuse subssystem"
+ help
+ (deprecated - needs conversion to driver model)
+ This allows reading, sensing, programming or overriding fuses
+ which control the behaviour of the device. The command uses the
+ fuse_...() API.
+
+config CMD_GPIO
+ bool "gpio"
+ help
+ GPIO support.
+
+config CMD_PWM
+ bool "pwm"
+ depends on DM_PWM
+ help
+ Control PWM channels, this allows invert/config/enable/disable PWM channels.
+
+config CMD_GPT
+ bool "GPT (GUID Partition Table) command"
+ select EFI_PARTITION
+ select HAVE_BLOCK_DEVICE
+ select PARTITION_UUIDS
+ imply RANDOM_UUID
+ help
+ Enable the 'gpt' command to ready and write GPT style partition
+ tables.
+
+config RANDOM_UUID
+ bool "GPT Random UUID generation"
+ select LIB_UUID
+ help
+ Enable the generation of partitions with random UUIDs if none
+ are provided.
+
+config CMD_GPT_RENAME
+ bool "GPT partition renaming commands"
+ depends on CMD_GPT
+ help
+ Enables the 'gpt' command to interchange names on two GPT
+ partitions via the 'gpt swap' command or to rename single
+ partitions via the 'rename' command.
+
+config CMD_IDE
+ bool "ide - Support for IDE drivers"
+ select IDE
+ help
+ Provides an 'ide' command which allows accessing the IDE drive,
+ reseting the IDE interface, printing the partition table and
+ geting device info. It also enables the 'diskboot' command which
+ permits booting from an IDE drive.
+
+config CMD_IO
+ bool "io - Support for performing I/O accesses"
+ help
+ Provides an 'iod' command to display I/O space and an 'iow' command
+ to write values to the I/O space. This can be useful for manually
+ checking the state of devices during boot when debugging device
+ drivers, etc.
+
+config CMD_IOTRACE
+ bool "iotrace - Support for tracing I/O activity"
+ help
+ Provides an 'iotrace' command which supports recording I/O reads and
+ writes in a trace buffer in memory . It also maintains a checksum
+ of the trace records (even if space is exhausted) so that the
+ sequence of I/O accesses can be verified.
+
+ When debugging drivers it is useful to see what I/O accesses were
+ done and in what order.
+
+ Even if the individual accesses are of little interest it can be
+ useful to verify that the access pattern is consistent each time
+ an operation is performed. In this case a checksum can be used to
+ characterise the operation of a driver. The checksum can be compared
+ across different runs of the operation to verify that the driver is
+ working properly.
+
+ In particular, when performing major refactoring of the driver, where
+ the access pattern should not change, the checksum provides assurance
+ that the refactoring work has not broken the driver.
+
+ This works by sneaking into the io.h heder for an architecture and
+ redirecting I/O accesses through iotrace's tracing mechanism.
+
+ For now no commands are provided to examine the trace buffer. The
+ format is fairly simple, so 'md' is a reasonable substitute.
+
+ Note: The checksum feature is only useful for I/O regions where the
+ contents do not change outside of software control. Where this is not
+ suitable you can fall back to manually comparing the addresses. It
+ might be useful to enhance tracing to only checksum the accesses and
+ not the data read/written.
+
+config CMD_I2C
+ bool "i2c"
+ help
+ I2C support.
+
+config CMD_W1
+ depends on W1
+ default y if W1
+ bool "w1 - Support for Dallas 1-Wire protocol"
+ help
+ Dallas 1-wire protocol support
+
+config CMD_LOADB
+ bool "loadb"
+ default y
+ help
+ Load a binary file over serial line.
+
+config CMD_LOADS
+ bool "loads"
+ default y
+ help
+ Load an S-Record file over serial line
+
+config CMD_LSBLK
+ depends on BLK
+ bool "lsblk - list block drivers and devices"
+ help
+ Print list of available block device drivers, and for each, the list
+ of known block devices.
+
+config CMD_MBR
+ bool "MBR (Master Boot Record) command"
+ select DOS_PARTITION
+ select HAVE_BLOCK_DEVICE
+ help
+ Enable the 'mbr' command to ready and write MBR (Master Boot Record)
+ style partition tables.
+
+config CMD_MISC
+ bool "misc"
+ depends on MISC
+ help
+ Enable the command "misc" for accessing miscellaneous devices with
+ a MISC uclass driver. The command provides listing all MISC devices
+ as well as read and write functionalities via their drivers.
+
+config CMD_MMC
+ bool "mmc"
+ depends on MMC
+ help
+ MMC memory mapped support.
+
+if CMD_MMC
+
+config CMD_BKOPS_ENABLE
+ bool "mmc bkops enable"
+ depends on CMD_MMC
+ default n
+ help
+ Enable command for setting manual background operations handshake
+ on a eMMC device. The feature is optionally available on eMMC devices
+ conforming to standard >= 4.41.
+
+config CMD_MMC_RPMB
+ bool "Enable support for RPMB in the mmc command"
+ depends on SUPPORT_EMMC_RPMB
+ help
+ Enable the commands for reading, writing and programming the
+ key for the Replay Protection Memory Block partition in eMMC.
+
+config CMD_MMC_SWRITE
+ bool "mmc swrite"
+ depends on MMC_WRITE
+ select IMAGE_SPARSE
+ help
+ Enable support for the "mmc swrite" command to write Android sparse
+ images to eMMC.
+
+endif
+
+config CMD_CLONE
+ bool "clone"
+ depends on BLK
+ help
+ Enable storage cloning over block devices, useful for
+ initial flashing by external block device without network
+ or usb support.
+
+config CMD_OPTEE_RPMB
+ bool "Enable read/write support on RPMB via OPTEE"
+ depends on SUPPORT_EMMC_RPMB && OPTEE
+ help
+ Enable the commands for reading, writing persistent named values
+ in the Replay Protection Memory Block partition in eMMC by
+ using Persistent Objects in OPTEE
+
+config CMD_MTD
+ bool "mtd"
+ depends on MTD
+ select MTD_PARTITIONS
+ help
+ MTD commands support.
+
+config CMD_MUX
+ bool "mux"
+ depends on MULTIPLEXER
+ help
+ List, select, and deselect mux controllers on the fly.
+
+config CMD_NAND
+ bool "nand"
+ default y if NAND_SUNXI
+ depends on MTD_RAW_NAND
+ help
+ NAND support.
+
+if CMD_NAND
+config CMD_NAND_TRIMFFS
+ bool "nand write.trimffs"
+ default y if ARCH_SUNXI
+ help
+ Allows one to skip empty pages when flashing something on a NAND.
+
+config CMD_NAND_LOCK_UNLOCK
+ bool "nand lock/unlock"
+ help
+ NAND locking support.
+
+config CMD_NAND_TORTURE
+ bool "nand torture"
+ help
+ NAND torture support.
+
+endif # CMD_NAND
+
+config CMD_NVME
+ bool "nvme"
+ depends on NVME
+ default y if NVME
+ help
+ NVM Express device support
+
+config CMD_ONENAND
+ bool "onenand - access to onenand device"
+ depends on MTD
+ help
+ OneNAND is a brand of NAND ('Not AND' gate) flash which provides
+ various useful features. This command allows reading, writing,
+ and erasing blocks. It allso provides a way to show and change
+ bad blocks, and test the device.
+
+config CMD_OSD
+ bool "osd"
+ help
+ Enable the 'osd' command which allows to query information from and
+ write text data to a on-screen display (OSD) device; a virtual device
+ associated with a display capable of displaying a text overlay on the
+ display it's associated with..
+
+config CMD_PART
+ bool "part"
+ select HAVE_BLOCK_DEVICE
+ select PARTITION_UUIDS
+ help
+ Read and display information about the partition table on
+ various media.
+
+config CMD_PCI
+ bool "pci - Access PCI devices"
+ help
+ Provide access to PCI (Peripheral Interconnect Bus), a type of bus
+ used on some devices to allow the CPU to communicate with its
+ peripherals. Sub-commands allow bus enumeration, displaying and
+ changing configuration space and a few other features.
+
+config CMD_PINMUX
+ bool "pinmux - show pins muxing"
+ depends on PINCTRL
+ default y if PINCTRL
+ help
+ Parse all available pin-controllers and show pins muxing. This
+ is useful for debug purpoer to check the pin muxing and to know if
+ a pin is configured as a GPIO or as an alternate function.
+
+config CMD_POWEROFF
+ bool "poweroff"
+ help
+ Poweroff/Shutdown the system
+
+config CMD_READ
+ bool "read - Read binary data from a partition"
+ help
+ Provides low-level access to the data in a partition.
+
+config CMD_REMOTEPROC
+ bool "remoteproc"
+ depends on REMOTEPROC
+ help
+ Support for Remote Processor control
+
+config CMD_SATA
+ bool "sata - Access SATA subsystem"
+ select SATA
+ help
+ SATA (Serial Advanced Technology Attachment) is a serial bus
+ standard for connecting to hard drives and other storage devices.
+ This command provides information about attached devices and allows
+ reading, writing and other operations.
+
+ SATA replaces PATA (originally just ATA), which stands for Parallel AT
+ Attachment, where AT refers to an IBM AT (Advanced Technology)
+ computer released in 1984.
+
+config CMD_SAVES
+ bool "saves - Save a file over serial in S-Record format"
+ help
+ Provides a way to save a binary file using the Motorola S-Record
+ format over the serial line.
+
+config CMD_SCSI
+ bool "scsi - Access to SCSI devices"
+ default y if SCSI
+ help
+ This provides a 'scsi' command which provides access to SCSI (Small
+ Computer System Interface) devices. The command provides a way to
+ scan the bus, reset the bus, read and write data and get information
+ about devices.
+
+config CMD_SDRAM
+ bool "sdram - Print SDRAM configuration information"
+ help
+ Provides information about attached SDRAM. This assumed that the
+ SDRAM has an EEPROM with information that can be read using the
+ I2C bus. This is only available on some boards.
+
+config CMD_SF
+ bool "sf"
+ depends on DM_SPI_FLASH || SPI_FLASH
+ default y if DM_SPI_FLASH
+ help
+ SPI Flash support
+
+config CMD_SF_TEST
+ bool "sf test - Allow testing of SPI flash"
+ depends on CMD_SF
+ help
+ Provides a way to test that SPI flash is working correctly. The
+ test is destructive, in that an area of SPI flash must be provided
+ for the test to use. Performance information is also provided,
+ measuring the performance of reading, writing and erasing in
+ Mbps (Million Bits Per Second). This value should approximately
+ equal the SPI bus speed for a single-bit-wide SPI bus, assuming
+ everything is working properly.
+
+config CMD_SPI
+ bool "sspi - Command to access spi device"
+ depends on SPI
+ help
+ SPI utility command.
+
+config DEFAULT_SPI_BUS
+ int "default spi bus used by sspi command"
+ depends on CMD_SPI
+ default 0
+
+config DEFAULT_SPI_MODE
+ hex "default spi mode used by sspi command (see include/spi.h)"
+ depends on CMD_SPI
+ default 0
+
+config CMD_TSI148
+ bool "tsi148 - Command to access tsi148 device"
+ help
+ This provides various sub-commands to initialise and configure the
+ Turndra tsi148 device. See the command help for full details.
+
+config CMD_UFS
+ bool "Enable UFS - Universal Flash Subsystem commands"
+ depends on UFS
+ help
+ "This provides commands to initialise and configure universal flash
+ subsystem devices"
+
+config CMD_UNIVERSE
+ bool "universe - Command to set up the Turndra Universe controller"
+ help
+ This allows setting up the VMEbus provided by this controller.
+ See the command help for full details.
+
+config CMD_USB
+ bool "usb"
+ depends on USB
+ select HAVE_BLOCK_DEVICE
+ help
+ USB support.
+
+config CMD_USB_SDP
+ bool "sdp"
+ select USB_FUNCTION_SDP
+ help
+ Enables the command "sdp" which is used to have U-Boot emulating the
+ Serial Download Protocol (SDP) via USB.
+
+config CMD_ROCKUSB
+ bool "rockusb"
+ depends on USB_FUNCTION_ROCKUSB
+ help
+ Rockusb protocol is widely used by Rockchip SoC based devices. It can
+ read/write info, image to/from devices. This enable rockusb command
+ support to communication with rockusb device. for more detail about
+ this command, please read doc/README.rockusb.
+
+config CMD_USB_MASS_STORAGE
+ bool "UMS usb mass storage"
+ select USB_FUNCTION_MASS_STORAGE
+ depends on BLK && USB_GADGET
+ help
+ Enables the command "ums" and the USB mass storage support to the
+ export a block device: U-Boot, the USB device, acts as a simple
+ external hard drive plugged on the host USB port.
+
+config CMD_PVBLOCK
+ bool "Xen para-virtualized block device"
+ depends on XEN
+ select PVBLOCK
+ help
+ Xen para-virtualized block device support
+
+config CMD_VIRTIO
+ bool "virtio"
+ depends on VIRTIO
+ depends on HAVE_BLOCK_DEVICE
+ default y if VIRTIO
+ help
+ VirtIO block device support
+
+config CMD_WDT
+ bool "wdt"
+ depends on WDT
+ help
+ This provides commands to control the watchdog timer devices.
+
+config CMD_AXI
+ bool "axi"
+ depends on AXI
+ help
+ Enable the command "axi" for accessing AXI (Advanced eXtensible
+ Interface) busses, a on-chip interconnect specification for managing
+ functional blocks in SoC designs, which is also often used in designs
+ involving FPGAs (e.g. communication with IP cores in Xilinx FPGAs).
+endmenu
+
+
+menu "Shell scripting commands"
+
+config CMD_ECHO
+ bool "echo"
+ default y
+ help
+ Echo args to console
+
+config CMD_ITEST
+ bool "itest"
+ default y
+ help
+ Return true/false on integer compare.
+
+config CMD_SOURCE
+ bool "source"
+ default y
+ help
+ Run script from memory
+
+config CMD_SETEXPR
+ bool "setexpr"
+ default y
+ help
+ Evaluate boolean and math expressions and store the result in an env
+ variable.
+ Also supports loading the value at a memory location into a variable.
+ If CONFIG_REGEX is enabled, setexpr also supports a gsub function.
+
+endmenu
+
+menu "Android support commands"
+
+config CMD_AB_SELECT
+ bool "ab_select"
+ default n
+ depends on ANDROID_AB
+ help
+ On Android devices with more than one boot slot (multiple copies of
+ the kernel and system images) this provides a command to select which
+ slot should be used to boot from and register the boot attempt. This
+ is used by the new A/B update model where one slot is updated in the
+ background while running from the other slot.
+
+endmenu
+
+if NET
+
+menuconfig CMD_NET
+ bool "Network commands"
+ default y
+ imply NETDEVICES
+
+if CMD_NET
+
+config CMD_BOOTP
+ bool "bootp"
+ default y
+ help
+ bootp - boot image via network using BOOTP/TFTP protocol
+
+config CMD_DHCP
+ bool "dhcp"
+ depends on CMD_BOOTP
+ help
+ Boot image via network using DHCP/TFTP protocol
+
+config BOOTP_BOOTPATH
+ bool "Request & store 'rootpath' from BOOTP/DHCP server"
+ default y
+ depends on CMD_BOOTP
+ help
+ Even though the config is called BOOTP_BOOTPATH, it stores the
+ path in the variable 'rootpath'.
+
+config BOOTP_DNS
+ bool "Request & store 'dnsip' from BOOTP/DHCP server"
+ default y
+ depends on CMD_BOOTP
+ help
+ The primary DNS server is stored as 'dnsip'. If two servers are
+ returned, you must set BOOTP_DNS2 to store that second server IP
+ also.
+
+config BOOTP_DNS2
+ bool "Store 'dnsip2' from BOOTP/DHCP server"
+ depends on BOOTP_DNS
+ help
+ If a DHCP client requests the DNS server IP from a DHCP server,
+ it is possible that more than one DNS serverip is offered to the
+ client. If CONFIG_BOOTP_DNS2 is enabled, the secondary DNS
+ server IP will be stored in the additional environment
+ variable "dnsip2". The first DNS serverip is always
+ stored in the variable "dnsip", when BOOTP_DNS is defined.
+
+config BOOTP_GATEWAY
+ bool "Request & store 'gatewayip' from BOOTP/DHCP server"
+ default y
+ depends on CMD_BOOTP
+
+config BOOTP_HOSTNAME
+ bool "Request & store 'hostname' from BOOTP/DHCP server"
+ default y
+ depends on CMD_BOOTP
+ help
+ The name may or may not be qualified with the local domain name.
+
+config BOOTP_PREFER_SERVERIP
+ bool "serverip variable takes precedent over DHCP server IP."
+ depends on CMD_BOOTP
+ help
+ By default a BOOTP/DHCP reply will overwrite the 'serverip' variable.
+
+ With this option enabled, the 'serverip' variable in the environment
+ takes precedence over DHCP server IP and will only be set by the DHCP
+ server if not already set in the environment.
+
+config BOOTP_SUBNETMASK
+ bool "Request & store 'netmask' from BOOTP/DHCP server"
+ default y
+ depends on CMD_BOOTP
+
+config BOOTP_NTPSERVER
+ bool "Request & store 'ntpserverip' from BOOTP/DHCP server"
+ depends on CMD_BOOTP
+
+config CMD_PCAP
+ bool "pcap capture"
+ help
+ Selecting this will allow capturing all Ethernet packets and store
+ them in physical memory in a PCAP formated file,
+ later to be analyzed by PCAP reader application (IE. WireShark).
+
+config BOOTP_PXE
+ bool "Send PXE client arch to BOOTP/DHCP server"
+ default y
+ depends on CMD_BOOTP && CMD_PXE
+ help
+ Supported for ARM, ARM64, and x86 for now.
+
+config BOOTP_PXE_CLIENTARCH
+ hex
+ depends on BOOTP_PXE
+ default 0x16 if ARM64
+ default 0x15 if ARM
+ default 0 if X86
+
+config BOOTP_VCI_STRING
+ string
+ depends on CMD_BOOTP
+ default "U-Boot.armv7" if CPU_V7A || CPU_V7M || CPU_V7R
+ default "U-Boot.armv8" if ARM64
+ default "U-Boot.arm" if ARM
+ default "U-Boot"
+
+config CMD_TFTPBOOT
+ bool "tftpboot"
+ default y
+ help
+ tftpboot - boot image via network using TFTP protocol
+
+config CMD_TFTPPUT
+ bool "tftp put"
+ depends on CMD_TFTPBOOT
+ help
+ TFTP put command, for uploading files to a server
+
+config CMD_TFTPSRV
+ bool "tftpsrv"
+ depends on CMD_TFTPBOOT
+ help
+ Act as a TFTP server and boot the first received file
+
+config NET_TFTP_VARS
+ bool "Control TFTP timeout and count through environment"
+ depends on CMD_TFTPBOOT
+ default y
+ help
+ If set, allows controlling the TFTP timeout through the
+ environment variable tftptimeout, and the TFTP maximum
+ timeout count through the variable tftptimeoutcountmax.
+ If unset, timeout and maximum are hard-defined as 1 second
+ and 10 timouts per TFTP transfer.
+
+config CMD_RARP
+ bool "rarpboot"
+ help
+ Boot image via network using RARP/TFTP protocol
+
+config CMD_NFS
+ bool "nfs"
+ default y
+ help
+ Boot image via network using NFS protocol.
+
+config CMD_MII
+ bool "mii"
+ imply CMD_MDIO
+ help
+ If set, allows 802.3(clause 22) MII Management functions interface access
+ The management interface specified in Clause 22 provides
+ a simple, two signal, serial interface to connect a
+ Station Management entity and a managed PHY for providing access
+ to management parameters and services.
+ The interface is referred to as the MII management interface.
+
+config CMD_MDIO
+ bool "mdio"
+ depends on PHYLIB
+ help
+ If set, allows Enable 802.3(clause 45) MDIO interface registers access
+ The MDIO interface is orthogonal to the MII interface and extends
+ it by adding access to more registers through indirect addressing.
+
+config CMD_PING
+ bool "ping"
+ help
+ Send ICMP ECHO_REQUEST to network host
+
+config CMD_CDP
+ bool "cdp"
+ help
+ Perform CDP network configuration
+
+config CMD_SNTP
+ bool "sntp"
+ select PROT_UDP
+ help
+ Synchronize RTC via network
+
+config CMD_DNS
+ bool "dns"
+ help
+ Lookup the IP of a hostname
+
+config CMD_LINK_LOCAL
+ bool "linklocal"
+ select LIB_RAND
+ help
+ Acquire a network IP address using the link-local protocol
+
+endif
+
+config CMD_ETHSW
+ bool "ethsw"
+ help
+ Allow control of L2 Ethernet switch commands. These are supported
+ by the vsc9953 Ethernet driver at present. Sub-commands allow
+ operations such as enabling / disabling a port and
+ viewing/maintaining the filtering database (FDB)
+
+config CMD_PXE
+ bool "pxe"
+ select MENU
+ help
+ Boot image via network using PXE protocol
+
+config CMD_WOL
+ bool "wol"
+ help
+ Wait for wake-on-lan Magic Packet
+
+endif
+
+menu "Misc commands"
+
+config CMD_BMP
+ bool "Enable 'bmp' command"
+ depends on LCD || DM_VIDEO || VIDEO
+ help
+ This provides a way to obtain information about a BMP-format image
+ and to display it. BMP (which presumably stands for BitMaP) is a
+ file format defined by Microsoft which supports images of various
+ depths, formats and compression methods. Headers on the file
+ determine the formats used. This command can be used by first loading
+ the image into RAM, then using this command to look at it or display
+ it.
+
+config CMD_BOOTCOUNT
+ bool "bootcount"
+ depends on BOOTCOUNT_LIMIT
+ help
+ Enable the bootcount command, which allows interrogation and
+ reset of the bootcounter.
+
+config CMD_BSP
+ bool "Enable board-specific commands"
+ help
+ (deprecated: instead, please define a Kconfig option for each command)
+
+ Some boards have board-specific commands which are only enabled
+ during developemnt and need to be turned off for production. This
+ option provides a way to control this. The commands that are enabled
+ vary depending on the board.
+
+config CMD_BLOCK_CACHE
+ bool "blkcache - control and stats for block cache"
+ depends on BLOCK_CACHE
+ default y if BLOCK_CACHE
+ help
+ Enable the blkcache command, which can be used to control the
+ operation of the cache functions.
+ This is most useful when fine-tuning the operation of the cache
+ during development, but also allows the cache to be disabled when
+ it might hurt performance (e.g. when using the ums command).
+
+config CMD_BUTTON
+ bool "button"
+ depends on BUTTON
+ default y if BUTTON
+ help
+ Enable the 'button' command which allows to get the status of
+ buttons supported by the board. The buttonss can be listed with
+ 'button list' and state can be known with 'button <label>'.
+ Any button drivers can be controlled with this command, e.g.
+ button_gpio.
+
+config CMD_CACHE
+ bool "icache or dcache"
+ help
+ Enable the "icache" and "dcache" commands
+
+config CMD_CONITRACE
+ bool "conitrace - trace console input codes"
+ help
+ Enable the 'conitrace' command which displays the codes received
+ from the console input as hexadecimal numbers.
+
+config CMD_CLS
+ bool "Enable clear screen command 'cls'"
+ depends on CFB_CONSOLE || DM_VIDEO || LCD || VIDEO
+ default y if LCD
+ help
+ Enable the 'cls' command which clears the screen contents
+ on video frame buffer.
+
+config CMD_EFIDEBUG
+ bool "efidebug - display/configure UEFI environment"
+ depends on EFI_LOADER
+ select EFI_DEVICE_PATH_TO_TEXT
+ default n
+ help
+ Enable the 'efidebug' command which provides a subset of UEFI
+ shell utility with simplified functionality. It will be useful
+ particularly for managing boot parameters as well as examining
+ various EFI status for debugging.
+
+config CMD_EXCEPTION
+ bool "exception - raise exception"
+ depends on ARM || RISCV || SANDBOX || X86
+ help
+ Enable the 'exception' command which allows to raise an exception.
+
+config CMD_LED
+ bool "led"
+ depends on LED
+ default y if LED
+ help
+ Enable the 'led' command which allows for control of LEDs supported
+ by the board. The LEDs can be listed with 'led list' and controlled
+ with led on/off/togle/blink. Any LED drivers can be controlled with
+ this command, e.g. led_gpio.
+
+config CMD_DATE
+ bool "date"
+ default y if DM_RTC
+ select LIB_DATE
+ help
+ Enable the 'date' command for getting/setting the time/date in RTC
+ devices.
+
+config CMD_RTC
+ bool "rtc"
+ depends on DM_RTC
+ help
+ Enable the 'rtc' command for low-level access to RTC devices.
+
+config CMD_TIME
+ bool "time"
+ help
+ Run commands and summarize execution time.
+
+config CMD_GETTIME
+ bool "gettime - read elapsed time"
+ help
+ Enable the 'gettime' command which reads the elapsed time since
+ U-Boot started running. This shows the time in seconds and
+ milliseconds. See also the 'bootstage' command which provides more
+ flexibility for boot timing.
+
+config CMD_RNG
+ bool "rng command"
+ depends on DM_RNG
+ select HEXDUMP
+ help
+ Print bytes from the hardware random number generator.
+
+config CMD_SLEEP
+ bool "sleep"
+ default y
+ help
+ Delay execution for some time
+
+config MP
+ bool "support for multiprocessor"
+ help
+ This provides an option to brinup
+ different processors in multiprocessor
+ cases.
+
+config CMD_TIMER
+ bool "timer"
+ help
+ Access the system timer.
+
+config CMD_SOUND
+ bool "sound"
+ depends on SOUND
+ help
+ This provides basic access to the U-Boot's sound support. The main
+ feature is to play a beep.
+
+ sound init - set up sound system
+ sound play - play a sound
+
+config CMD_SYSBOOT
+ bool "sysboot"
+ select MENU
+ help
+ Boot image via local extlinux.conf file
+
+config CMD_QFW
+ bool "qfw"
+ select QFW
+ help
+ This provides access to the QEMU firmware interface. The main
+ feature is to allow easy loading of files passed to qemu-system
+ via -kernel / -initrd
+
+config CMD_PSTORE
+ bool "pstore"
+ help
+ This provides access to Linux PStore with Rammoops backend. The main
+ feature is to allow to display or save PStore records.
+
+ See doc/pstore.rst for more information.
+
+if CMD_PSTORE
+
+config CMD_PSTORE_MEM_ADDR
+ hex "Memory Address"
+ depends on CMD_PSTORE
+ help
+ Base addr used for PStore ramoops memory, should be identical to
+ ramoops.mem_address parameter used by kernel
+
+config CMD_PSTORE_MEM_SIZE
+ hex "Memory size"
+ depends on CMD_PSTORE
+ default "0x10000"
+ help
+ Size of PStore ramoops memory, should be identical to ramoops.mem_size
+ parameter used by kernel, a power of 2 and larger than the sum of the
+ record sizes
+
+config CMD_PSTORE_RECORD_SIZE
+ hex "Dump record size"
+ depends on CMD_PSTORE
+ default "0x1000"
+ help
+ Size of each dump done on oops/panic, should be identical to
+ ramoops.record_size parameter used by kernel and a power of 2
+ Must be non-zero
+
+config CMD_PSTORE_CONSOLE_SIZE
+ hex "Kernel console log size"
+ depends on CMD_PSTORE
+ default "0x1000"
+ help
+ Size of kernel console log, should be identical to
+ ramoops.console_size parameter used by kernel and a power of 2
+ Must be non-zero
+
+config CMD_PSTORE_FTRACE_SIZE
+ hex "FTrace log size"
+ depends on CMD_PSTORE
+ default "0x1000"
+ help
+ Size of ftrace log, should be identical to ramoops.ftrace_size
+ parameter used by kernel and a power of 2
+
+config CMD_PSTORE_PMSG_SIZE
+ hex "User space message log size"
+ depends on CMD_PSTORE
+ default "0x1000"
+ help
+ Size of user space message log, should be identical to
+ ramoops.pmsg_size parameter used by kernel and a power of 2
+
+config CMD_PSTORE_ECC_SIZE
+ int "ECC size"
+ depends on CMD_PSTORE
+ default "0"
+ help
+ if non-zero, the option enables ECC support and specifies ECC buffer
+ size in bytes (1 is a special value, means 16 bytes ECC), should be
+ identical to ramoops.ramoops_ecc parameter used by kernel
+
+endif
+
+source "cmd/mvebu/Kconfig"
+
+config CMD_TERMINAL
+ bool "terminal - provides a way to attach a serial terminal"
+ help
+ Provides a 'cu'-like serial terminal command. This can be used to
+ access other serial ports from the system console. The terminal
+ is very simple with no special processing of characters. As with
+ cu, you can press ~. (tilde followed by period) to exit.
+
+config CMD_UUID
+ bool "uuid, guid - generation of unique IDs"
+ select LIB_UUID
+ help
+ This enables two commands:
+
+ uuid - generate random Universally Unique Identifier
+ guid - generate Globally Unique Identifier based on random UUID
+
+ The two commands are very similar except for the endianness of the
+ output.
+
+endmenu
+
+source "cmd/ti/Kconfig"
+
+config CMD_BOOTSTAGE
+ bool "Enable the 'bootstage' command"
+ depends on BOOTSTAGE
+ help
+ Add a 'bootstage' command which supports printing a report
+ and un/stashing of bootstage data.
+
+menu "Power commands"
+config CMD_PMIC
+ bool "Enable Driver Model PMIC command"
+ depends on DM_PMIC
+ help
+ This is the pmic command, based on a driver model pmic's API.
+ Command features are unchanged:
+ - list - list pmic devices
+ - pmic dev <id> - show or [set] operating pmic device (NEW)
+ - pmic dump - dump registers
+ - pmic read address - read byte of register at address
+ - pmic write address - write byte to register at address
+ The only one change for this command is 'dev' subcommand.
+
+config CMD_REGULATOR
+ bool "Enable Driver Model REGULATOR command"
+ depends on DM_REGULATOR
+ help
+ This command is based on driver model regulator's API.
+ User interface features:
+ - list - list regulator devices
+ - regulator dev <id> - show or [set] operating regulator device
+ - regulator info - print constraints info
+ - regulator status - print operating status
+ - regulator value <val] <-f> - print/[set] voltage value [uV]
+ - regulator current <val> - print/[set] current value [uA]
+ - regulator mode <id> - print/[set] operating mode id
+ - regulator enable - enable the regulator output
+ - regulator disable - disable the regulator output
+
+ The '-f' (force) option can be used for set the value which exceeds
+ the limits, which are found in device-tree and are kept in regulator's
+ uclass plat structure.
+
+endmenu
+
+menu "Security commands"
+config CMD_AES
+ bool "Enable the 'aes' command"
+ select AES
+ help
+ This provides a means to encrypt and decrypt data using the AES
+ (Advanced Encryption Standard). This algorithm uses a symetric key
+ and is widely used as a streaming cipher. Different key lengths are
+ supported by the algorithm but this command only supports 128 bits
+ at present.
+
+config CMD_BLOB
+ bool "Enable the 'blob' command"
+ depends on !MX6ULL && !MX6SLL && !MX6SL
+ select IMX_HAB if ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP || ARCH_IMX8M
+ help
+ This is used with the Freescale secure boot mechanism.
+
+ Freescale's SEC block has built-in Blob Protocol which provides
+ a method for protecting user-defined data across system power
+ cycles. SEC block protects data in a data structure called a Blob,
+ which provides both confidentiality and integrity protection.
+
+ Encapsulating data as a blob
+ Each time that the Blob Protocol is used to protect data, a
+ different randomly generated key is used to encrypt the data.
+ This random key is itself encrypted using a key which is derived
+ from SoC's non-volatile secret key and a 16 bit Key identifier.
+ The resulting encrypted key along with encrypted data is called a
+ blob. The non-volatile secure key is available for use only during
+ secure boot.
+
+ During decapsulation, the reverse process is performed to get back
+ the original data.
+
+ Sub-commands:
+ blob enc - encapsulating data as a cryptgraphic blob
+ blob dec - decapsulating cryptgraphic blob to get the data
+
+ Syntax:
+
+ blob enc src dst len km
+
+ Encapsulate and create blob of data $len bytes long
+ at address $src and store the result at address $dst.
+ $km is the 16 byte key modifier is also required for
+ generation/use as key for cryptographic operation. Key
+ modifier should be 16 byte long.
+
+ blob dec src dst len km
+
+ Decapsulate the blob of data at address $src and
+ store result of $len byte at addr $dst.
+ $km is the 16 byte key modifier is also required for
+ generation/use as key for cryptographic operation. Key
+ modifier should be 16 byte long.
+
+config CMD_HASH
+ bool "Support 'hash' command"
+ select HASH
+ help
+ This provides a way to hash data in memory using various supported
+ algorithms (such as SHA1, MD5, CRC32). The computed digest can be
+ saved to memory or to an environment variable. It is also possible
+ to verify a hash against data in memory.
+
+config CMD_HVC
+ bool "Support the 'hvc' command"
+ depends on ARM_SMCCC
+ help
+ Allows issuing Hypervisor Calls (HVCs). Mostly useful for
+ development and testing.
+
+config CMD_SMC
+ bool "Support the 'smc' command"
+ depends on ARM_SMCCC
+ help
+ Allows issuing Secure Monitor Calls (SMCs). Mostly useful for
+ development and testing.
+
+config HASH_VERIFY
+ bool "hash -v"
+ depends on CMD_HASH
+ help
+ Add -v option to verify data against a hash.
+
+config CMD_SCP03
+ bool "scp03 - SCP03 enable and rotate/provision operations"
+ depends on SCP03
+ help
+ This command provides access to a Trusted Application
+ running in a TEE to request Secure Channel Protocol 03
+ (SCP03) enablement and/or rotation of its SCP03 keys.
+
+config CMD_TPM_V1
+ bool
+
+config CMD_TPM_V2
+ bool
+
+config CMD_TPM
+ bool "Enable the 'tpm' command"
+ depends on TPM_V1 || TPM_V2
+ select CMD_TPM_V1 if TPM_V1
+ select CMD_TPM_V2 if TPM_V2
+ help
+ This provides a means to talk to a TPM from the command line. A wide
+ range of commands if provided - see 'tpm help' for details. The
+ command requires a suitable TPM on your board and the correct driver
+ must be enabled.
+
+if CMD_TPM
+
+config CMD_TPM_TEST
+ bool "Enable the 'tpm test' command"
+ depends on TPM_V1
+ help
+ This provides a a series of tests to confirm that the TPMv1.x is
+ working correctly. The tests cover initialisation, non-volatile RAM,
+ extend, global lock and checking that timing is within expectations.
+ The tests pass correctly on Infineon TPMs but may need to be adjusted
+ for other devices.
+
+endif
+
+endmenu
+
+menu "Firmware commands"
+config CMD_CROS_EC
+ bool "Enable crosec command"
+ depends on CROS_EC
+ default y
+ help
+ Enable command-line access to the Chrome OS EC (Embedded
+ Controller). This provides the 'crosec' command which has
+ a number of sub-commands for performing EC tasks such as
+ updating its flash, accessing a small saved context area
+ and talking to the I2C bus behind the EC (if there is one).
+endmenu
+
+menu "Filesystem commands"
+config CMD_BTRFS
+ bool "Enable the 'btrsubvol' command"
+ select FS_BTRFS
+ help
+ This enables the 'btrsubvol' command to list subvolumes
+ of a BTRFS filesystem. There are no special commands for
+ listing BTRFS directories or loading BTRFS files - this
+ can be done by the generic 'fs' commands (see CMD_FS_GENERIC)
+ when BTRFS is enabled (see FS_BTRFS).
+
+config CMD_CBFS
+ bool "Enable the 'cbfs' command"
+ depends on FS_CBFS
+ help
+ Define this to enable support for reading from a Coreboot
+ filesystem. This is a ROM-based filesystem used for accessing files
+ on systems that use coreboot as the first boot-loader and then load
+ U-Boot to actually boot the Operating System. Available commands are
+ cbfsinit, cbfsinfo, cbfsls and cbfsload.
+
+config CMD_CRAMFS
+ bool "Enable the 'cramfs' command"
+ depends on FS_CRAMFS
+ help
+ This provides commands for dealing with CRAMFS (Compressed ROM
+ filesystem). CRAMFS is useful when space is tight since files are
+ compressed. Two commands are provided:
+
+ cramfsls - lists files in a cramfs image
+ cramfsload - loads a file from a cramfs image
+
+config CMD_EXT2
+ bool "ext2 command support"
+ select FS_EXT4
+ help
+ Enables EXT2 FS command
+
+config CMD_EXT4
+ bool "ext4 command support"
+ select FS_EXT4
+ help
+ Enables EXT4 FS command
+
+config CMD_EXT4_WRITE
+ depends on CMD_EXT4
+ bool "ext4 write command support"
+ select EXT4_WRITE
+ help
+ Enables EXT4 FS write command
+
+config CMD_FAT
+ bool "FAT command support"
+ select FS_FAT
+ help
+ Support for the FAT fs
+
+config CMD_SQUASHFS
+ bool "SquashFS command support"
+ select FS_SQUASHFS
+ help
+ Enables SquashFS filesystem commands (e.g. load, ls).
+
+config CMD_FS_GENERIC
+ bool "filesystem commands"
+ help
+ Enables filesystem commands (e.g. load, ls) that work for multiple
+ fs types.
+
+config CMD_FS_UUID
+ bool "fsuuid command"
+ help
+ Enables fsuuid command for filesystem UUID.
+
+config CMD_JFFS2
+ bool "jffs2 command"
+ select FS_JFFS2
+ help
+ Enables commands to support the JFFS2 (Journalling Flash File System
+ version 2) filesystem. This enables fsload, ls and fsinfo which
+ provide the ability to load files, list directories and obtain
+ filesystem information.
+
+config CMD_MTDPARTS
+ bool "MTD partition support"
+ depends on MTD
+ help
+ MTD partitioning tool support.
+ It is strongly encouraged to avoid using this command
+ anymore along with 'sf', 'nand', 'onenand'. One can still
+ declare the partitions in the mtdparts environment variable
+ but better use the MTD stack and the 'mtd' command instead.
+
+config CMD_MTDPARTS_SPREAD
+ bool "Padd partition size to take account of bad blocks"
+ depends on CMD_MTDPARTS
+ help
+ This enables the 'spread' sub-command of the mtdparts command.
+ This command will modify the existing mtdparts variable by increasing
+ the size of the partitions such that 1) each partition's net size is
+ at least as large as the size specified in the mtdparts variable and
+ 2) each partition starts on a good block.
+
+config CMD_MTDPARTS_SHOW_NET_SIZES
+ bool "Show net size (w/o bad blocks) of partitions"
+ depends on CMD_MTDPARTS
+ help
+ Adds two columns to the printed partition table showing the
+ effective usable size of a partition, if bad blocks are taken
+ into account.
+
+config MTDIDS_DEFAULT
+ string "Default MTD IDs"
+ depends on MTD || SPI_FLASH
+ help
+ Defines a default MTD IDs list for use with MTD partitions in the
+ Linux MTD command line partitions format.
+
+config MTDPARTS_DEFAULT
+ string "Default MTD partition scheme"
+ depends on MTD || SPI_FLASH
+ help
+ Defines a default MTD partitioning scheme in the Linux MTD command
+ line partitions format
+
+config CMD_REISER
+ bool "reiser - Access to reiserfs filesystems"
+ help
+ This provides two commands which operate on a resierfs filesystem,
+ commonly used some years ago:
+
+ reiserls - list files
+ reiserload - load a file
+
+config CMD_YAFFS2
+ bool "yaffs2 - Access of YAFFS2 filesystem"
+ depends on YAFFS2
+ default y
+ help
+ This provides commands for accessing a YAFFS2 filesystem. Yet
+ Another Flash Filesystem 2 is a filesystem designed specifically
+ for NAND flash. It incorporates bad-block management and ensures
+ that device writes are sequential regardless of filesystem
+ activity.
+
+config CMD_ZFS
+ bool "zfs - Access of ZFS filesystem"
+ help
+ This provides commands to accessing a ZFS filesystem, commonly used
+ on Solaris systems. Two sub-commands are provided:
+
+ zfsls - list files in a directory
+ zfsload - load a file
+
+ See doc/README.zfs for more details.
+
+endmenu
+
+menu "Debug commands"
+
+config CMD_BEDBUG
+ bool "bedbug"
+ help
+ The bedbug (emBEDded deBUGger) command provides debugging features
+ for some PowerPC processors. For details please see the
+ documentation in doc/README.bedbug.
+
+config CMD_CBSYSINFO
+ bool "cbsysinfo"
+ depends on X86
+ default y if SYS_COREBOOT
+ help
+ This provides information about the coreboot sysinfo table stored in
+ memory by coreboot before jumping to U-Boot. It can be useful for
+ debugging the beaaviour of coreboot or U-Boot.
+
+config CMD_DIAG
+ bool "diag - Board diagnostics"
+ help
+ This command provides access to board diagnostic tests. These are
+ called Power-on Self Tests (POST). The command allows listing of
+ available tests and running either all the tests, or specific tests
+ identified by name.
+
+config CMD_IRQ
+ bool "irq - Show information about interrupts"
+ depends on !ARM && !MIPS && !RISCV && !SH
+ help
+ This enables two commands:
+
+ interrupts - enable or disable interrupts
+ irqinfo - print device-specific interrupt information
+
+config CMD_KGDB
+ bool "kgdb - Allow debugging of U-Boot with gdb"
+ depends on PPC
+ help
+ This enables a 'kgdb' command which allows gdb to connect to U-Boot
+ over a serial link for debugging purposes. This allows
+ single-stepping, inspecting variables, etc. This is supported only
+ on PowerPC at present.
+
+config CMD_LOG
+ bool "log - Generation, control and access to logging"
+ select LOG
+ select GETOPT
+ help
+ This provides access to logging features. It allows the output of
+ log data to be controlled to a limited extent (setting up the default
+ maximum log level for emitting of records). It also provides access
+ to a command used for testing the log system.
+
+config CMD_TRACE
+ bool "trace - Support tracing of function calls and timing"
+ help
+ Enables a command to control using of function tracing within
+ U-Boot. This allows recording of call traces including timing
+ information. The command can write data to memory for exporting
+ for analysis (e.g. using bootchart). See doc/README.trace for full
+ details.
+
+config CMD_AVB
+ bool "avb - Android Verified Boot 2.0 operations"
+ depends on AVB_VERIFY
+ default n
+ help
+ Enables a "avb" command to perform verification of partitions using
+ Android Verified Boot 2.0 functionality. It includes such subcommands:
+ avb init - initialize avb2 subsystem
+ avb read_rb - read rollback index
+ avb write_rb - write rollback index
+ avb is_unlocked - check device lock state
+ avb get_uuid - read and print uuid of a partition
+ avb read_part - read data from partition
+ avb read_part_hex - read data from partition and output to stdout
+ avb write_part - write data to partition
+ avb verify - run full verification chain
+
+config CMD_STACKPROTECTOR_TEST
+ bool "Test command for stack protector"
+ depends on STACKPROTECTOR
+ help
+ Enable stackprot_test command
+ The stackprot_test command will force a stack overrun to test
+ the stack smashing detection mechanisms.
+
+endmenu
+
+config CMD_UBI
+ tristate "Enable UBI - Unsorted block images commands"
+ select MTD_UBI
+ help
+ UBI is a software layer above MTD layer which admits use of LVM-like
+ logical volumes on top of MTD devices, hides some complexities of
+ flash chips like wear and bad blocks and provides some other useful
+ capabilities. Please, consult the MTD web site for more details
+ (www.linux-mtd.infradead.org). Activate this option if you want
+ to use U-Boot UBI commands.
+ It is also strongly encouraged to also enable CONFIG_MTD to get full
+ partition support.
+
+config CMD_UBI_RENAME
+ bool "Enable rename"
+ depends on CMD_UBI
+ default n
+ help
+ Enable a "ubi" command to rename ubi volume:
+ ubi rename <oldname> <newname>
+
+config CMD_UBIFS
+ tristate "Enable UBIFS - Unsorted block images filesystem commands"
+ depends on CMD_UBI
+ default y if CMD_UBI
+ select LZO
+ help
+ UBIFS is a file system for flash devices which works on top of UBI.
+
+endmenu
diff --git a/roms/u-boot/cmd/Makefile b/roms/u-boot/cmd/Makefile
new file mode 100644
index 000000000..9d10e07f0
--- /dev/null
+++ b/roms/u-boot/cmd/Makefile
@@ -0,0 +1,255 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2004-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+ifndef CONFIG_SPL_BUILD
+# core command
+obj-y += boot.o
+obj-$(CONFIG_CMD_BOOTM) += bootm.o
+obj-y += help.o
+obj-y += panic.o
+obj-y += version.o
+
+# command
+obj-$(CONFIG_CMD_ACPI) += acpi.o
+obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
+obj-$(CONFIG_CMD_AES) += aes.o
+obj-$(CONFIG_CMD_AB_SELECT) += ab_select.o
+obj-$(CONFIG_CMD_ADC) += adc.o
+obj-$(CONFIG_CMD_ARMFLASH) += armflash.o
+obj-$(CONFIG_HAVE_BLOCK_DEVICE) += blk_common.o
+obj-$(CONFIG_CMD_SOURCE) += source.o
+obj-$(CONFIG_CMD_BCB) += bcb.o
+obj-$(CONFIG_CMD_BDI) += bdinfo.o
+obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
+obj-$(CONFIG_CMD_BIND) += bind.o
+obj-$(CONFIG_CMD_BINOP) += binop.o
+obj-$(CONFIG_CMD_BLOBLIST) += bloblist.o
+obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o
+obj-$(CONFIG_CMD_BMP) += bmp.o
+obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o
+obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o
+obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o
+obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o
+obj-$(CONFIG_CMD_BOOTZ) += bootz.o
+obj-$(CONFIG_CMD_BOOTI) += booti.o
+obj-$(CONFIG_CMD_BTRFS) += btrfs.o
+obj-$(CONFIG_CMD_BUTTON) += button.o
+obj-$(CONFIG_CMD_CACHE) += cache.o
+obj-$(CONFIG_CMD_CBFS) += cbfs.o
+obj-$(CONFIG_CMD_CLK) += clk.o
+obj-$(CONFIG_CMD_CLS) += cls.o
+obj-$(CONFIG_CMD_CONFIG) += config.o
+obj-$(CONFIG_CMD_CONITRACE) += conitrace.o
+obj-$(CONFIG_CMD_CONSOLE) += console.o
+obj-$(CONFIG_CMD_CPU) += cpu.o
+obj-$(CONFIG_DATAFLASH_MMC_SELECT) += dataflash_mmc_mux.o
+obj-$(CONFIG_CMD_DATE) += date.o
+obj-$(CONFIG_CMD_DEMO) += demo.o
+obj-$(CONFIG_CMD_DM) += dm.o
+obj-$(CONFIG_CMD_SOUND) += sound.o
+ifdef CONFIG_POST
+obj-$(CONFIG_CMD_DIAG) += diag.o
+endif
+obj-$(CONFIG_CMD_ADTIMG) += adtimg.o
+obj-$(CONFIG_CMD_ABOOTIMG) += abootimg.o
+obj-$(CONFIG_CMD_EXTENSION) += extension_board.o
+obj-$(CONFIG_CMD_ECHO) += echo.o
+obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o
+obj-$(CONFIG_CMD_EEPROM) += eeprom.o
+obj-$(CONFIG_EFI_STUB) += efi.o
+obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o
+obj-$(CONFIG_CMD_ELF) += elf.o
+obj-$(CONFIG_HUSH_PARSER) += exit.o
+obj-$(CONFIG_CMD_EXT4) += ext4.o
+obj-$(CONFIG_CMD_EXT2) += ext2.o
+obj-$(CONFIG_CMD_FAT) += fat.o
+obj-$(CONFIG_CMD_FDT) += fdt.o
+obj-$(CONFIG_CMD_SQUASHFS) += sqfs.o
+obj-$(CONFIG_CMD_FLASH) += flash.o
+obj-$(CONFIG_CMD_FPGA) += fpga.o
+obj-$(CONFIG_CMD_FPGAD) += fpgad.o
+obj-$(CONFIG_CMD_FS_GENERIC) += fs.o
+obj-$(CONFIG_CMD_FUSE) += fuse.o
+obj-$(CONFIG_CMD_GETTIME) += gettime.o
+obj-$(CONFIG_CMD_GPIO) += gpio.o
+obj-$(CONFIG_CMD_HVC) += smccc.o
+obj-$(CONFIG_CMD_I2C) += i2c.o
+obj-$(CONFIG_CMD_IOTRACE) += iotrace.o
+obj-$(CONFIG_CMD_HASH) += hash.o
+obj-$(CONFIG_CMD_IDE) += ide.o disk.o
+obj-$(CONFIG_CMD_INI) += ini.o
+obj-$(CONFIG_CMD_IRQ) += irq.o
+obj-$(CONFIG_CMD_ITEST) += itest.o
+obj-$(CONFIG_CMD_JFFS2) += jffs2.o
+obj-$(CONFIG_CMD_CRAMFS) += cramfs.o
+obj-$(CONFIG_LED_STATUS_CMD) += legacy_led.o
+obj-$(CONFIG_CMD_LED) += led.o
+obj-$(CONFIG_CMD_LICENSE) += license.o
+obj-y += load.o
+obj-$(CONFIG_CMD_LOG) += log.o
+obj-$(CONFIG_CMD_LSBLK) += lsblk.o
+obj-$(CONFIG_ID_EEPROM) += mac.o
+obj-$(CONFIG_CMD_MD5SUM) += md5sum.o
+obj-$(CONFIG_CMD_MEMORY) += mem.o
+obj-$(CONFIG_CMD_IO) += io.o
+obj-$(CONFIG_CMD_MFSL) += mfsl.o
+obj-$(CONFIG_CMD_MII) += mii.o
+obj-$(CONFIG_CMD_MISC) += misc.o
+obj-$(CONFIG_CMD_MDIO) += mdio.o
+obj-$(CONFIG_CMD_SLEEP) += sleep.o
+obj-$(CONFIG_CMD_MMC) += mmc.o
+obj-$(CONFIG_CMD_OPTEE_RPMB) += optee_rpmb.o
+obj-$(CONFIG_MP) += mp.o
+obj-$(CONFIG_CMD_MTD) += mtd.o
+obj-$(CONFIG_CMD_MTDPARTS) += mtdparts.o
+obj-$(CONFIG_CMD_CLONE) += clone.o
+ifneq ($(CONFIG_CMD_NAND)$(CONFIG_CMD_SF),)
+obj-y += legacy-mtd-utils.o
+endif
+obj-$(CONFIG_CMD_MUX) += mux.o
+obj-$(CONFIG_CMD_NAND) += nand.o
+obj-$(CONFIG_CMD_NET) += net.o
+obj-$(CONFIG_CMD_NVEDIT_EFI) += nvedit_efi.o
+obj-$(CONFIG_CMD_ONENAND) += onenand.o
+obj-$(CONFIG_CMD_OSD) += osd.o
+obj-$(CONFIG_CMD_PART) += part.o
+obj-$(CONFIG_CMD_PCAP) += pcap.o
+ifdef CONFIG_PCI
+obj-$(CONFIG_CMD_PCI) += pci.o
+endif
+obj-$(CONFIG_CMD_PINMUX) += pinmux.o
+obj-$(CONFIG_CMD_PMC) += pmc.o
+obj-$(CONFIG_CMD_PSTORE) += pstore.o
+obj-$(CONFIG_CMD_PWM) += pwm.o
+obj-$(CONFIG_CMD_PXE) += pxe.o pxe_utils.o
+obj-$(CONFIG_CMD_WOL) += wol.o
+obj-$(CONFIG_CMD_QFW) += qfw.o
+obj-$(CONFIG_CMD_READ) += read.o
+obj-$(CONFIG_CMD_REGINFO) += reginfo.o
+obj-$(CONFIG_CMD_REISER) += reiser.o
+obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o
+obj-$(CONFIG_CMD_RNG) += rng.o
+obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
+obj-$(CONFIG_CMD_RTC) += rtc.o
+obj-$(CONFIG_SANDBOX) += host.o
+obj-$(CONFIG_CMD_SATA) += sata.o
+obj-$(CONFIG_CMD_NVME) += nvme.o
+obj-$(CONFIG_SANDBOX) += sb.o
+obj-$(CONFIG_CMD_SF) += sf.o
+obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o
+obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o
+obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
+obj-$(CONFIG_CMD_SPI) += spi.o
+obj-$(CONFIG_CMD_STRINGS) += strings.o
+obj-$(CONFIG_CMD_SMC) += smccc.o
+obj-$(CONFIG_CMD_SYSBOOT) += sysboot.o pxe_utils.o
+obj-$(CONFIG_CMD_STACKPROTECTOR_TEST) += stackprot_test.o
+obj-$(CONFIG_CMD_TERMINAL) += terminal.o
+obj-$(CONFIG_CMD_TIME) += time.o
+obj-$(CONFIG_CMD_TIMER) += timer.o
+obj-$(CONFIG_CMD_TRACE) += trace.o
+obj-$(CONFIG_HUSH_PARSER) += test.o
+obj-$(CONFIG_CMD_TPM) += tpm-common.o
+obj-$(CONFIG_CMD_TPM_V1) += tpm-v1.o
+obj-$(CONFIG_CMD_TPM_TEST) += tpm_test.o
+obj-$(CONFIG_CMD_TPM_V2) += tpm-v2.o
+obj-$(CONFIG_CMD_CROS_EC) += cros_ec.o
+obj-$(CONFIG_CMD_TSI148) += tsi148.o
+obj-$(CONFIG_CMD_UBI) += ubi.o
+obj-$(CONFIG_CMD_UBIFS) += ubifs.o
+obj-$(CONFIG_CMD_UNIVERSE) += universe.o
+obj-$(CONFIG_CMD_UNLZ4) += unlz4.o
+obj-$(CONFIG_CMD_UNZIP) += unzip.o
+obj-$(CONFIG_CMD_VIRTIO) += virtio.o
+obj-$(CONFIG_CMD_WDT) += wdt.o
+obj-$(CONFIG_CMD_LZMADEC) += lzmadec.o
+obj-$(CONFIG_CMD_UFS) += ufs.o
+obj-$(CONFIG_CMD_USB) += usb.o disk.o
+obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o
+obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o
+
+obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o
+obj-$(CONFIG_CMD_USB_SDP) += usb_gadget_sdp.o
+obj-$(CONFIG_CMD_THOR_DOWNLOAD) += thordown.o
+obj-$(CONFIG_CMD_XIMG) += ximg.o
+obj-$(CONFIG_CMD_YAFFS2) += yaffs2.o
+obj-$(CONFIG_CMD_SPL) += spl.o
+obj-$(CONFIG_CMD_W1) += w1.o
+obj-$(CONFIG_CMD_ZIP) += zip.o
+obj-$(CONFIG_CMD_ZFS) += zfs.o
+
+obj-$(CONFIG_CMD_DFU) += dfu.o
+obj-$(CONFIG_CMD_GPT) += gpt.o
+obj-$(CONFIG_CMD_MBR) += mbr.o
+obj-$(CONFIG_CMD_ETHSW) += ethsw.o
+obj-$(CONFIG_CMD_AXI) += axi.o
+obj-$(CONFIG_CMD_PVBLOCK) += pvblock.o
+
+# Power
+obj-$(CONFIG_CMD_PMIC) += pmic.o
+obj-$(CONFIG_CMD_REGULATOR) += regulator.o
+
+obj-$(CONFIG_CMD_BLOB) += blob.o
+
+# Android Verified Boot 2.0
+obj-$(CONFIG_CMD_AVB) += avb.o
+
+# Foundries.IO SCP03
+obj-$(CONFIG_CMD_SCP03) += scp03.o
+
+obj-$(CONFIG_ARM) += arm/
+obj-$(CONFIG_RISCV) += riscv/
+obj-$(CONFIG_SANDBOX) += sandbox/
+obj-$(CONFIG_X86) += x86/
+
+obj-$(CONFIG_ARCH_MVEBU) += mvebu/
+endif # !CONFIG_SPL_BUILD
+
+obj-$(CONFIG_$(SPL_)CMD_TLV_EEPROM) += tlv_eeprom.o
+
+# core command
+obj-y += nvedit.o
+
+obj-$(CONFIG_CMD_BCM_EXT_UTILS) += broadcom/
+
+obj-$(CONFIG_TI_COMMON_CMD_OPTIONS) += ti/
+
+filechk_data_gz = (echo "static const char data_gz[] ="; cat $< | scripts/bin2c; echo ";")
+
+filechk_data_size = \
+ (echo "static const size_t data_size = "; \
+ cat $< | wc -c; echo ";")
+
+# "config" command
+$(obj)/config.o: $(obj)/config_data_gz.h $(obj)/config_data_size.h
+
+targets += config_data.gz
+$(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE
+ $(call if_changed,gzip)
+
+targets += config_data_gz.h
+$(obj)/config_data_gz.h: $(obj)/config_data.gz FORCE
+ $(call filechk,data_gz)
+
+targets += config_data_size.h
+$(obj)/config_data_size.h: $(KCONFIG_CONFIG) FORCE
+ $(call filechk,data_size)
+
+# "license" command
+$(obj)/license.o: $(obj)/license_data_gz.h $(obj)/license_data_size.h
+
+targets += license_data.gz
+$(obj)/license_data.gz: $(srctree)/Licenses/gpl-2.0.txt FORCE
+ $(call if_changed,gzip)
+
+targets += license_data_gz.h
+$(obj)/license_data_gz.h: $(obj)/license_data.gz FORCE
+ $(call filechk,data_gz)
+
+targets += license_data_size.h
+$(obj)/license_data_size.h: $(srctree)/Licenses/gpl-2.0.txt FORCE
+ $(call filechk,data_size)
+
+CFLAGS_ethsw.o := -Wno-enum-conversion
diff --git a/roms/u-boot/cmd/ab_select.c b/roms/u-boot/cmd/ab_select.c
new file mode 100644
index 000000000..3e46663d6
--- /dev/null
+++ b/roms/u-boot/cmd/ab_select.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ */
+
+#include <common.h>
+#include <android_ab.h>
+#include <command.h>
+#include <env.h>
+#include <part.h>
+
+static int do_ab_select(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+ struct blk_desc *dev_desc;
+ struct disk_partition part_info;
+ char slot[2];
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ /* Lookup the "misc" partition from argv[2] and argv[3] */
+ if (part_get_info_by_dev_and_name_or_num(argv[2], argv[3],
+ &dev_desc, &part_info,
+ false) < 0) {
+ return CMD_RET_FAILURE;
+ }
+
+ ret = ab_select_slot(dev_desc, &part_info);
+ if (ret < 0) {
+ printf("Android boot failed, error %d.\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ /* Android standard slot names are 'a', 'b', ... */
+ slot[0] = BOOT_SLOT_NAME(ret);
+ slot[1] = '\0';
+ env_set(argv[1], slot);
+ printf("ANDROID: Booting slot: %s\n", slot);
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(ab_select, 4, 0, do_ab_select,
+ "Select the slot used to boot from and register the boot attempt.",
+ "<slot_var_name> <interface> <dev[:part|#part_name]>\n"
+ " - Load the slot metadata from the partition 'part' on\n"
+ " device type 'interface' instance 'dev' and store the active\n"
+ " slot in the 'slot_var_name' variable. This also updates the\n"
+ " Android slot metadata with a boot attempt, which can cause\n"
+ " successive calls to this function to return a different result\n"
+ " if the returned slot runs out of boot attempts.\n"
+ " - If 'part_name' is passed, preceded with a # instead of :, the\n"
+ " partition name whose label is 'part_name' will be looked up in\n"
+ " the partition table. This is commonly the \"misc\" partition.\n"
+);
diff --git a/roms/u-boot/cmd/abootimg.c b/roms/u-boot/cmd/abootimg.c
new file mode 100644
index 000000000..40e8978f1
--- /dev/null
+++ b/roms/u-boot/cmd/abootimg.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020
+ * Sam Protsenko <joe.skb7@gmail.com>
+ */
+
+#include <android_image.h>
+#include <common.h>
+#include <command.h>
+#include <image.h>
+#include <mapmem.h>
+
+#define abootimg_addr() \
+ (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr)
+
+/* Please use abootimg_addr() macro to obtain the boot image address */
+static ulong _abootimg_addr = -1;
+
+static int abootimg_get_ver(int argc, char *const argv[])
+{
+ const struct andr_img_hdr *hdr;
+ int res = CMD_RET_SUCCESS;
+
+ if (argc > 1)
+ return CMD_RET_USAGE;
+
+ hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
+ if (android_image_check_header(hdr)) {
+ printf("Error: Boot Image header is incorrect\n");
+ res = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ if (argc == 0)
+ printf("%u\n", hdr->header_version);
+ else
+ env_set_ulong(argv[0], hdr->header_version);
+
+exit:
+ unmap_sysmem(hdr);
+ return res;
+}
+
+static int abootimg_get_recovery_dtbo(int argc, char *const argv[])
+{
+ ulong addr;
+ u32 size;
+
+ if (argc > 2)
+ return CMD_RET_USAGE;
+
+ if (!android_image_get_dtbo(abootimg_addr(), &addr, &size))
+ return CMD_RET_FAILURE;
+
+ if (argc == 0) {
+ printf("%lx\n", addr);
+ } else {
+ env_set_hex(argv[0], addr);
+ if (argc == 2)
+ env_set_hex(argv[1], size);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int abootimg_get_dtb_load_addr(int argc, char *const argv[])
+{
+ const struct andr_img_hdr *hdr;
+ int res = CMD_RET_SUCCESS;
+
+ if (argc > 1)
+ return CMD_RET_USAGE;
+
+ hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
+ if (android_image_check_header(hdr)) {
+ printf("Error: Boot Image header is incorrect\n");
+ res = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ if (hdr->header_version < 2) {
+ printf("Error: header_version must be >= 2 for this\n");
+ res = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ if (argc == 0)
+ printf("%lx\n", (ulong)hdr->dtb_addr);
+ else
+ env_set_hex(argv[0], (ulong)hdr->dtb_addr);
+
+exit:
+ unmap_sysmem(hdr);
+ return res;
+}
+
+static int abootimg_get_dtb_by_index(int argc, char *const argv[])
+{
+ const char *index_str;
+ u32 num;
+ char *endp;
+ ulong addr;
+ u32 size;
+
+ if (argc < 1 || argc > 3)
+ return CMD_RET_USAGE;
+
+ index_str = argv[0] + strlen("--index=");
+ if (index_str[0] == '\0') {
+ printf("Error: Wrong index num\n");
+ return CMD_RET_FAILURE;
+ }
+
+ num = simple_strtoul(index_str, &endp, 0);
+ if (*endp != '\0') {
+ printf("Error: Wrong index num\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!android_image_get_dtb_by_index(abootimg_addr(), num,
+ &addr, &size)) {
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc == 1) {
+ printf("%lx\n", addr);
+ } else {
+ if (env_set_hex(argv[1], addr)) {
+ printf("Error: Can't set [addr_var]\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc == 3) {
+ if (env_set_hex(argv[2], size)) {
+ printf("Error: Can't set [size_var]\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int abootimg_get_dtb(int argc, char *const argv[])
+{
+ if (argc < 1)
+ return CMD_RET_USAGE;
+
+ if (strstr(argv[0], "--index="))
+ return abootimg_get_dtb_by_index(argc, argv);
+
+ return CMD_RET_USAGE;
+}
+
+static int do_abootimg_addr(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *endp;
+ ulong img_addr;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ img_addr = simple_strtoul(argv[1], &endp, 16);
+ if (*endp != '\0') {
+ printf("Error: Wrong image address\n");
+ return CMD_RET_FAILURE;
+ }
+
+ _abootimg_addr = img_addr;
+ return CMD_RET_SUCCESS;
+}
+
+static int do_abootimg_get(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *param;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ param = argv[1];
+ argc -= 2;
+ argv += 2;
+ if (!strcmp(param, "ver"))
+ return abootimg_get_ver(argc, argv);
+ else if (!strcmp(param, "recovery_dtbo"))
+ return abootimg_get_recovery_dtbo(argc, argv);
+ else if (!strcmp(param, "dtb_load_addr"))
+ return abootimg_get_dtb_load_addr(argc, argv);
+ else if (!strcmp(param, "dtb"))
+ return abootimg_get_dtb(argc, argv);
+
+ return CMD_RET_USAGE;
+}
+
+static int do_abootimg_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(argv[1], "dtb")) {
+ if (android_image_print_dtb_contents(abootimg_addr()))
+ return CMD_RET_FAILURE;
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_abootimg_sub[] = {
+ U_BOOT_CMD_MKENT(addr, 2, 1, do_abootimg_addr, "", ""),
+ U_BOOT_CMD_MKENT(dump, 2, 1, do_abootimg_dump, "", ""),
+ U_BOOT_CMD_MKENT(get, 5, 1, do_abootimg_get, "", ""),
+};
+
+static int do_abootimg(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ cp = find_cmd_tbl(argv[1], cmd_abootimg_sub,
+ ARRAY_SIZE(cmd_abootimg_sub));
+
+ /* Strip off leading 'abootimg' command argument */
+ argc--;
+ argv++;
+
+ if (!cp || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+ if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+ return CMD_RET_SUCCESS;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ abootimg, CONFIG_SYS_MAXARGS, 0, do_abootimg,
+ "manipulate Android Boot Image",
+ "addr <addr>\n"
+ " - set the address in RAM where boot image is located\n"
+ " ($loadaddr is used by default)\n"
+ "abootimg dump dtb\n"
+ " - print info for all DT blobs in DTB area\n"
+ "abootimg get ver [varname]\n"
+ " - get header version\n"
+ "abootimg get recovery_dtbo [addr_var [size_var]]\n"
+ " - get address and size (hex) of recovery DTBO area in the image\n"
+ " [addr_var]: variable name to contain DTBO area address\n"
+ " [size_var]: variable name to contain DTBO area size\n"
+ "abootimg get dtb_load_addr [varname]\n"
+ " - get load address (hex) of DTB, from image header\n"
+ "abootimg get dtb --index=<num> [addr_var [size_var]]\n"
+ " - get address and size (hex) of DT blob in the image by index\n"
+ " <num>: index number of desired DT blob in DTB area\n"
+ " [addr_var]: variable name to contain DT blob address\n"
+ " [size_var]: variable name to contain DT blob size"
+);
diff --git a/roms/u-boot/cmd/acpi.c b/roms/u-boot/cmd/acpi.c
new file mode 100644
index 000000000..e5b9a1752
--- /dev/null
+++ b/roms/u-boot/cmd/acpi.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+#include <common.h>
+#include <command.h>
+#include <mapmem.h>
+#include <acpi/acpi_table.h>
+#include <asm/acpi_table.h>
+#include <asm/global_data.h>
+#include <dm/acpi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * dump_hdr() - Dump an ACPI header
+ *
+ * If the header is for FACS then it shows the revision information as well
+ *
+ * @hdr: ACPI header to dump
+ */
+static void dump_hdr(struct acpi_table_header *hdr)
+{
+ bool has_hdr = memcmp(hdr->signature, "FACS", ACPI_NAME_LEN);
+
+ printf("%.*s %08lx %06x", ACPI_NAME_LEN, hdr->signature,
+ (ulong)map_to_sysmem(hdr), hdr->length);
+ if (has_hdr) {
+ printf(" (v%02d %.6s %.8s %x %.4s %x)\n", hdr->revision,
+ hdr->oem_id, hdr->oem_table_id, hdr->oem_revision,
+ hdr->aslc_id, hdr->aslc_revision);
+ } else {
+ printf("\n");
+ }
+}
+
+/**
+ * find_table() - Look up an ACPI table
+ *
+ * @sig: Signature of table (4 characters, upper case)
+ * @return pointer to table header, or NULL if not found
+ */
+struct acpi_table_header *find_table(const char *sig)
+{
+ struct acpi_rsdp *rsdp;
+ struct acpi_rsdt *rsdt;
+ int len, i, count;
+
+ rsdp = map_sysmem(gd->arch.acpi_start, 0);
+ if (!rsdp)
+ return NULL;
+ rsdt = map_sysmem(rsdp->rsdt_address, 0);
+ len = rsdt->header.length - sizeof(rsdt->header);
+ count = len / sizeof(u32);
+ for (i = 0; i < count; i++) {
+ struct acpi_table_header *hdr;
+
+ hdr = map_sysmem(rsdt->entry[i], 0);
+ if (!memcmp(hdr->signature, sig, ACPI_NAME_LEN))
+ return hdr;
+ if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN)) {
+ struct acpi_fadt *fadt = (struct acpi_fadt *)hdr;
+
+ if (!memcmp(sig, "DSDT", ACPI_NAME_LEN) && fadt->dsdt)
+ return map_sysmem(fadt->dsdt, 0);
+ if (!memcmp(sig, "FACS", ACPI_NAME_LEN) &&
+ fadt->firmware_ctrl)
+ return map_sysmem(fadt->firmware_ctrl, 0);
+ }
+ }
+
+ return NULL;
+}
+
+static int dump_table_name(const char *sig)
+{
+ struct acpi_table_header *hdr;
+
+ hdr = find_table(sig);
+ if (!hdr)
+ return -ENOENT;
+ printf("%.*s @ %08lx\n", ACPI_NAME_LEN, hdr->signature,
+ (ulong)map_to_sysmem(hdr));
+ print_buffer(0, hdr, 1, hdr->length, 0);
+
+ return 0;
+}
+
+static void list_fadt(struct acpi_fadt *fadt)
+{
+ if (fadt->dsdt)
+ dump_hdr(map_sysmem(fadt->dsdt, 0));
+ if (fadt->firmware_ctrl)
+ dump_hdr(map_sysmem(fadt->firmware_ctrl, 0));
+}
+
+static int list_rsdt(struct acpi_rsdt *rsdt, struct acpi_xsdt *xsdt)
+{
+ int len, i, count;
+
+ dump_hdr(&rsdt->header);
+ if (xsdt)
+ dump_hdr(&xsdt->header);
+ len = rsdt->header.length - sizeof(rsdt->header);
+ count = len / sizeof(u32);
+ for (i = 0; i < count; i++) {
+ struct acpi_table_header *hdr;
+
+ if (!rsdt->entry[i])
+ break;
+ hdr = map_sysmem(rsdt->entry[i], 0);
+ dump_hdr(hdr);
+ if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN))
+ list_fadt((struct acpi_fadt *)hdr);
+ if (xsdt) {
+ if (xsdt->entry[i] != rsdt->entry[i]) {
+ printf(" (xsdt mismatch %llx)\n",
+ xsdt->entry[i]);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int list_rsdp(struct acpi_rsdp *rsdp)
+{
+ struct acpi_rsdt *rsdt;
+ struct acpi_xsdt *xsdt;
+
+ printf("RSDP %08lx %06x (v%02d %.6s)\n", (ulong)map_to_sysmem(rsdp),
+ rsdp->length, rsdp->revision, rsdp->oem_id);
+ rsdt = map_sysmem(rsdp->rsdt_address, 0);
+ xsdt = map_sysmem(rsdp->xsdt_address, 0);
+ list_rsdt(rsdt, xsdt);
+
+ return 0;
+}
+
+static int do_acpi_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct acpi_rsdp *rsdp;
+
+ rsdp = map_sysmem(gd->arch.acpi_start, 0);
+ if (!rsdp) {
+ printf("No ACPI tables present\n");
+ return 0;
+ }
+ printf("ACPI tables start at %lx\n", gd->arch.acpi_start);
+ list_rsdp(rsdp);
+
+ return 0;
+}
+
+static int do_acpi_items(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bool dump_contents;
+
+ dump_contents = argc >= 2 && !strcmp("-d", argv[1]);
+ acpi_dump_items(dump_contents ? ACPI_DUMP_CONTENTS : ACPI_DUMP_LIST);
+
+ return 0;
+}
+
+static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *name;
+ char sig[ACPI_NAME_LEN];
+ int ret;
+
+ name = argv[1];
+ if (strlen(name) != ACPI_NAME_LEN) {
+ printf("Table name '%s' must be four characters\n", name);
+ return CMD_RET_FAILURE;
+ }
+ str_to_upper(name, sig, -1);
+ ret = dump_table_name(sig);
+ if (ret) {
+ printf("Table '%.*s' not found\n", ACPI_NAME_LEN, sig);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char acpi_help_text[] =
+ "list - list ACPI tables\n"
+ "acpi items [-d] - List/dump each piece of ACPI data from devices\n"
+ "acpi dump <name> - Dump ACPI table";
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
+ U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
+ U_BOOT_SUBCMD_MKENT(items, 2, 1, do_acpi_items),
+ U_BOOT_SUBCMD_MKENT(dump, 2, 1, do_acpi_dump));
diff --git a/roms/u-boot/cmd/adc.c b/roms/u-boot/cmd/adc.c
new file mode 100644
index 000000000..16f914a03
--- /dev/null
+++ b/roms/u-boot/cmd/adc.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <adc.h>
+
+static int do_adc_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_ADC, &dev);
+ if (ret) {
+ printf("No available ADC device\n");
+ return CMD_RET_FAILURE;
+ }
+
+ do {
+ printf("- %s\n", dev->name);
+
+ ret = uclass_next_device(&dev);
+ if (ret)
+ return CMD_RET_FAILURE;
+ } while (dev);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_adc_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ unsigned int data_mask, ch_mask;
+ int ret, vss, vdd;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ ret = uclass_get_device_by_name(UCLASS_ADC, argv[1], &dev);
+ if (ret) {
+ printf("Unknown ADC device %s\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("ADC Device '%s' :\n", argv[1]);
+
+ ret = adc_channel_mask(dev, &ch_mask);
+ if (!ret)
+ printf("channel mask: %x\n", ch_mask);
+
+ ret = adc_data_mask(dev, &data_mask);
+ if (!ret)
+ printf("data mask: %x\n", data_mask);
+
+ ret = adc_vdd_value(dev, &vdd);
+ if (!ret)
+ printf("vdd: %duV\n", vdd);
+
+ ret = adc_vss_value(dev, &vss);
+ if (!ret)
+ printf("vss: %duV\n", vss);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_adc_single(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ unsigned int data;
+ int ret, uV;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ ret = adc_channel_single_shot(argv[1], simple_strtol(argv[2], NULL, 0),
+ &data);
+ if (ret) {
+ printf("Error getting single shot for device %s channel %s\n",
+ argv[1], argv[2]);
+ return CMD_RET_FAILURE;
+ }
+
+ ret = uclass_get_device_by_name(UCLASS_ADC, argv[1], &dev);
+ if (!ret && !adc_raw_to_uV(dev, data, &uV))
+ printf("%u, %d uV\n", data, uV);
+ else
+ printf("%u\n", data);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_adc_scan(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct adc_channel ch[ADC_MAX_CHANNEL];
+ struct udevice *dev;
+ unsigned int ch_mask;
+ int i, chan, ret, uV;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ ret = uclass_get_device_by_name(UCLASS_ADC, argv[1], &dev);
+ if (ret) {
+ pr_err("Can't get the ADC %s: %d\n", argv[1], ret);
+ return CMD_RET_FAILURE;
+ }
+
+ switch (argc) {
+ case 3:
+ ch_mask = simple_strtoul(argv[2], NULL, 0);
+ if (ch_mask)
+ break;
+ case 2:
+ ret = adc_channel_mask(dev, &ch_mask);
+ if (ret) {
+ pr_err("Can't get mask for %s: %d\n", dev->name, ret);
+ return CMD_RET_FAILURE;
+ }
+ break;
+ }
+
+ ret = adc_channels_single_shot(dev->name, ch_mask, ch);
+ if (ret) {
+ pr_err("Can't get single shot for %s (chans mask: 0x%x): %d\n",
+ dev->name, ch_mask, ret);
+ return CMD_RET_FAILURE;
+ }
+
+ for (chan = 0, i = 0; chan < ADC_MAX_CHANNEL; chan++) {
+ if (!(ch_mask & ADC_CHANNEL(chan)))
+ continue;
+ if (!adc_raw_to_uV(dev, ch[i].data, &uV))
+ printf("[%02d]: %u, %d uV\n", ch[i].id, ch[i].data, uV);
+ else
+ printf("[%02d]: %u\n", ch[i].id, ch[i].data);
+ i++;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static char adc_help_text[] =
+ "list - list ADC devices\n"
+ "adc info <name> - Get ADC device info\n"
+ "adc single <name> <channel> - Get Single data of ADC device channel\n"
+ "adc scan <name> [channel mask] - Scan all [or masked] ADC channels";
+
+U_BOOT_CMD_WITH_SUBCMDS(adc, "ADC sub-system", adc_help_text,
+ U_BOOT_SUBCMD_MKENT(list, 1, 1, do_adc_list),
+ U_BOOT_SUBCMD_MKENT(info, 2, 1, do_adc_info),
+ U_BOOT_SUBCMD_MKENT(single, 3, 1, do_adc_single),
+ U_BOOT_SUBCMD_MKENT(scan, 3, 1, do_adc_scan));
diff --git a/roms/u-boot/cmd/addrmap.c b/roms/u-boot/cmd/addrmap.c
new file mode 100644
index 000000000..bd23549f3
--- /dev/null
+++ b/roms/u-boot/cmd/addrmap.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <addr_map.h>
+
+static int do_addrmap(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int i;
+
+ printf(" vaddr paddr size\n");
+ printf("================ ================ ================\n");
+
+ for (i = 0; i < CONFIG_SYS_NUM_ADDR_MAP; i++) {
+ if (address_map[i].size == 0)
+ continue;
+
+ printf("%16.8lx %16.8llx %16.8llx\n",
+ address_map[i].vaddr,
+ (unsigned long long)address_map[i].paddr,
+ (unsigned long long)address_map[i].size);
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ addrmap, 1, 1, do_addrmap,
+ "List non-identity virtual-physical memory mappings for 32-bit CPUs",
+ ""
+);
diff --git a/roms/u-boot/cmd/adtimg.c b/roms/u-boot/cmd/adtimg.c
new file mode 100644
index 000000000..aa943007f
--- /dev/null
+++ b/roms/u-boot/cmd/adtimg.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018 Linaro Ltd.
+ * Sam Protsenko <semen.protsenko@linaro.org>
+ * Eugeniu Rosca <rosca.eugeniu@gmail.com>
+ */
+
+#include <command.h>
+#include <env.h>
+#include <image-android-dt.h>
+#include <common.h>
+
+#define OPT_INDEX "--index"
+
+/*
+ * Current/working DTB/DTBO Android image address.
+ * Similar to 'working_fdt' variable in 'fdt' command.
+ */
+static ulong working_img;
+
+static int do_adtimg_addr(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *endp;
+ ulong hdr_addr;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ hdr_addr = simple_strtoul(argv[1], &endp, 16);
+ if (*endp != '\0') {
+ printf("Error: Wrong image address '%s'\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ /*
+ * Allow users to set an address prior to copying the DTB/DTBO
+ * image to that same address, i.e. skip header verification.
+ */
+
+ working_img = hdr_addr;
+ return CMD_RET_SUCCESS;
+}
+
+static int adtimg_check_working_img(void)
+{
+ if (!working_img) {
+ printf("Error: Please, call 'adtimg addr <addr>'. Aborting!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!android_dt_check_header(working_img)) {
+ printf("Error: Invalid image header at 0x%lx\n", working_img);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_adtimg_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ if (adtimg_check_working_img() != CMD_RET_SUCCESS)
+ return CMD_RET_FAILURE;
+
+ android_dt_print_contents(working_img);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int adtimg_getopt_u32(char * const opt, char * const name, u32 *optval)
+{
+ char *endp, *str;
+ u32 val;
+
+ if (!opt || !name || !optval)
+ return CMD_RET_FAILURE;
+
+ str = strchr(opt, '=');
+ if (!str) {
+ printf("Error: Option '%s' not followed by '='\n", name);
+ return CMD_RET_FAILURE;
+ }
+
+ if (*++str == '\0') {
+ printf("Error: Option '%s=' not followed by value\n", name);
+ return CMD_RET_FAILURE;
+ }
+
+ val = simple_strtoul(str, &endp, 0);
+ if (*endp != '\0') {
+ printf("Error: Wrong integer value '%s=%s'\n", name, str);
+ return CMD_RET_FAILURE;
+ }
+
+ *optval = val;
+ return CMD_RET_SUCCESS;
+}
+
+static int adtimg_getopt_index(int argc, char *const argv[], u32 *index,
+ char **avar, char **svar)
+{
+ int ret;
+
+ if (!argv || !avar || !svar)
+ return CMD_RET_FAILURE;
+
+ if (argc > 3) {
+ printf("Error: Unexpected argument '%s'\n", argv[3]);
+ return CMD_RET_FAILURE;
+ }
+
+ ret = adtimg_getopt_u32(argv[0], OPT_INDEX, index);
+ if (ret != CMD_RET_SUCCESS)
+ return ret;
+
+ if (argc > 1)
+ *avar = argv[1];
+ if (argc > 2)
+ *svar = argv[2];
+
+ return CMD_RET_SUCCESS;
+}
+
+static int adtimg_get_dt_by_index(int argc, char *const argv[])
+{
+ ulong addr;
+ u32 index, size;
+ int ret;
+ char *avar = NULL, *svar = NULL;
+
+ ret = adtimg_getopt_index(argc, argv, &index, &avar, &svar);
+ if (ret != CMD_RET_SUCCESS)
+ return ret;
+
+ if (!android_dt_get_fdt_by_index(working_img, index, &addr, &size))
+ return CMD_RET_FAILURE;
+
+ if (avar && svar) {
+ ret = env_set_hex(avar, addr);
+ if (ret) {
+ printf("Error: Can't set '%s' to 0x%lx\n", avar, addr);
+ return CMD_RET_FAILURE;
+ }
+ ret = env_set_hex(svar, size);
+ if (ret) {
+ printf("Error: Can't set '%s' to 0x%x\n", svar, size);
+ return CMD_RET_FAILURE;
+ }
+ } else if (avar) {
+ ret = env_set_hex(avar, addr);
+ if (ret) {
+ printf("Error: Can't set '%s' to 0x%lx\n", avar, addr);
+ return CMD_RET_FAILURE;
+ }
+ printf("0x%x (%d)\n", size, size);
+ } else {
+ printf("0x%lx, 0x%x (%d)\n", addr, size, size);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int adtimg_get_dt(int argc, char *const argv[])
+{
+ if (argc < 2) {
+ printf("Error: No options passed to '%s'\n", argv[0]);
+ return CMD_RET_FAILURE;
+ }
+
+ /* Strip off leading 'dt' command argument */
+ argc--;
+ argv++;
+
+ if (!strncmp(argv[0], OPT_INDEX, sizeof(OPT_INDEX) - 1))
+ return adtimg_get_dt_by_index(argc, argv);
+
+ printf("Error: Option '%s' not supported\n", argv[0]);
+ return CMD_RET_FAILURE;
+}
+
+static int do_adtimg_get(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc < 2) {
+ printf("Error: No arguments passed to '%s'\n", argv[0]);
+ return CMD_RET_FAILURE;
+ }
+
+ if (adtimg_check_working_img() != CMD_RET_SUCCESS)
+ return CMD_RET_FAILURE;
+
+ /* Strip off leading 'get' command argument */
+ argc--;
+ argv++;
+
+ if (!strcmp(argv[0], "dt"))
+ return adtimg_get_dt(argc, argv);
+
+ printf("Error: Wrong argument '%s'\n", argv[0]);
+ return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_adtimg_sub[] = {
+ U_BOOT_CMD_MKENT(addr, CONFIG_SYS_MAXARGS, 1, do_adtimg_addr, "", ""),
+ U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_adtimg_dump, "", ""),
+ U_BOOT_CMD_MKENT(get, CONFIG_SYS_MAXARGS, 1, do_adtimg_get, "", ""),
+};
+
+static int do_adtimg(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ cp = find_cmd_tbl(argv[1], cmd_adtimg_sub, ARRAY_SIZE(cmd_adtimg_sub));
+
+ /* Strip off leading 'adtimg' command argument */
+ argc--;
+ argv++;
+
+ if (!cp || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+ if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+ return CMD_RET_SUCCESS;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ adtimg, CONFIG_SYS_MAXARGS, 0, do_adtimg,
+ "manipulate dtb/dtbo Android image",
+ "addr <addr> - Set image location to <addr>\n"
+ "adtimg dump - Print out image contents\n"
+ "adtimg get dt --index=<index> [avar [svar]] - Get DT address/size by index\n"
+ "\n"
+ "Legend:\n"
+ " - <addr>: DTB/DTBO image address (hex) in RAM\n"
+ " - <index>: index (hex/dec) of desired DT in the image\n"
+ " - <avar>: variable name to contain DT address (hex)\n"
+ " - <svar>: variable name to contain DT size (hex)"
+);
diff --git a/roms/u-boot/cmd/aes.c b/roms/u-boot/cmd/aes.c
new file mode 100644
index 000000000..4c0dad993
--- /dev/null
+++ b/roms/u-boot/cmd/aes.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014 Marek Vasut <marex@denx.de>
+ *
+ * Command for en/de-crypting block of memory with AES-[128/192/256]-CBC cipher.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <uboot_aes.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <linux/compiler.h>
+#include <mapmem.h>
+
+u32 aes_get_key_len(char *command)
+{
+ u32 key_len = AES128_KEY_LENGTH;
+
+ if (!strcmp(command, "aes.192"))
+ key_len = AES192_KEY_LENGTH;
+ else if (!strcmp(command, "aes.256"))
+ key_len = AES256_KEY_LENGTH;
+
+ return key_len;
+}
+
+/**
+ * do_aes() - Handle the "aes" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_aes(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ uint32_t key_addr, iv_addr, src_addr, dst_addr, len;
+ uint8_t *key_ptr, *iv_ptr, *src_ptr, *dst_ptr;
+ u8 key_exp[AES256_EXPAND_KEY_LENGTH];
+ u32 aes_blocks, key_len;
+ int enc;
+
+ if (argc != 7)
+ return CMD_RET_USAGE;
+
+ key_len = aes_get_key_len(argv[0]);
+
+ if (!strncmp(argv[1], "enc", 3))
+ enc = 1;
+ else if (!strncmp(argv[1], "dec", 3))
+ enc = 0;
+ else
+ return CMD_RET_USAGE;
+
+ key_addr = simple_strtoul(argv[2], NULL, 16);
+ iv_addr = simple_strtoul(argv[3], NULL, 16);
+ src_addr = simple_strtoul(argv[4], NULL, 16);
+ dst_addr = simple_strtoul(argv[5], NULL, 16);
+ len = simple_strtoul(argv[6], NULL, 16);
+
+ key_ptr = (uint8_t *)map_sysmem(key_addr, key_len);
+ iv_ptr = (uint8_t *)map_sysmem(iv_addr, 128 / 8);
+ src_ptr = (uint8_t *)map_sysmem(src_addr, len);
+ dst_ptr = (uint8_t *)map_sysmem(dst_addr, len);
+
+ /* First we expand the key. */
+ aes_expand_key(key_ptr, key_len, key_exp);
+
+ /* Calculate the number of AES blocks to encrypt. */
+ aes_blocks = DIV_ROUND_UP(len, AES_BLOCK_LENGTH);
+
+ if (enc)
+ aes_cbc_encrypt_blocks(key_len, key_exp, iv_ptr, src_ptr,
+ dst_ptr, aes_blocks);
+ else
+ aes_cbc_decrypt_blocks(key_len, key_exp, iv_ptr, src_ptr,
+ dst_ptr, aes_blocks);
+
+ unmap_sysmem(key_ptr);
+ unmap_sysmem(iv_ptr);
+ unmap_sysmem(src_ptr);
+ unmap_sysmem(dst_ptr);
+
+ return 0;
+}
+
+/***************************************************/
+#ifdef CONFIG_SYS_LONGHELP
+static char aes_help_text[] =
+ "[.128,.192,.256] enc key iv src dst len - Encrypt block of data $len bytes long\n"
+ " at address $src using a key at address\n"
+ " $key with initialization vector at address\n"
+ " $iv. Store the result at address $dst.\n"
+ " The $len size must be multiple of 16 bytes.\n"
+ " The $key and $iv must be 16 bytes long.\n"
+ "aes [.128,.192,.256] dec key iv src dst len - Decrypt block of data $len bytes long\n"
+ " at address $src using a key at address\n"
+ " $key with initialization vector at address\n"
+ " $iv. Store the result at address $dst.\n"
+ " The $len size must be multiple of 16 bytes.\n"
+ " The $key and $iv must be 16 bytes long.";
+#endif
+
+U_BOOT_CMD(
+ aes, 7, 1, do_aes,
+ "AES 128/192/256 CBC encryption",
+ aes_help_text
+);
diff --git a/roms/u-boot/cmd/arm/Makefile b/roms/u-boot/cmd/arm/Makefile
new file mode 100644
index 000000000..94367dcb4
--- /dev/null
+++ b/roms/u-boot/cmd/arm/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+ifdef CONFIG_ARM64
+obj-$(CONFIG_CMD_EXCEPTION) += exception64.o
+else
+obj-$(CONFIG_CMD_EXCEPTION) += exception.o
+endif
diff --git a/roms/u-boot/cmd/arm/exception.c b/roms/u-boot/cmd/arm/exception.c
new file mode 100644
index 000000000..522f6dff5
--- /dev/null
+++ b/roms/u-boot/cmd/arm/exception.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The 'exception' command can be used for testing exception handling.
+ *
+ * Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_unaligned(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ /*
+ * The LDRD instruction requires the data source to be four byte aligned
+ * even if strict alignment fault checking is disabled in the system
+ * control register.
+ */
+ asm volatile (
+ "MOV r5, sp\n"
+ "ADD r5, #1\n"
+ "LDRD r6, r7, [r5]\n");
+ return CMD_RET_FAILURE;
+}
+
+static int do_breakpoint(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ asm volatile ("BKPT #123\n");
+ return CMD_RET_FAILURE;
+}
+
+static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ /*
+ * 0xe7f...f. is undefined in ARM mode
+ * 0xde.. is undefined in Thumb mode
+ */
+ asm volatile (".word 0xe7f7defb\n");
+ return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_sub[] = {
+ U_BOOT_CMD_MKENT(breakpoint, CONFIG_SYS_MAXARGS, 1, do_breakpoint,
+ "", ""),
+ U_BOOT_CMD_MKENT(unaligned, CONFIG_SYS_MAXARGS, 1, do_unaligned,
+ "", ""),
+ U_BOOT_CMD_MKENT(undefined, CONFIG_SYS_MAXARGS, 1, do_undefined,
+ "", ""),
+};
+
+static char exception_help_text[] =
+ "<ex>\n"
+ " The following exceptions are available:\n"
+ " breakpoint - prefetch abort\n"
+ " unaligned - data abort\n"
+ " undefined - undefined instruction\n"
+ ;
+
+#include <exception.h>
diff --git a/roms/u-boot/cmd/arm/exception64.c b/roms/u-boot/cmd/arm/exception64.c
new file mode 100644
index 000000000..d5de50a08
--- /dev/null
+++ b/roms/u-boot/cmd/arm/exception64.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The 'exception' command can be used for testing exception handling.
+ *
+ * Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ /*
+ * 0xe7f...f. is undefined in ARM mode
+ * 0xde.. is undefined in Thumb mode
+ */
+ asm volatile (".word 0xe7f7defb\n");
+ return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_sub[] = {
+ U_BOOT_CMD_MKENT(undefined, CONFIG_SYS_MAXARGS, 1, do_undefined,
+ "", ""),
+};
+
+static char exception_help_text[] =
+ "<ex>\n"
+ " The following exceptions are available:\n"
+ " undefined - undefined instruction\n"
+ ;
+
+#include <exception.h>
diff --git a/roms/u-boot/cmd/armflash.c b/roms/u-boot/cmd/armflash.c
new file mode 100644
index 000000000..5e7315eb7
--- /dev/null
+++ b/roms/u-boot/cmd/armflash.c
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015
+ * Linus Walleij, Linaro
+ *
+ * Support for ARM Flash Partitions
+ */
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <flash.h>
+#include <asm/io.h>
+
+#define MAX_REGIONS 4
+#define MAX_IMAGES 32
+
+struct afs_region {
+ u32 load_address;
+ u32 size;
+ u32 offset;
+};
+
+struct afs_image {
+ flash_info_t *flinfo;
+ const char *name;
+ u32 version;
+ u32 entrypoint;
+ u32 attributes;
+ u32 region_count;
+ struct afs_region regions[MAX_REGIONS];
+ ulong flash_mem_start;
+ ulong flash_mem_end;
+};
+
+static struct afs_image afs_images[MAX_IMAGES];
+static int num_afs_images;
+
+static u32 compute_crc(ulong start, u32 len)
+{
+ u32 sum = 0;
+ int i;
+
+ if (len % 4 != 0) {
+ printf("bad checksumming\n");
+ return 0;
+ }
+
+ for (i = 0; i < len; i += 4) {
+ u32 val;
+
+ val = readl((void *)start + i);
+ if (val > ~sum)
+ sum++;
+ sum += val;
+ }
+ return ~sum;
+}
+
+static void parse_bank(ulong bank)
+{
+ int i;
+ ulong flstart, flend;
+ flash_info_t *info;
+
+ info = &flash_info[bank];
+ if (info->flash_id != FLASH_MAN_CFI) {
+ printf("Bank %lu: missing or unknown FLASH type\n", bank);
+ return;
+ }
+ if (!info->sector_count) {
+ printf("Bank %lu: no FLASH sectors\n", bank);
+ return;
+ }
+
+ flstart = info->start[0];
+ flend = flstart + info->size;
+
+ for (i = 0; i < info->sector_count; ++i) {
+ ulong secend;
+ u32 foot1, foot2;
+
+ if (ctrlc())
+ break;
+
+ if (i == info->sector_count-1)
+ secend = flend;
+ else
+ secend = info->start[i+1];
+
+ /* Check for v1 header */
+ foot1 = readl((void *)secend - 0x0c);
+ if (foot1 == 0xA0FFFF9FU) {
+ struct afs_image *afi = &afs_images[num_afs_images];
+ ulong imginfo;
+
+ afi->flinfo = info;
+ afi->version = 1;
+ afi->flash_mem_start = readl((void *)secend - 0x10);
+ afi->flash_mem_end = readl((void *)secend - 0x14);
+ afi->attributes = readl((void *)secend - 0x08);
+ /* Adjust to even address */
+ imginfo = afi->flash_mem_end + afi->flash_mem_end % 4;
+ /* Record as a single region */
+ afi->region_count = 1;
+ afi->regions[0].offset = readl((void *)imginfo + 0x04);
+ afi->regions[0].load_address =
+ readl((void *)imginfo + 0x08);
+ afi->regions[0].size = readl((void *)imginfo + 0x0C);
+ afi->entrypoint = readl((void *)imginfo + 0x10);
+ afi->name = (const char *)imginfo + 0x14;
+ num_afs_images++;
+ }
+
+ /* Check for v2 header */
+ foot1 = readl((void *)secend - 0x04);
+ foot2 = readl((void *)secend - 0x08);
+ /* This makes up the string "HSLFTOOF" flash footer */
+ if (foot1 == 0x464F4F54U && foot2 == 0x464C5348U) {
+ struct afs_image *afi = &afs_images[num_afs_images];
+ ulong imginfo;
+ u32 block_start, block_end;
+ int j;
+
+ afi->flinfo = info;
+ afi->version = readl((void *)secend - 0x0c);
+ imginfo = secend - 0x30 - readl((void *)secend - 0x10);
+ afi->name = (const char *)secend - 0x30;
+
+ afi->entrypoint = readl((void *)imginfo+0x08);
+ afi->attributes = readl((void *)imginfo+0x0c);
+ afi->region_count = readl((void *)imginfo+0x10);
+ block_start = readl((void *)imginfo+0x54);
+ block_end = readl((void *)imginfo+0x58);
+ afi->flash_mem_start = afi->flinfo->start[block_start];
+ afi->flash_mem_end = afi->flinfo->start[block_end];
+
+ /*
+ * Check footer CRC, the algorithm saves the inverse
+ * checksum as part of the summed words, and thus
+ * the result should be zero.
+ */
+ if (compute_crc(imginfo + 8, 0x88) != 0) {
+ printf("BAD CRC on ARM image info\n");
+ printf("(continuing anyway)\n");
+ }
+
+ /* Parse regions */
+ for (j = 0; j < afi->region_count; j++) {
+ afi->regions[j].load_address =
+ readl((void *)imginfo+0x14 + j*0x10);
+ afi->regions[j].size =
+ readl((void *)imginfo+0x18 + j*0x10);
+ afi->regions[j].offset =
+ readl((void *)imginfo+0x1c + j*0x10);
+ /*
+ * At offset 0x20 + j*0x10 there is a region
+ * checksum which seems to be the running
+ * sum + 3, however since we anyway checksum
+ * the entire footer this is skipped over for
+ * checking here.
+ */
+ }
+ num_afs_images++;
+ }
+ }
+}
+
+static void parse_flash(void)
+{
+ ulong bank;
+
+ /* We have already parsed the images in flash */
+ if (num_afs_images > 0)
+ return;
+ for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank)
+ parse_bank(bank);
+}
+
+static int load_image(const char * const name, const ulong address)
+{
+ struct afs_image *afi = NULL;
+ int i;
+
+ parse_flash();
+ for (i = 0; i < num_afs_images; i++) {
+ struct afs_image *tmp = &afs_images[i];
+
+ if (!strcmp(tmp->name, name)) {
+ afi = tmp;
+ break;
+ }
+ }
+ if (!afi) {
+ printf("image \"%s\" not found in flash\n", name);
+ return CMD_RET_FAILURE;
+ }
+
+ for (i = 0; i < afi->region_count; i++) {
+ ulong from, to;
+
+ from = afi->flash_mem_start + afi->regions[i].offset;
+ if (address) {
+ to = address;
+ } else if (afi->regions[i].load_address) {
+ to = afi->regions[i].load_address;
+ } else {
+ printf("no valid load address\n");
+ return CMD_RET_FAILURE;
+ }
+
+ memcpy((void *)to, (void *)from, afi->regions[i].size);
+
+ printf("loaded region %d from %08lX to %08lX, %08X bytes\n",
+ i,
+ from,
+ to,
+ afi->regions[i].size);
+ }
+ return CMD_RET_SUCCESS;
+}
+
+static void print_images(void)
+{
+ int i;
+
+ parse_flash();
+ for (i = 0; i < num_afs_images; i++) {
+ struct afs_image *afi = &afs_images[i];
+ int j;
+
+ printf("Image: \"%s\" (v%d):\n", afi->name, afi->version);
+ printf(" Entry point: 0x%08X\n", afi->entrypoint);
+ printf(" Attributes: 0x%08X: ", afi->attributes);
+ if (afi->attributes == 0x01)
+ printf("ARM executable");
+ if (afi->attributes == 0x08)
+ printf("ARM backup");
+ printf("\n");
+ printf(" Flash mem start: 0x%08lX\n",
+ afi->flash_mem_start);
+ printf(" Flash mem end: 0x%08lX\n",
+ afi->flash_mem_end);
+ for (j = 0; j < afi->region_count; j++) {
+ printf(" region %d\n"
+ " load address: %08X\n"
+ " size: %08X\n"
+ " offset: %08X\n",
+ j,
+ afi->regions[j].load_address,
+ afi->regions[j].size,
+ afi->regions[j].offset);
+ }
+ }
+}
+
+static int exists(const char * const name)
+{
+ int i;
+
+ parse_flash();
+ for (i = 0; i < num_afs_images; i++) {
+ struct afs_image *afi = &afs_images[i];
+
+ if (strcmp(afi->name, name) == 0)
+ return CMD_RET_SUCCESS;
+ }
+ return CMD_RET_FAILURE;
+}
+
+static int do_afs(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int ret = CMD_RET_SUCCESS;
+
+ if (argc == 1) {
+ print_images();
+ } else if (argc == 3 && !strcmp(argv[1], "exists")) {
+ ret = exists(argv[2]);
+ } else if (argc == 3 && !strcmp(argv[1], "load")) {
+ ret = load_image(argv[2], 0x0);
+ } else if (argc == 4 && !strcmp(argv[1], "load")) {
+ ulong load_addr;
+
+ load_addr = simple_strtoul(argv[3], NULL, 16);
+ ret = load_image(argv[2], load_addr);
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ return ret;
+}
+
+U_BOOT_CMD(afs, 4, 0, do_afs, "show AFS partitions",
+ "no arguments\n"
+ " - list images in flash\n"
+ "exists <image>\n"
+ " - returns 1 if an image exists, else 0\n"
+ "load <image>\n"
+ " - load an image to the location indicated in the header\n"
+ "load <image> 0x<address>\n"
+ " - load an image to the location specified\n");
diff --git a/roms/u-boot/cmd/avb.c b/roms/u-boot/cmd/avb.c
new file mode 100644
index 000000000..88172a9ee
--- /dev/null
+++ b/roms/u-boot/cmd/avb.c
@@ -0,0 +1,476 @@
+
+/*
+ * (C) Copyright 2018, Linaro Limited
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <avb_verify.h>
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <malloc.h>
+#include <mmc.h>
+
+#define AVB_BOOTARGS "avb_bootargs"
+static struct AvbOps *avb_ops;
+
+int do_avb_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned long mmc_dev;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ mmc_dev = simple_strtoul(argv[1], NULL, 16);
+
+ if (avb_ops)
+ avb_ops_free(avb_ops);
+
+ avb_ops = avb_ops_alloc(mmc_dev);
+ if (avb_ops)
+ return CMD_RET_SUCCESS;
+
+ printf("Failed to initialize avb2\n");
+
+ return CMD_RET_FAILURE;
+}
+
+int do_avb_read_part(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *part;
+ s64 offset;
+ size_t bytes, bytes_read = 0;
+ void *buffer;
+
+ if (!avb_ops) {
+ printf("AVB 2.0 is not initialized, please run 'avb init'\n");
+ return CMD_RET_USAGE;
+ }
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ part = argv[1];
+ offset = simple_strtoul(argv[2], NULL, 16);
+ bytes = simple_strtoul(argv[3], NULL, 16);
+ buffer = (void *)simple_strtoul(argv[4], NULL, 16);
+
+ if (avb_ops->read_from_partition(avb_ops, part, offset, bytes,
+ buffer, &bytes_read) ==
+ AVB_IO_RESULT_OK) {
+ printf("Read %zu bytes\n", bytes_read);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Failed to read from partition\n");
+
+ return CMD_RET_FAILURE;
+}
+
+int do_avb_read_part_hex(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *part;
+ s64 offset;
+ size_t bytes, bytes_read = 0;
+ char *buffer;
+
+ if (!avb_ops) {
+ printf("AVB 2.0 is not initialized, please run 'avb init'\n");
+ return CMD_RET_USAGE;
+ }
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ part = argv[1];
+ offset = simple_strtoul(argv[2], NULL, 16);
+ bytes = simple_strtoul(argv[3], NULL, 16);
+
+ buffer = malloc(bytes);
+ if (!buffer) {
+ printf("Failed to tlb_allocate buffer for data\n");
+ return CMD_RET_FAILURE;
+ }
+ memset(buffer, 0, bytes);
+
+ if (avb_ops->read_from_partition(avb_ops, part, offset, bytes, buffer,
+ &bytes_read) == AVB_IO_RESULT_OK) {
+ printf("Requested %zu, read %zu bytes\n", bytes, bytes_read);
+ printf("Data: ");
+ for (int i = 0; i < bytes_read; i++)
+ printf("%02X", buffer[i]);
+
+ printf("\n");
+
+ free(buffer);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Failed to read from partition\n");
+
+ free(buffer);
+ return CMD_RET_FAILURE;
+}
+
+int do_avb_write_part(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *part;
+ s64 offset;
+ size_t bytes;
+ void *buffer;
+
+ if (!avb_ops) {
+ printf("AVB 2.0 is not initialized, run 'avb init' first\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ part = argv[1];
+ offset = simple_strtoul(argv[2], NULL, 16);
+ bytes = simple_strtoul(argv[3], NULL, 16);
+ buffer = (void *)simple_strtoul(argv[4], NULL, 16);
+
+ if (avb_ops->write_to_partition(avb_ops, part, offset, bytes, buffer) ==
+ AVB_IO_RESULT_OK) {
+ printf("Wrote %zu bytes\n", bytes);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Failed to write in partition\n");
+
+ return CMD_RET_FAILURE;
+}
+
+int do_avb_read_rb(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ size_t index;
+ u64 rb_idx;
+
+ if (!avb_ops) {
+ printf("AVB 2.0 is not initialized, run 'avb init' first\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ index = (size_t)simple_strtoul(argv[1], NULL, 16);
+
+ if (avb_ops->read_rollback_index(avb_ops, index, &rb_idx) ==
+ AVB_IO_RESULT_OK) {
+ printf("Rollback index: %llx\n", rb_idx);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Failed to read rollback index\n");
+
+ return CMD_RET_FAILURE;
+}
+
+int do_avb_write_rb(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ size_t index;
+ u64 rb_idx;
+
+ if (!avb_ops) {
+ printf("AVB 2.0 is not initialized, run 'avb init' first\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ index = (size_t)simple_strtoul(argv[1], NULL, 16);
+ rb_idx = simple_strtoul(argv[2], NULL, 16);
+
+ if (avb_ops->write_rollback_index(avb_ops, index, rb_idx) ==
+ AVB_IO_RESULT_OK)
+ return CMD_RET_SUCCESS;
+
+ printf("Failed to write rollback index\n");
+
+ return CMD_RET_FAILURE;
+}
+
+int do_avb_get_uuid(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ const char *part;
+ char buffer[UUID_STR_LEN + 1];
+
+ if (!avb_ops) {
+ printf("AVB 2.0 is not initialized, run 'avb init' first\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ part = argv[1];
+
+ if (avb_ops->get_unique_guid_for_partition(avb_ops, part, buffer,
+ UUID_STR_LEN + 1) ==
+ AVB_IO_RESULT_OK) {
+ printf("'%s' UUID: %s\n", part, buffer);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Failed to read UUID\n");
+
+ return CMD_RET_FAILURE;
+}
+
+int do_avb_verify_part(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ const char * const requested_partitions[] = {"boot", NULL};
+ AvbSlotVerifyResult slot_result;
+ AvbSlotVerifyData *out_data;
+ char *cmdline;
+ char *extra_args;
+ char *slot_suffix = "";
+
+ bool unlocked = false;
+ int res = CMD_RET_FAILURE;
+
+ if (!avb_ops) {
+ printf("AVB 2.0 is not initialized, run 'avb init' first\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc < 1 || argc > 2)
+ return CMD_RET_USAGE;
+
+ if (argc == 2)
+ slot_suffix = argv[1];
+
+ printf("## Android Verified Boot 2.0 version %s\n",
+ avb_version_string());
+
+ if (avb_ops->read_is_device_unlocked(avb_ops, &unlocked) !=
+ AVB_IO_RESULT_OK) {
+ printf("Can't determine device lock state.\n");
+ return CMD_RET_FAILURE;
+ }
+
+ slot_result =
+ avb_slot_verify(avb_ops,
+ requested_partitions,
+ slot_suffix,
+ unlocked,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+ &out_data);
+
+ switch (slot_result) {
+ case AVB_SLOT_VERIFY_RESULT_OK:
+ /* Until we don't have support of changing unlock states, we
+ * assume that we are by default in locked state.
+ * So in this case we can boot only when verification is
+ * successful; we also supply in cmdline GREEN boot state
+ */
+ printf("Verification passed successfully\n");
+
+ /* export additional bootargs to AVB_BOOTARGS env var */
+
+ extra_args = avb_set_state(avb_ops, AVB_GREEN);
+ if (extra_args)
+ cmdline = append_cmd_line(out_data->cmdline,
+ extra_args);
+ else
+ cmdline = out_data->cmdline;
+
+ env_set(AVB_BOOTARGS, cmdline);
+
+ res = CMD_RET_SUCCESS;
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+ printf("Verification failed\n");
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_IO:
+ printf("I/O error occurred during verification\n");
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_OOM:
+ printf("OOM error occurred during verification\n");
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
+ printf("Corrupted dm-verity metadata detected\n");
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
+ printf("Unsupported version avbtool was used\n");
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX:
+ printf("Checking rollback index failed\n");
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
+ printf("Public key was rejected\n");
+ break;
+ default:
+ printf("Unknown error occurred\n");
+ }
+
+ if (out_data)
+ avb_slot_verify_data_free(out_data);
+
+ return res;
+}
+
+int do_avb_is_unlocked(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ bool unlock;
+
+ if (!avb_ops) {
+ printf("AVB not initialized, run 'avb init' first\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc != 1) {
+ printf("--%s(-1)\n", __func__);
+ return CMD_RET_USAGE;
+ }
+
+ if (avb_ops->read_is_device_unlocked(avb_ops, &unlock) ==
+ AVB_IO_RESULT_OK) {
+ printf("Unlocked = %d\n", unlock);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Can't determine device lock state.\n");
+
+ return CMD_RET_FAILURE;
+}
+
+int do_avb_read_pvalue(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *name;
+ size_t bytes;
+ size_t bytes_read;
+ void *buffer;
+ char *endp;
+
+ if (!avb_ops) {
+ printf("AVB 2.0 is not initialized, run 'avb init' first\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ name = argv[1];
+ bytes = simple_strtoul(argv[2], &endp, 10);
+ if (*endp && *endp != '\n')
+ return CMD_RET_USAGE;
+
+ buffer = malloc(bytes);
+ if (!buffer)
+ return CMD_RET_FAILURE;
+
+ if (avb_ops->read_persistent_value(avb_ops, name, bytes, buffer,
+ &bytes_read) == AVB_IO_RESULT_OK) {
+ printf("Read %zu bytes, value = %s\n", bytes_read,
+ (char *)buffer);
+ free(buffer);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Failed to read persistent value\n");
+
+ free(buffer);
+
+ return CMD_RET_FAILURE;
+}
+
+int do_avb_write_pvalue(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *name;
+ const char *value;
+
+ if (!avb_ops) {
+ printf("AVB 2.0 is not initialized, run 'avb init' first\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ name = argv[1];
+ value = argv[2];
+
+ if (avb_ops->write_persistent_value(avb_ops, name, strlen(value) + 1,
+ (const uint8_t *)value) ==
+ AVB_IO_RESULT_OK) {
+ printf("Wrote %zu bytes\n", strlen(value) + 1);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Failed to write persistent value\n");
+
+ return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_avb[] = {
+ U_BOOT_CMD_MKENT(init, 2, 0, do_avb_init, "", ""),
+ U_BOOT_CMD_MKENT(read_rb, 2, 0, do_avb_read_rb, "", ""),
+ U_BOOT_CMD_MKENT(write_rb, 3, 0, do_avb_write_rb, "", ""),
+ U_BOOT_CMD_MKENT(is_unlocked, 1, 0, do_avb_is_unlocked, "", ""),
+ U_BOOT_CMD_MKENT(get_uuid, 2, 0, do_avb_get_uuid, "", ""),
+ U_BOOT_CMD_MKENT(read_part, 5, 0, do_avb_read_part, "", ""),
+ U_BOOT_CMD_MKENT(read_part_hex, 4, 0, do_avb_read_part_hex, "", ""),
+ U_BOOT_CMD_MKENT(write_part, 5, 0, do_avb_write_part, "", ""),
+ U_BOOT_CMD_MKENT(verify, 2, 0, do_avb_verify_part, "", ""),
+#ifdef CONFIG_OPTEE_TA_AVB
+ U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_avb_read_pvalue, "", ""),
+ U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_avb_write_pvalue, "", ""),
+#endif
+};
+
+static int do_avb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ cp = find_cmd_tbl(argv[1], cmd_avb, ARRAY_SIZE(cmd_avb));
+
+ argc--;
+ argv++;
+
+ if (!cp || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+
+ if (flag == CMD_FLAG_REPEAT)
+ return CMD_RET_FAILURE;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ avb, 29, 0, do_avb,
+ "Provides commands for testing Android Verified Boot 2.0 functionality",
+ "init <dev> - initialize avb2 for <dev>\n"
+ "avb read_rb <num> - read rollback index at location <num>\n"
+ "avb write_rb <num> <rb> - write rollback index <rb> to <num>\n"
+ "avb is_unlocked - returns unlock status of the device\n"
+ "avb get_uuid <partname> - read and print uuid of partition <part>\n"
+ "avb read_part <partname> <offset> <num> <addr> - read <num> bytes from\n"
+ " partition <partname> to buffer <addr>\n"
+ "avb read_part_hex <partname> <offset> <num> - read <num> bytes from\n"
+ " partition <partname> and print to stdout\n"
+ "avb write_part <partname> <offset> <num> <addr> - write <num> bytes to\n"
+ " <partname> by <offset> using data from <addr>\n"
+#ifdef CONFIG_OPTEE_TA_AVB
+ "avb read_pvalue <name> <bytes> - read a persistent value <name>\n"
+ "avb write_pvalue <name> <value> - write a persistent value <name>\n"
+#endif
+ "avb verify [slot_suffix] - run verification process using hash data\n"
+ " from vbmeta structure\n"
+ " [slot_suffix] - _a, _b, etc (if vbmeta partition is slotted)\n"
+ );
diff --git a/roms/u-boot/cmd/axi.c b/roms/u-boot/cmd/axi.c
new file mode 100644
index 000000000..c72197ee8
--- /dev/null
+++ b/roms/u-boot/cmd/axi.c
@@ -0,0 +1,355 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ *
+ * (C) Copyright 2017, 2018
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <axi.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <log.h>
+
+/* Currently selected AXI bus device */
+static struct udevice *axi_cur_bus;
+/* Transmission size from last command */
+static uint dp_last_size;
+/* Address from last command */
+static uint dp_last_addr;
+/* Number of bytes to display from last command; default = 64 */
+static uint dp_last_length = 0x40;
+
+/**
+ * show_bus() - Show devices on a single AXI bus
+ * @bus: The AXI bus device to printt information for
+ */
+static void show_bus(struct udevice *bus)
+{
+ struct udevice *dev;
+
+ printf("Bus %d:\t%s", dev_seq(bus), bus->name);
+ if (device_active(bus))
+ printf(" (active)");
+ printf("\n");
+ for (device_find_first_child(bus, &dev);
+ dev;
+ device_find_next_child(&dev))
+ printf(" %s\n", dev->name);
+}
+
+/**
+ * axi_set_cur_bus() - Set the currently active AXI bus
+ * @busnum: The number of the bus (i.e. its sequence number) that should be
+ * made active
+ *
+ * The operations supplied by this command operate only on the currently active
+ * bus.
+ *
+ * Return: 0 if OK, -ve on error
+ */
+static int axi_set_cur_bus(unsigned int busnum)
+{
+ struct udevice *bus;
+ struct udevice *dummy;
+ int ret;
+
+ /* Make sure that all sequence numbers are initialized */
+ for (uclass_first_device(UCLASS_AXI, &dummy);
+ dummy;
+ uclass_next_device(&dummy))
+ ;
+
+ ret = uclass_get_device_by_seq(UCLASS_AXI, busnum, &bus);
+ if (ret) {
+ debug("%s: No bus %d\n", __func__, busnum);
+ return ret;
+ }
+ axi_cur_bus = bus;
+
+ return 0;
+}
+
+/**
+ * axi_get_cur_bus() - Retrieve the currently active AXI bus device
+ * @busp: Pointer to a struct udevice that receives the currently active bus
+ * device
+ *
+ * Return: 0 if OK, -ve on error
+ */
+static int axi_get_cur_bus(struct udevice **busp)
+{
+ if (!axi_cur_bus) {
+ puts("No AXI bus selected\n");
+ return -ENODEV;
+ }
+ *busp = axi_cur_bus;
+
+ return 0;
+}
+
+/*
+ * Command handlers
+ */
+
+static int do_axi_show_bus(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dummy;
+
+ /* Make sure that all sequence numbers are initialized */
+ for (uclass_first_device(UCLASS_AXI, &dummy);
+ dummy;
+ uclass_next_device(&dummy))
+ ;
+
+ if (argc == 1) {
+ /* show all busses */
+ struct udevice *bus;
+
+ for (uclass_first_device(UCLASS_AXI, &bus);
+ bus;
+ uclass_next_device(&bus))
+ show_bus(bus);
+ } else {
+ int i;
+
+ /* show specific bus */
+ i = simple_strtoul(argv[1], NULL, 10);
+
+ struct udevice *bus;
+ int ret;
+
+ ret = uclass_get_device_by_seq(UCLASS_AXI, i, &bus);
+ if (ret) {
+ printf("Invalid bus %d: err=%d\n", i, ret);
+ return CMD_RET_FAILURE;
+ }
+ show_bus(bus);
+ }
+
+ return 0;
+}
+
+static int do_axi_bus_num(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret = 0;
+ int bus_no;
+
+ if (argc == 1) {
+ /* querying current setting */
+ struct udevice *bus;
+
+ if (!axi_get_cur_bus(&bus))
+ bus_no = dev_seq(bus);
+ else
+ bus_no = -1;
+
+ printf("Current bus is %d\n", bus_no);
+ } else {
+ bus_no = simple_strtoul(argv[1], NULL, 10);
+ printf("Setting bus to %d\n", bus_no);
+
+ ret = axi_set_cur_bus(bus_no);
+ if (ret)
+ printf("Failure changing bus number (%d)\n", ret);
+ }
+
+ return ret ? CMD_RET_FAILURE : 0;
+}
+
+static int do_axi_md(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ /* Print that many bytes per line */
+ const uint DISP_LINE_LEN = 16;
+ u8 linebuf[DISP_LINE_LEN];
+ unsigned int k;
+ ulong addr, length, size;
+ ulong nbytes;
+ enum axi_size_t axisize;
+ int unitsize;
+
+ /*
+ * We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ size = dp_last_size;
+ addr = dp_last_addr;
+ length = dp_last_length;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if (!axi_cur_bus) {
+ puts("No AXI bus selected\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ size = simple_strtoul(argv[1], NULL, 10);
+
+ /*
+ * Address is specified since argc >= 3
+ */
+ addr = simple_strtoul(argv[2], NULL, 16);
+
+ /*
+ * If there's another parameter, it is the length to display;
+ * length is the number of objects, not number of bytes
+ */
+ if (argc > 3)
+ length = simple_strtoul(argv[3], NULL, 16);
+ }
+
+ switch (size) {
+ case 8:
+ axisize = AXI_SIZE_8;
+ unitsize = 1;
+ break;
+ case 16:
+ axisize = AXI_SIZE_16;
+ unitsize = 2;
+ break;
+ case 32:
+ axisize = AXI_SIZE_32;
+ unitsize = 4;
+ break;
+ default:
+ printf("Unknown read size '%lu'\n", size);
+ return CMD_RET_USAGE;
+ };
+
+ nbytes = length * unitsize;
+ do {
+ ulong linebytes = (nbytes > DISP_LINE_LEN) ?
+ DISP_LINE_LEN : nbytes;
+
+ for (k = 0; k < linebytes / unitsize; ++k) {
+ int ret = axi_read(axi_cur_bus, addr + k * unitsize,
+ linebuf + k * unitsize, axisize);
+
+ if (!ret) /* Continue if axi_read was successful */
+ continue;
+
+ if (ret == -ENOSYS)
+ printf("axi_read failed; read size not supported?\n");
+ else
+ printf("axi_read failed: err = %d\n", ret);
+
+ return CMD_RET_FAILURE;
+ }
+ print_buffer(addr, (void *)linebuf, unitsize,
+ linebytes / unitsize,
+ DISP_LINE_LEN / unitsize);
+
+ nbytes -= max(linebytes, 1UL);
+ addr += linebytes;
+
+ if (ctrlc())
+ break;
+ } while (nbytes > 0);
+
+ dp_last_size = size;
+ dp_last_addr = addr;
+ dp_last_length = length;
+
+ return 0;
+}
+
+static int do_axi_mw(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 writeval;
+ ulong addr, count, size;
+ enum axi_size_t axisize;
+
+ if (argc <= 3 || argc >= 6)
+ return CMD_RET_USAGE;
+
+ size = simple_strtoul(argv[1], NULL, 10);
+
+ switch (size) {
+ case 8:
+ axisize = AXI_SIZE_8;
+ break;
+ case 16:
+ axisize = AXI_SIZE_16;
+ break;
+ case 32:
+ axisize = AXI_SIZE_32;
+ break;
+ default:
+ printf("Unknown write size '%lu'\n", size);
+ return CMD_RET_USAGE;
+ };
+
+ /* Address is specified since argc > 4 */
+ addr = simple_strtoul(argv[2], NULL, 16);
+
+ /* Get the value to write */
+ writeval = simple_strtoul(argv[3], NULL, 16);
+
+ /* Count ? */
+ if (argc == 5)
+ count = simple_strtoul(argv[4], NULL, 16);
+ else
+ count = 1;
+
+ while (count-- > 0) {
+ int ret = axi_write(axi_cur_bus, addr + count * sizeof(u32),
+ &writeval, axisize);
+
+ if (ret) {
+ printf("axi_write failed: err = %d\n", ret);
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_axi_sub[] = {
+ U_BOOT_CMD_MKENT(bus, 1, 1, do_axi_show_bus, "", ""),
+ U_BOOT_CMD_MKENT(dev, 1, 1, do_axi_bus_num, "", ""),
+ U_BOOT_CMD_MKENT(md, 4, 1, do_axi_md, "", ""),
+ U_BOOT_CMD_MKENT(mw, 5, 1, do_axi_mw, "", ""),
+};
+
+static int do_ihs_axi(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* Strip off leading 'axi' command argument */
+ argc--;
+ argv++;
+
+ /* Hand off rest of command line to sub-commands */
+ c = find_cmd_tbl(argv[0], &cmd_axi_sub[0], ARRAY_SIZE(cmd_axi_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+static char axi_help_text[] =
+ "bus - show AXI bus info\n"
+ "axi dev [bus] - show or set current AXI bus to bus number [bus]\n"
+ "axi md size addr [# of objects] - read from AXI device at address [addr] and data width [size] (one of 8, 16, 32)\n"
+ "axi mw size addr value [count] - write data [value] to AXI device at address [addr] and data width [size] (one of 8, 16, 32)\n";
+
+U_BOOT_CMD(axi, 7, 1, do_ihs_axi,
+ "AXI sub-system",
+ axi_help_text
+);
diff --git a/roms/u-boot/cmd/bcb.c b/roms/u-boot/cmd/bcb.c
new file mode 100644
index 000000000..6b6f1e9a2
--- /dev/null
+++ b/roms/u-boot/cmd/bcb.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Eugeniu Rosca <rosca.eugeniu@gmail.com>
+ *
+ * Command to read/modify/write Android BCB fields
+ */
+
+#include <android_bootloader_message.h>
+#include <bcb.h>
+#include <command.h>
+#include <common.h>
+#include <log.h>
+#include <part.h>
+#include <malloc.h>
+
+enum bcb_cmd {
+ BCB_CMD_LOAD,
+ BCB_CMD_FIELD_SET,
+ BCB_CMD_FIELD_CLEAR,
+ BCB_CMD_FIELD_TEST,
+ BCB_CMD_FIELD_DUMP,
+ BCB_CMD_STORE,
+};
+
+static int bcb_dev = -1;
+static int bcb_part = -1;
+static struct bootloader_message bcb = { { 0 } };
+
+static int bcb_cmd_get(char *cmd)
+{
+ if (!strcmp(cmd, "load"))
+ return BCB_CMD_LOAD;
+ if (!strcmp(cmd, "set"))
+ return BCB_CMD_FIELD_SET;
+ if (!strcmp(cmd, "clear"))
+ return BCB_CMD_FIELD_CLEAR;
+ if (!strcmp(cmd, "test"))
+ return BCB_CMD_FIELD_TEST;
+ if (!strcmp(cmd, "store"))
+ return BCB_CMD_STORE;
+ if (!strcmp(cmd, "dump"))
+ return BCB_CMD_FIELD_DUMP;
+ else
+ return -1;
+}
+
+static int bcb_is_misused(int argc, char *const argv[])
+{
+ int cmd = bcb_cmd_get(argv[0]);
+
+ switch (cmd) {
+ case BCB_CMD_LOAD:
+ case BCB_CMD_FIELD_SET:
+ if (argc != 3)
+ goto err;
+ break;
+ case BCB_CMD_FIELD_TEST:
+ if (argc != 4)
+ goto err;
+ break;
+ case BCB_CMD_FIELD_CLEAR:
+ if (argc != 1 && argc != 2)
+ goto err;
+ break;
+ case BCB_CMD_STORE:
+ if (argc != 1)
+ goto err;
+ break;
+ case BCB_CMD_FIELD_DUMP:
+ if (argc != 2)
+ goto err;
+ break;
+ default:
+ printf("Error: 'bcb %s' not supported\n", argv[0]);
+ return -1;
+ }
+
+ if (cmd != BCB_CMD_LOAD && (bcb_dev < 0 || bcb_part < 0)) {
+ printf("Error: Please, load BCB first!\n");
+ return -1;
+ }
+
+ return 0;
+err:
+ printf("Error: Bad usage of 'bcb %s'\n", argv[0]);
+
+ return -1;
+}
+
+static int bcb_field_get(char *name, char **fieldp, int *sizep)
+{
+ if (!strcmp(name, "command")) {
+ *fieldp = bcb.command;
+ *sizep = sizeof(bcb.command);
+ } else if (!strcmp(name, "status")) {
+ *fieldp = bcb.status;
+ *sizep = sizeof(bcb.status);
+ } else if (!strcmp(name, "recovery")) {
+ *fieldp = bcb.recovery;
+ *sizep = sizeof(bcb.recovery);
+ } else if (!strcmp(name, "stage")) {
+ *fieldp = bcb.stage;
+ *sizep = sizeof(bcb.stage);
+ } else if (!strcmp(name, "reserved")) {
+ *fieldp = bcb.reserved;
+ *sizep = sizeof(bcb.reserved);
+ } else {
+ printf("Error: Unknown bcb field '%s'\n", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __bcb_load(int devnum, const char *partp)
+{
+ struct blk_desc *desc;
+ struct disk_partition info;
+ u64 cnt;
+ char *endp;
+ int part, ret;
+
+ desc = blk_get_devnum_by_type(IF_TYPE_MMC, devnum);
+ if (!desc) {
+ ret = -ENODEV;
+ goto err_read_fail;
+ }
+
+ part = simple_strtoul(partp, &endp, 0);
+ if (*endp == '\0') {
+ ret = part_get_info(desc, part, &info);
+ if (ret)
+ goto err_read_fail;
+ } else {
+ part = part_get_info_by_name(desc, partp, &info);
+ if (part < 0) {
+ ret = part;
+ goto err_read_fail;
+ }
+ }
+
+ cnt = DIV_ROUND_UP(sizeof(struct bootloader_message), info.blksz);
+ if (cnt > info.size)
+ goto err_too_small;
+
+ if (blk_dread(desc, info.start, cnt, &bcb) != cnt) {
+ ret = -EIO;
+ goto err_read_fail;
+ }
+
+ bcb_dev = desc->devnum;
+ bcb_part = part;
+ debug("%s: Loaded from mmc %d:%d\n", __func__, bcb_dev, bcb_part);
+
+ return CMD_RET_SUCCESS;
+err_read_fail:
+ printf("Error: mmc %d:%s read failed (%d)\n", devnum, partp, ret);
+ goto err;
+err_too_small:
+ printf("Error: mmc %d:%s too small!", devnum, partp);
+ goto err;
+err:
+ bcb_dev = -1;
+ bcb_part = -1;
+
+ return CMD_RET_FAILURE;
+}
+
+static int do_bcb_load(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ char *endp;
+ int devnum = simple_strtoul(argv[1], &endp, 0);
+
+ if (*endp != '\0') {
+ printf("Error: Device id '%s' not a number\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ return __bcb_load(devnum, argv[2]);
+}
+
+static int __bcb_set(char *fieldp, const char *valp)
+{
+ int size, len;
+ char *field, *str, *found, *tmp;
+
+ if (bcb_field_get(fieldp, &field, &size))
+ return CMD_RET_FAILURE;
+
+ len = strlen(valp);
+ if (len >= size) {
+ printf("Error: sizeof('%s') = %d >= %d = sizeof(bcb.%s)\n",
+ valp, len, size, fieldp);
+ return CMD_RET_FAILURE;
+ }
+ str = strdup(valp);
+ if (!str) {
+ printf("Error: Out of memory while strdup\n");
+ return CMD_RET_FAILURE;
+ }
+
+ tmp = str;
+ field[0] = '\0';
+ while ((found = strsep(&tmp, ":"))) {
+ if (field[0] != '\0')
+ strcat(field, "\n");
+ strcat(field, found);
+ }
+ free(str);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_bcb_set(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ return __bcb_set(argv[1], argv[2]);
+}
+
+static int do_bcb_clear(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int size;
+ char *field;
+
+ if (argc == 1) {
+ memset(&bcb, 0, sizeof(bcb));
+ return CMD_RET_SUCCESS;
+ }
+
+ if (bcb_field_get(argv[1], &field, &size))
+ return CMD_RET_FAILURE;
+
+ memset(field, 0, size);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_bcb_test(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int size;
+ char *field;
+ char *op = argv[2];
+
+ if (bcb_field_get(argv[1], &field, &size))
+ return CMD_RET_FAILURE;
+
+ if (*op == '=' && *(op + 1) == '\0') {
+ if (!strncmp(argv[3], field, size))
+ return CMD_RET_SUCCESS;
+ else
+ return CMD_RET_FAILURE;
+ } else if (*op == '~' && *(op + 1) == '\0') {
+ if (!strstr(field, argv[3]))
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+ } else {
+ printf("Error: Unknown operator '%s'\n", op);
+ }
+
+ return CMD_RET_FAILURE;
+}
+
+static int do_bcb_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int size;
+ char *field;
+
+ if (bcb_field_get(argv[1], &field, &size))
+ return CMD_RET_FAILURE;
+
+ print_buffer((ulong)field - (ulong)&bcb, (void *)field, 1, size, 16);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int __bcb_store(void)
+{
+ struct blk_desc *desc;
+ struct disk_partition info;
+ u64 cnt;
+ int ret;
+
+ desc = blk_get_devnum_by_type(IF_TYPE_MMC, bcb_dev);
+ if (!desc) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = part_get_info(desc, bcb_part, &info);
+ if (ret)
+ goto err;
+
+ cnt = DIV_ROUND_UP(sizeof(struct bootloader_message), info.blksz);
+
+ if (blk_dwrite(desc, info.start, cnt, &bcb) != cnt) {
+ ret = -EIO;
+ goto err;
+ }
+
+ return CMD_RET_SUCCESS;
+err:
+ printf("Error: mmc %d:%d write failed (%d)\n", bcb_dev, bcb_part, ret);
+
+ return CMD_RET_FAILURE;
+}
+
+static int do_bcb_store(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ return __bcb_store();
+}
+
+int bcb_write_reboot_reason(int devnum, char *partp, const char *reasonp)
+{
+ int ret;
+
+ ret = __bcb_load(devnum, partp);
+ if (ret != CMD_RET_SUCCESS)
+ return ret;
+
+ ret = __bcb_set("command", reasonp);
+ if (ret != CMD_RET_SUCCESS)
+ return ret;
+
+ ret = __bcb_store();
+ if (ret != CMD_RET_SUCCESS)
+ return ret;
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_bcb_sub[] = {
+ U_BOOT_CMD_MKENT(load, CONFIG_SYS_MAXARGS, 1, do_bcb_load, "", ""),
+ U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 1, do_bcb_set, "", ""),
+ U_BOOT_CMD_MKENT(clear, CONFIG_SYS_MAXARGS, 1, do_bcb_clear, "", ""),
+ U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_bcb_test, "", ""),
+ U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_bcb_dump, "", ""),
+ U_BOOT_CMD_MKENT(store, CONFIG_SYS_MAXARGS, 1, do_bcb_store, "", ""),
+};
+
+static int do_bcb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], cmd_bcb_sub, ARRAY_SIZE(cmd_bcb_sub));
+ if (!c)
+ return CMD_RET_USAGE;
+
+ if (bcb_is_misused(argc, argv)) {
+ /*
+ * We try to improve the user experience by reporting the
+ * root-cause of misusage, so don't return CMD_RET_USAGE,
+ * since the latter prints out the full-blown help text
+ */
+ return CMD_RET_FAILURE;
+ }
+
+ return c->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ bcb, CONFIG_SYS_MAXARGS, 1, do_bcb,
+ "Load/set/clear/test/dump/store Android BCB fields",
+ "load <dev> <part> - load BCB from mmc <dev>:<part>\n"
+ "bcb set <field> <val> - set BCB <field> to <val>\n"
+ "bcb clear [<field>] - clear BCB <field> or all fields\n"
+ "bcb test <field> <op> <val> - test BCB <field> against <val>\n"
+ "bcb dump <field> - dump BCB <field>\n"
+ "bcb store - store BCB back to mmc\n"
+ "\n"
+ "Legend:\n"
+ "<dev> - MMC device index containing the BCB partition\n"
+ "<part> - MMC partition index or name containing the BCB\n"
+ "<field> - one of {command,status,recovery,stage,reserved}\n"
+ "<op> - the binary operator used in 'bcb test':\n"
+ " '=' returns true if <val> matches the string stored in <field>\n"
+ " '~' returns true if <val> matches a subset of <field>'s string\n"
+ "<val> - string/text provided as input to bcb {set,test}\n"
+ " NOTE: any ':' character in <val> will be replaced by line feed\n"
+ " during 'bcb set' and used as separator by upper layers\n"
+);
diff --git a/roms/u-boot/cmd/bdinfo.c b/roms/u-boot/cmd/bdinfo.c
new file mode 100644
index 000000000..bf63cc6d6
--- /dev/null
+++ b/roms/u-boot/cmd/bdinfo.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Implements the 'bd' command to show board information
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <env.h>
+#include <lmb.h>
+#include <net.h>
+#include <video.h>
+#include <vsprintf.h>
+#include <asm/cache.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void bdinfo_print_num_l(const char *name, ulong value)
+{
+ printf("%-12s= 0x%0*lx\n", name, 2 * (int)sizeof(value), value);
+}
+
+void bdinfo_print_num_ll(const char *name, unsigned long long value)
+{
+ printf("%-12s= 0x%.*llx\n", name, 2 * (int)sizeof(ulong), value);
+}
+
+static void print_eth(int idx)
+{
+ char name[10], *val;
+ if (idx)
+ sprintf(name, "eth%iaddr", idx);
+ else
+ strcpy(name, "ethaddr");
+ val = env_get(name);
+ if (!val)
+ val = "(not set)";
+ printf("%-12s= %s\n", name, val);
+}
+
+void bdinfo_print_mhz(const char *name, unsigned long hz)
+{
+ char buf[32];
+
+ printf("%-12s= %6s MHz\n", name, strmhz(buf, hz));
+}
+
+static void print_bi_dram(const struct bd_info *bd)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
+ if (bd->bi_dram[i].size) {
+ bdinfo_print_num_l("DRAM bank", i);
+ bdinfo_print_num_ll("-> start", bd->bi_dram[i].start);
+ bdinfo_print_num_ll("-> size", bd->bi_dram[i].size);
+ }
+ }
+}
+
+__weak void arch_print_bdinfo(void)
+{
+}
+
+static void show_video_info(void)
+{
+ const struct udevice *dev;
+ struct uclass *uc;
+
+ uclass_id_foreach_dev(UCLASS_VIDEO, dev, uc) {
+ printf("%-12s= %s %sactive\n", "Video", dev->name,
+ device_active(dev) ? "" : "in");
+ if (device_active(dev)) {
+ struct video_priv *upriv = dev_get_uclass_priv(dev);
+
+ bdinfo_print_num_ll("FB base", (ulong)upriv->fb);
+ if (upriv->copy_fb)
+ bdinfo_print_num_ll("FB copy",
+ (ulong)upriv->copy_fb);
+ printf("%-12s= %dx%dx%d\n", "FB size", upriv->xsize,
+ upriv->ysize, 1 << upriv->bpix);
+ }
+ }
+}
+
+int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct bd_info *bd = gd->bd;
+
+#ifdef DEBUG
+ bdinfo_print_num_l("bd address", (ulong)bd);
+#endif
+ bdinfo_print_num_l("boot_params", (ulong)bd->bi_boot_params);
+ print_bi_dram(bd);
+ if (IS_ENABLED(CONFIG_SYS_HAS_SRAM)) {
+ bdinfo_print_num_l("sramstart", (ulong)bd->bi_sramstart);
+ bdinfo_print_num_l("sramsize", (ulong)bd->bi_sramsize);
+ }
+ bdinfo_print_num_l("flashstart", (ulong)bd->bi_flashstart);
+ bdinfo_print_num_l("flashsize", (ulong)bd->bi_flashsize);
+ bdinfo_print_num_l("flashoffset", (ulong)bd->bi_flashoffset);
+ printf("baudrate = %u bps\n", gd->baudrate);
+ bdinfo_print_num_l("relocaddr", gd->relocaddr);
+ bdinfo_print_num_l("reloc off", gd->reloc_off);
+ printf("%-12s= %u-bit\n", "Build", (uint)sizeof(void *) * 8);
+ if (IS_ENABLED(CONFIG_CMD_NET)) {
+ printf("current eth = %s\n", eth_get_name());
+ print_eth(0);
+ printf("IP addr = %s\n", env_get("ipaddr"));
+ }
+ bdinfo_print_num_l("fdt_blob", (ulong)gd->fdt_blob);
+ bdinfo_print_num_l("new_fdt", (ulong)gd->new_fdt);
+ bdinfo_print_num_l("fdt_size", (ulong)gd->fdt_size);
+ if (IS_ENABLED(CONFIG_DM_VIDEO))
+ show_video_info();
+#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
+ bdinfo_print_num_l("FB base ", gd->fb_base);
+#endif
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+ bdinfo_print_num_l("multi_dtb_fit", (ulong)gd->multi_dtb_fit);
+#endif
+ if (gd->fdt_blob) {
+ struct lmb lmb;
+
+ lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
+ lmb_dump_all_force(&lmb);
+ }
+
+ arch_print_bdinfo();
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ bdinfo, 1, 1, do_bdinfo,
+ "print Board Info structure",
+ ""
+);
diff --git a/roms/u-boot/cmd/bedbug.c b/roms/u-boot/cmd/bedbug.c
new file mode 100644
index 000000000..bef617b6a
--- /dev/null
+++ b/roms/u-boot/cmd/bedbug.c
@@ -0,0 +1,414 @@
+/*
+ * BedBug Functions
+ */
+
+#include <common.h>
+#include <cli.h>
+#include <command.h>
+#include <console.h>
+#include <asm/global_data.h>
+#include <asm/ptrace.h>
+#include <linux/ctype.h>
+#include <net.h>
+#include <bedbug/type.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern void show_regs __P ((struct pt_regs *));
+extern int run_command __P ((const char *, int));
+
+ulong dis_last_addr = 0; /* Last address disassembled */
+ulong dis_last_len = 20; /* Default disassembler length */
+CPU_DEBUG_CTX bug_ctx; /* Bedbug context structure */
+
+
+/* ======================================================================
+ * U-Boot's puts function does not append a newline, so the bedbug stuff
+ * will use this for the output of the dis/assembler.
+ * ====================================================================== */
+
+int bedbug_puts (const char *str)
+{
+ /* -------------------------------------------------- */
+
+ printf ("%s\r\n", str);
+ return 0;
+} /* bedbug_puts */
+
+
+
+/* ======================================================================
+ * Initialize the bug_ctx structure used by the bedbug debugger. This is
+ * specific to the CPU since each has different debug registers and
+ * settings.
+ * ====================================================================== */
+
+int bedbug_init(void)
+{
+ /* -------------------------------------------------- */
+ return 0;
+} /* bedbug_init */
+
+
+
+/* ======================================================================
+ * Entry point from the interpreter to the disassembler. Repeated calls
+ * will resume from the last disassembled address.
+ * ====================================================================== */
+int do_bedbug_dis(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr; /* Address to start disassembly from */
+ ulong len; /* # of instructions to disassemble */
+
+ /* -------------------------------------------------- */
+
+ /* Setup to go from the last address if none is given */
+ addr = dis_last_addr;
+ len = dis_last_len;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /* New command */
+ addr = simple_strtoul (argv[1], NULL, 16);
+
+ /* If an extra param is given then it is the length */
+ if (argc > 2)
+ len = simple_strtoul (argv[2], NULL, 16);
+ }
+
+ /* Run the disassembler */
+ disppc ((unsigned char *) addr, 0, len, bedbug_puts, F_RADHEX);
+
+ dis_last_addr = addr + (len * 4);
+ dis_last_len = len;
+ return 0;
+} /* do_bedbug_dis */
+
+U_BOOT_CMD (ds, 3, 1, do_bedbug_dis,
+ "disassemble memory",
+ "ds <address> [# instructions]");
+
+/* ======================================================================
+ * Entry point from the interpreter to the assembler. Assembles
+ * instructions in consecutive memory locations until a '.' (period) is
+ * entered on a line by itself.
+ * ====================================================================== */
+int do_bedbug_asm(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ long mem_addr; /* Address to assemble into */
+ unsigned long instr; /* Machine code for text */
+ char prompt[15]; /* Prompt string for user input */
+ int asm_err; /* Error code from the assembler */
+
+ /* -------------------------------------------------- */
+ int rcode = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ printf ("\nEnter '.' when done\n");
+ mem_addr = simple_strtoul (argv[1], NULL, 16);
+
+ while (1) {
+ putc ('\n');
+ disppc ((unsigned char *) mem_addr, 0, 1, bedbug_puts,
+ F_RADHEX);
+
+ sprintf (prompt, "%08lx: ", mem_addr);
+ cli_readline(prompt);
+
+ if (console_buffer[0] && strcmp (console_buffer, ".")) {
+ if ((instr =
+ asmppc (mem_addr, console_buffer,
+ &asm_err)) != 0) {
+ *(unsigned long *) mem_addr = instr;
+ mem_addr += 4;
+ } else {
+ printf ("*** Error: %s ***\n",
+ asm_error_str (asm_err));
+ rcode = 1;
+ }
+ } else {
+ break;
+ }
+ }
+ return rcode;
+} /* do_bedbug_asm */
+
+U_BOOT_CMD (as, 2, 0, do_bedbug_asm,
+ "assemble memory", "as <address>");
+
+/* ======================================================================
+ * Used to set a break point from the interpreter. Simply calls into the
+ * CPU-specific break point set routine.
+ * ====================================================================== */
+
+int do_bedbug_break(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ /* -------------------------------------------------- */
+ if (bug_ctx.do_break)
+ (*bug_ctx.do_break) (cmdtp, flag, argc, argv);
+ return 0;
+
+} /* do_bedbug_break */
+
+U_BOOT_CMD (break, 3, 0, do_bedbug_break,
+ "set or clear a breakpoint",
+ " - Set or clear a breakpoint\n"
+ "break <address> - Break at an address\n"
+ "break off <bp#> - Disable breakpoint.\n"
+ "break show - List breakpoints.");
+
+/* ======================================================================
+ * Called from the debug interrupt routine. Simply calls the CPU-specific
+ * breakpoint handling routine.
+ * ====================================================================== */
+
+void do_bedbug_breakpoint (struct pt_regs *regs)
+{
+ /* -------------------------------------------------- */
+
+ if (bug_ctx.break_isr)
+ (*bug_ctx.break_isr) (regs);
+
+ return;
+} /* do_bedbug_breakpoint */
+
+
+
+/* ======================================================================
+ * Called from the CPU-specific breakpoint handling routine. Enter a
+ * mini main loop until the stopped flag is cleared from the breakpoint
+ * context.
+ *
+ * This handles the parts of the debugger that are common to all CPU's.
+ * ====================================================================== */
+
+void bedbug_main_loop (unsigned long addr, struct pt_regs *regs)
+{
+ int len; /* Length of command line */
+ int flag; /* Command flags */
+ int rc = 0; /* Result from run_command */
+ char prompt_str[20]; /* Prompt string */
+ static char lastcommand[CONFIG_SYS_CBSIZE] = { 0 }; /* previous command */
+ /* -------------------------------------------------- */
+
+ if (bug_ctx.clear)
+ (*bug_ctx.clear) (bug_ctx.current_bp);
+
+ printf ("Breakpoint %d: ", bug_ctx.current_bp);
+ disppc ((unsigned char *) addr, 0, 1, bedbug_puts, F_RADHEX);
+
+ bug_ctx.stopped = 1;
+ bug_ctx.regs = regs;
+
+ sprintf (prompt_str, "BEDBUG.%d =>", bug_ctx.current_bp);
+
+ /* A miniature main loop */
+ while (bug_ctx.stopped) {
+ len = cli_readline(prompt_str);
+
+ flag = 0; /* assume no special flags for now */
+
+ if (len > 0)
+ strcpy (lastcommand, console_buffer);
+ else if (len == 0)
+ flag |= CMD_FLAG_REPEAT;
+
+ if (len == -1)
+ printf ("<INTERRUPT>\n");
+ else
+ rc = run_command_repeatable(lastcommand, flag);
+
+ if (rc <= 0) {
+ /* invalid command or not repeatable, forget it */
+ lastcommand[0] = 0;
+ }
+ }
+
+ bug_ctx.regs = NULL;
+ bug_ctx.current_bp = 0;
+
+ return;
+} /* bedbug_main_loop */
+
+
+
+/* ======================================================================
+ * Interpreter command to continue from a breakpoint. Just clears the
+ * stopped flag in the context so that the breakpoint routine will
+ * return.
+ * ====================================================================== */
+int do_bedbug_continue(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ /* -------------------------------------------------- */
+
+ if (!bug_ctx.stopped) {
+ printf ("Not at a breakpoint\n");
+ return 1;
+ }
+
+ bug_ctx.stopped = 0;
+ return 0;
+} /* do_bedbug_continue */
+
+U_BOOT_CMD (continue, 1, 0, do_bedbug_continue,
+ "continue from a breakpoint",
+ "");
+
+/* ======================================================================
+ * Interpreter command to continue to the next instruction, stepping into
+ * subroutines. Works by calling the find_next_addr() routine to compute
+ * the address passes control to the CPU-specific set breakpoint routine
+ * for the current breakpoint number.
+ * ====================================================================== */
+int do_bedbug_step(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long addr; /* Address to stop at */
+
+ /* -------------------------------------------------- */
+
+ if (!bug_ctx.stopped) {
+ printf ("Not at a breakpoint\n");
+ return 1;
+ }
+
+ if (!find_next_address((unsigned char *) &addr, false, bug_ctx.regs))
+ return 1;
+
+ if (bug_ctx.set)
+ (*bug_ctx.set) (bug_ctx.current_bp, addr);
+
+ bug_ctx.stopped = 0;
+ return 0;
+} /* do_bedbug_step */
+
+U_BOOT_CMD (step, 1, 1, do_bedbug_step,
+ "single step execution.",
+ "");
+
+/* ======================================================================
+ * Interpreter command to continue to the next instruction, stepping over
+ * subroutines. Works by calling the find_next_addr() routine to compute
+ * the address passes control to the CPU-specific set breakpoint routine
+ * for the current breakpoint number.
+ * ====================================================================== */
+int do_bedbug_next(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long addr; /* Address to stop at */
+
+ /* -------------------------------------------------- */
+
+ if (!bug_ctx.stopped) {
+ printf ("Not at a breakpoint\n");
+ return 1;
+ }
+
+ if (!find_next_address((unsigned char *) &addr, true, bug_ctx.regs))
+ return 1;
+
+ if (bug_ctx.set)
+ (*bug_ctx.set) (bug_ctx.current_bp, addr);
+
+ bug_ctx.stopped = 0;
+ return 0;
+} /* do_bedbug_next */
+
+U_BOOT_CMD (next, 1, 1, do_bedbug_next,
+ "single step execution, stepping over subroutines.",
+ "");
+
+/* ======================================================================
+ * Interpreter command to print the current stack. This assumes an EABI
+ * architecture, so it starts with GPR R1 and works back up the stack.
+ * ====================================================================== */
+int do_bedbug_stack(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long sp; /* Stack pointer */
+ unsigned long func; /* LR from stack */
+ int depth; /* Stack iteration level */
+ int skip = 1; /* Flag to skip the first entry */
+ unsigned long top; /* Top of memory address */
+
+ /* -------------------------------------------------- */
+
+ if (!bug_ctx.stopped) {
+ printf ("Not at a breakpoint\n");
+ return 1;
+ }
+
+ top = gd->ram_start + gd->ram_size;
+ depth = 0;
+
+ printf ("Depth PC\n");
+ printf ("----- --------\n");
+ printf ("%5d %08lx\n", depth++, bug_ctx.regs->nip);
+
+ sp = bug_ctx.regs->gpr[1];
+ func = *(unsigned long *) (sp + 4);
+
+ while ((func < top) && (sp < top)) {
+ if (!skip)
+ printf ("%5d %08lx\n", depth++, func);
+ else
+ --skip;
+
+ sp = *(unsigned long *) sp;
+ func = *(unsigned long *) (sp + 4);
+ }
+ return 0;
+} /* do_bedbug_stack */
+
+U_BOOT_CMD (where, 1, 1, do_bedbug_stack,
+ "Print the running stack.",
+ "");
+
+/* ======================================================================
+ * Interpreter command to dump the registers. Calls the CPU-specific
+ * show registers routine.
+ * ====================================================================== */
+int do_bedbug_rdump(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ /* -------------------------------------------------- */
+
+ if (!bug_ctx.stopped) {
+ printf ("Not at a breakpoint\n");
+ return 1;
+ }
+
+ show_regs (bug_ctx.regs);
+ return 0;
+} /* do_bedbug_rdump */
+
+U_BOOT_CMD (rdump, 1, 1, do_bedbug_rdump,
+ "Show registers.", "");
+/* ====================================================================== */
+
+
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
diff --git a/roms/u-boot/cmd/bind.c b/roms/u-boot/cmd/bind.c
new file mode 100644
index 000000000..af2f22cc4
--- /dev/null
+++ b/roms/u-boot/cmd/bind.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 JJ Hiblot <jjhiblot@ti.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <dm/uclass-internal.h>
+
+static int bind_by_class_index(const char *uclass, int index,
+ const char *drv_name)
+{
+ static enum uclass_id uclass_id;
+ struct udevice *dev;
+ struct udevice *parent;
+ int ret;
+ struct driver *drv;
+
+ drv = lists_driver_lookup_name(drv_name);
+ if (!drv) {
+ printf("Cannot find driver '%s'\n", drv_name);
+ return -ENOENT;
+ }
+
+ uclass_id = uclass_get_by_name(uclass);
+ if (uclass_id == UCLASS_INVALID) {
+ printf("%s is not a valid uclass\n", uclass);
+ return -EINVAL;
+ }
+
+ ret = uclass_find_device(uclass_id, index, &parent);
+ if (!parent || ret) {
+ printf("Cannot find device %d of class %s\n", index, uclass);
+ return ret;
+ }
+
+ ret = device_bind_with_driver_data(parent, drv, drv->name, 0,
+ ofnode_null(), &dev);
+ if (!dev || ret) {
+ printf("Unable to bind. err:%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int find_dev(const char *uclass, int index, struct udevice **devp)
+{
+ static enum uclass_id uclass_id;
+ int rc;
+
+ uclass_id = uclass_get_by_name(uclass);
+ if (uclass_id == UCLASS_INVALID) {
+ printf("%s is not a valid uclass\n", uclass);
+ return -EINVAL;
+ }
+
+ rc = uclass_find_device(uclass_id, index, devp);
+ if (!*devp || rc) {
+ printf("Cannot find device %d of class %s\n", index, uclass);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int unbind_by_class_index(const char *uclass, int index)
+{
+ int ret;
+ struct udevice *dev;
+
+ ret = find_dev(uclass, index, &dev);
+ if (ret)
+ return ret;
+
+ ret = device_remove(dev, DM_REMOVE_NORMAL);
+ if (ret) {
+ printf("Unable to remove. err:%d\n", ret);
+ return ret;
+ }
+
+ ret = device_unbind(dev);
+ if (ret) {
+ printf("Unable to unbind. err:%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int unbind_child_by_class_index(const char *uclass, int index,
+ const char *drv_name)
+{
+ struct udevice *parent;
+ int ret;
+ struct driver *drv;
+
+ drv = lists_driver_lookup_name(drv_name);
+ if (!drv) {
+ printf("Cannot find driver '%s'\n", drv_name);
+ return -ENOENT;
+ }
+
+ ret = find_dev(uclass, index, &parent);
+ if (ret)
+ return ret;
+
+ ret = device_chld_remove(parent, drv, DM_REMOVE_NORMAL);
+ if (ret)
+ printf("Unable to remove all. err:%d\n", ret);
+
+ ret = device_chld_unbind(parent, drv);
+ if (ret)
+ printf("Unable to unbind all. err:%d\n", ret);
+
+ return ret;
+}
+
+static int bind_by_node_path(const char *path, const char *drv_name)
+{
+ struct udevice *dev;
+ struct udevice *parent = NULL;
+ int ret;
+ ofnode ofnode;
+ struct driver *drv;
+
+ drv = lists_driver_lookup_name(drv_name);
+ if (!drv) {
+ printf("%s is not a valid driver name\n", drv_name);
+ return -ENOENT;
+ }
+
+ ofnode = ofnode_path(path);
+ if (!ofnode_valid(ofnode)) {
+ printf("%s is not a valid node path\n", path);
+ return -EINVAL;
+ }
+
+ while (ofnode_valid(ofnode)) {
+ if (!device_find_global_by_ofnode(ofnode, &parent))
+ break;
+ ofnode = ofnode_get_parent(ofnode);
+ }
+
+ if (!parent) {
+ printf("Cannot find a parent device for node path %s\n", path);
+ return -ENODEV;
+ }
+
+ ofnode = ofnode_path(path);
+ ret = lists_bind_fdt(parent, ofnode, &dev, false);
+
+ if (!dev || ret) {
+ printf("Unable to bind. err:%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int unbind_by_node_path(const char *path)
+{
+ struct udevice *dev;
+ int ret;
+ ofnode ofnode;
+
+ ofnode = ofnode_path(path);
+ if (!ofnode_valid(ofnode)) {
+ printf("%s is not a valid node path\n", path);
+ return -EINVAL;
+ }
+
+ ret = device_find_global_by_ofnode(ofnode, &dev);
+
+ if (!dev || ret) {
+ printf("Cannot find a device with path %s\n", path);
+ return -ENODEV;
+ }
+
+ ret = device_remove(dev, DM_REMOVE_NORMAL);
+ if (ret) {
+ printf("Unable to remove. err:%d\n", ret);
+ return ret;
+ }
+
+ ret = device_unbind(dev);
+ if (ret) {
+ printf("Unable to unbind. err:%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int do_bind_unbind(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret = 0;
+ bool bind;
+ bool by_node;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ bind = (argv[0][0] == 'b');
+ by_node = (argv[1][0] == '/');
+
+ if (by_node && bind) {
+ if (argc != 3)
+ return CMD_RET_USAGE;
+ ret = bind_by_node_path(argv[1], argv[2]);
+ } else if (by_node && !bind) {
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ ret = unbind_by_node_path(argv[1]);
+ } else if (!by_node && bind) {
+ int index = (argc > 2) ? simple_strtoul(argv[2], NULL, 10) : 0;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+ ret = bind_by_class_index(argv[1], index, argv[3]);
+ } else if (!by_node && !bind) {
+ int index = (argc > 2) ? simple_strtoul(argv[2], NULL, 10) : 0;
+
+ if (argc == 3)
+ ret = unbind_by_class_index(argv[1], index);
+ else if (argc == 4)
+ ret = unbind_child_by_class_index(argv[1], index,
+ argv[3]);
+ else
+ return CMD_RET_USAGE;
+ }
+
+ if (ret)
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ bind, 4, 0, do_bind_unbind,
+ "Bind a device to a driver",
+ "<node path> <driver>\n"
+ "bind <class> <index> <driver>\n"
+);
+
+U_BOOT_CMD(
+ unbind, 4, 0, do_bind_unbind,
+ "Unbind a device from a driver",
+ "<node path>\n"
+ "unbind <class> <index>\n"
+ "unbind <class> <index> <driver>\n"
+);
diff --git a/roms/u-boot/cmd/binop.c b/roms/u-boot/cmd/binop.c
new file mode 100644
index 000000000..c85cb5156
--- /dev/null
+++ b/roms/u-boot/cmd/binop.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <hexdump.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <linux/ctype.h>
+
+enum {
+ OP_ID_XOR,
+ OP_ID_AND,
+ OP_ID_OR,
+};
+
+void write_to_env_var(char *varname, u8 *result, ulong len)
+{
+ char *str_output;
+ char *str_ptr;
+ int i;
+
+ str_output = malloc(len * 2 + 1);
+ str_ptr = str_output;
+
+ for (i = 0; i < len; i++) {
+ sprintf(str_ptr, "%02x", result[i]);
+ str_ptr += 2;
+ }
+ *str_ptr = '\0';
+ env_set(varname, str_output);
+
+ free(str_output);
+}
+
+void read_from_env_var(char *varname, u8 *result)
+{
+ char *str_value;
+
+ str_value = env_get(varname);
+ if (str_value)
+ hex2bin(result, str_value, strlen(str_value) / 2);
+ else
+ hex2bin(result, varname, strlen(varname) / 2);
+}
+
+void read_from_mem(ulong addr, u8 *result, ulong len)
+{
+ u8 *src;
+
+ src = map_sysmem(addr, len);
+ memcpy(result, src, len);
+ unmap_sysmem(src);
+}
+
+void write_to_mem(char *varname, u8 *result, ulong len)
+{
+ ulong addr;
+ u8 *buf;
+
+ addr = simple_strtoul(varname, NULL, 16);
+ buf = map_sysmem(addr, len);
+ memcpy(buf, result, len);
+ unmap_sysmem(buf);
+}
+
+static int do_binop(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong len;
+ u8 *result, *src1, *src2;
+ char *oparg, *lenarg, *src1arg, *src2arg, *destarg;
+ int i, op;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ oparg = argv[1];
+ lenarg = argv[2];
+ src1arg = argv[3];
+ src2arg = argv[4];
+
+ if (!strcmp(oparg, "xor"))
+ op = OP_ID_XOR;
+ else if (!strcmp(oparg, "or"))
+ op = OP_ID_OR;
+ else if (!strcmp(oparg, "and"))
+ op = OP_ID_AND;
+ else
+ return CMD_RET_USAGE;
+
+ len = simple_strtoul(lenarg, NULL, 10);
+
+ src1 = malloc(len);
+ src2 = malloc(len);
+
+ if (*src1arg == '*')
+ read_from_mem(simple_strtoul(src1arg + 1, NULL, 16), src1, len);
+ else
+ read_from_env_var(src1arg, src1);
+
+ if (*src2arg == '*')
+ read_from_mem(simple_strtoul(src2arg + 1, NULL, 16), src2, len);
+ else
+ read_from_env_var(src2arg, src2);
+
+ result = malloc(len);
+
+ switch (op) {
+ case OP_ID_XOR:
+ for (i = 0; i < len; i++)
+ result[i] = src1[i] ^ src2[i];
+ break;
+ case OP_ID_OR:
+ for (i = 0; i < len; i++)
+ result[i] = src1[i] | src2[i];
+ break;
+ case OP_ID_AND:
+ for (i = 0; i < len; i++)
+ result[i] = src1[i] & src2[i];
+ break;
+ }
+
+ if (argc == 5) {
+ for (i = 0; i < len; i++) {
+ printf("%02x ", result[i]);
+ if (i % 16 == 15)
+ puts("\n");
+ }
+ puts("\n");
+
+ goto exit;
+ }
+
+ destarg = argv[5];
+
+ if (*destarg == '*')
+ write_to_mem(destarg + 1, result, len); /* Skip asterisk */
+ else
+ write_to_env_var(destarg, result, len);
+exit:
+ free(result);
+ free(src2);
+ free(src1);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ binop, 6, 1, do_binop,
+ "compute binary operation",
+ "op count [*]src1 [*]src2 [[*]dest]\n"
+ " - compute binary operation of data at/in src1 and\n src2 (either *memaddr, env var name or hex string)\n and store result in/at dest, where op is one of\n xor, or, and."
+);
diff --git a/roms/u-boot/cmd/blk_common.c b/roms/u-boot/cmd/blk_common.c
new file mode 100644
index 000000000..87f94b5ab
--- /dev/null
+++ b/roms/u-boot/cmd/blk_common.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Handling of common block commands
+ *
+ * Copyright (c) 2017 Google, Inc
+ *
+ * (C) Copyright 2000-2011
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <command.h>
+
+int blk_common_cmd(int argc, char *const argv[], enum if_type if_type,
+ int *cur_devnump)
+{
+ const char *if_name = blk_get_if_type_name(if_type);
+
+ switch (argc) {
+ case 0:
+ case 1:
+ return CMD_RET_USAGE;
+ case 2:
+ if (strncmp(argv[1], "inf", 3) == 0) {
+ blk_list_devices(if_type);
+ return 0;
+ } else if (strncmp(argv[1], "dev", 3) == 0) {
+ if (blk_print_device_num(if_type, *cur_devnump)) {
+ printf("\nno %s devices available\n", if_name);
+ return CMD_RET_FAILURE;
+ }
+ return 0;
+ } else if (strncmp(argv[1], "part", 4) == 0) {
+ if (blk_list_part(if_type))
+ printf("\nno %s partition table available\n",
+ if_name);
+ return 0;
+ }
+ return CMD_RET_USAGE;
+ case 3:
+ if (strncmp(argv[1], "dev", 3) == 0) {
+ int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+ if (!blk_show_device(if_type, dev)) {
+ *cur_devnump = dev;
+ printf("... is now current device\n");
+ } else {
+ return CMD_RET_FAILURE;
+ }
+ return 0;
+ } else if (strncmp(argv[1], "part", 4) == 0) {
+ int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+ if (blk_print_part_devnum(if_type, dev)) {
+ printf("\n%s device %d not available\n",
+ if_name, dev);
+ return CMD_RET_FAILURE;
+ }
+ return 0;
+ }
+ return CMD_RET_USAGE;
+
+ default: /* at least 4 args */
+ if (strcmp(argv[1], "read") == 0) {
+ ulong addr = simple_strtoul(argv[2], NULL, 16);
+ lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
+ ulong cnt = simple_strtoul(argv[4], NULL, 16);
+ ulong n;
+
+ printf("\n%s read: device %d block # "LBAFU", count %lu ... ",
+ if_name, *cur_devnump, blk, cnt);
+
+ n = blk_read_devnum(if_type, *cur_devnump, blk, cnt,
+ (ulong *)addr);
+
+ printf("%ld blocks read: %s\n", n,
+ n == cnt ? "OK" : "ERROR");
+ return n == cnt ? 0 : 1;
+ } else if (strcmp(argv[1], "write") == 0) {
+ ulong addr = simple_strtoul(argv[2], NULL, 16);
+ lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
+ ulong cnt = simple_strtoul(argv[4], NULL, 16);
+ ulong n;
+
+ printf("\n%s write: device %d block # "LBAFU", count %lu ... ",
+ if_name, *cur_devnump, blk, cnt);
+
+ n = blk_write_devnum(if_type, *cur_devnump, blk, cnt,
+ (ulong *)addr);
+
+ printf("%ld blocks written: %s\n", n,
+ n == cnt ? "OK" : "ERROR");
+ return n == cnt ? 0 : 1;
+ } else {
+ return CMD_RET_USAGE;
+ }
+ }
+}
diff --git a/roms/u-boot/cmd/blkcache.c b/roms/u-boot/cmd/blkcache.c
new file mode 100644
index 000000000..25f252e45
--- /dev/null
+++ b/roms/u-boot/cmd/blkcache.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) Nelson Integration, LLC 2016
+ * Author: Eric Nelson<eric@nelint.com>
+ *
+ */
+#include <command.h>
+#include <config.h>
+#include <common.h>
+#include <malloc.h>
+#include <part.h>
+
+static int blkc_show(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct block_cache_stats stats;
+ blkcache_stats(&stats);
+
+ printf("hits: %u\n"
+ "misses: %u\n"
+ "entries: %u\n"
+ "max blocks/entry: %u\n"
+ "max cache entries: %u\n",
+ stats.hits, stats.misses, stats.entries,
+ stats.max_blocks_per_entry, stats.max_entries);
+ return 0;
+}
+
+static int blkc_configure(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ unsigned blocks_per_entry, max_entries;
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ blocks_per_entry = simple_strtoul(argv[1], 0, 0);
+ max_entries = simple_strtoul(argv[2], 0, 0);
+ blkcache_configure(blocks_per_entry, max_entries);
+ printf("changed to max of %u entries of %u blocks each\n",
+ max_entries, blocks_per_entry);
+ return 0;
+}
+
+static struct cmd_tbl cmd_blkc_sub[] = {
+ U_BOOT_CMD_MKENT(show, 0, 0, blkc_show, "", ""),
+ U_BOOT_CMD_MKENT(configure, 3, 0, blkc_configure, "", ""),
+};
+
+static __maybe_unused void blkc_reloc(void)
+{
+ static int relocated;
+
+ if (!relocated) {
+ fixup_cmdtable(cmd_blkc_sub, ARRAY_SIZE(cmd_blkc_sub));
+ relocated = 1;
+ };
+}
+
+static int do_blkcache(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct cmd_tbl *c;
+
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+ blkc_reloc();
+#endif
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* Strip off leading argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], &cmd_blkc_sub[0], ARRAY_SIZE(cmd_blkc_sub));
+
+ if (!c)
+ return CMD_RET_USAGE;
+
+ return c->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ blkcache, 4, 0, do_blkcache,
+ "block cache diagnostics and control",
+ "show - show and reset statistics\n"
+ "blkcache configure blocks entries\n"
+);
diff --git a/roms/u-boot/cmd/blob.c b/roms/u-boot/cmd/blob.c
new file mode 100644
index 000000000..887219cc0
--- /dev/null
+++ b/roms/u-boot/cmd/blob.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *
+ * Command for encapsulating/decapsulating blob of memory.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <linux/compiler.h>
+#if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MX7) || \
+ defined(CONFIG_ARCH_MX7ULP) || defined(CONFIG_ARCH_IMX8M)
+#include <fsl_sec.h>
+#include <asm/arch/clock.h>
+#endif
+
+/**
+ * blob_decap() - Decapsulate the data as a blob
+ * @key_mod: - Pointer to key modifier/key
+ * @src: - Address of data to be decapsulated
+ * @dst: - Address of data to be decapsulated
+ * @len: - Size of data to be decapsulated
+ *
+ * Returns zero on success,and negative on error.
+ */
+__weak int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
+{
+ return 0;
+}
+
+/**
+ * blob_encap() - Encapsulate the data as a blob
+ * @key_mod: - Pointer to key modifier/key
+ * @src: - Address of data to be encapsulated
+ * @dst: - Address of data to be encapsulated
+ * @len: - Size of data to be encapsulated
+ *
+ * Returns zero on success,and negative on error.
+ */
+__weak int blob_encap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
+{
+ return 0;
+}
+
+/**
+ * do_blob() - Handle the "blob" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_blob(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong key_addr, src_addr, dst_addr, len;
+ uint8_t *km_ptr, *src_ptr, *dst_ptr;
+ int enc, ret = 0;
+
+ if (argc != 6)
+ return CMD_RET_USAGE;
+
+ if (!strncmp(argv[1], "enc", 3))
+ enc = 1;
+ else if (!strncmp(argv[1], "dec", 3))
+ enc = 0;
+ else
+ return CMD_RET_USAGE;
+
+ src_addr = simple_strtoul(argv[2], NULL, 16);
+ dst_addr = simple_strtoul(argv[3], NULL, 16);
+ len = simple_strtoul(argv[4], NULL, 16);
+ key_addr = simple_strtoul(argv[5], NULL, 16);
+
+ km_ptr = (uint8_t *)(uintptr_t)key_addr;
+ src_ptr = (uint8_t *)(uintptr_t)src_addr;
+ dst_ptr = (uint8_t *)(uintptr_t)dst_addr;
+
+#if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MX7) || \
+ defined(CONFIG_ARCH_MX7ULP) || defined(CONFIG_ARCH_IMX8M)
+
+ hab_caam_clock_enable(1);
+
+ u32 out_jr_size = sec_in32(CONFIG_SYS_FSL_JR0_ADDR +
+ FSL_CAAM_ORSR_JRa_OFFSET);
+ if (out_jr_size != FSL_CAAM_MAX_JR_SIZE)
+ sec_init();
+#endif
+
+ if (enc)
+ ret = blob_encap(km_ptr, src_ptr, dst_ptr, len);
+ else
+ ret = blob_decap(km_ptr, src_ptr, dst_ptr, len);
+
+ return ret;
+}
+
+/***************************************************/
+static char blob_help_text[] =
+ "enc src dst len km - Encapsulate and create blob of data\n"
+ " $len bytes long at address $src and\n"
+ " store the result at address $dst.\n"
+ " $km is the address where the key\n"
+ " modifier is stored.\n"
+ " The modifier is required for generation\n"
+ " /use as key for cryptographic operation.\n"
+ " Key modifier should be 16 byte long.\n"
+ "blob dec src dst len km - Decapsulate the blob of data at address\n"
+ " $src and store result of $len byte at\n"
+ " addr $dst.\n"
+ " $km is the address where the key\n"
+ " modifier is stored.\n"
+ " The modifier is required for generation\n"
+ " /use as key for cryptographic operation.\n"
+ " Key modifier should be 16 byte long.\n";
+
+U_BOOT_CMD(
+ blob, 6, 1, do_blob,
+ "Blob encapsulation/decryption",
+ blob_help_text
+);
diff --git a/roms/u-boot/cmd/bloblist.c b/roms/u-boot/cmd/bloblist.c
new file mode 100644
index 000000000..21e7ff67a
--- /dev/null
+++ b/roms/u-boot/cmd/bloblist.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Command-line access to bloblist features
+ *
+ * Copyright 2020 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bloblist.h>
+#include <command.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int do_bloblist_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bloblist_show_stats();
+
+ return 0;
+}
+
+static int do_bloblist_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bloblist_show_list();
+
+ return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bloblist_help_text[] =
+ "info - show information about the bloblist\n"
+ "bloblist list - list blobs in the bloblist";
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(bloblist, "Bloblists", bloblist_help_text,
+ U_BOOT_SUBCMD_MKENT(info, 1, 1, do_bloblist_info),
+ U_BOOT_SUBCMD_MKENT(list, 1, 1, do_bloblist_list));
diff --git a/roms/u-boot/cmd/bmp.c b/roms/u-boot/cmd/bmp.c
new file mode 100644
index 000000000..6040fa5d9
--- /dev/null
+++ b/roms/u-boot/cmd/bmp.c
@@ -0,0 +1,281 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Detlev Zundel, DENX Software Engineering, dzu@denx.de.
+ */
+
+/*
+ * BMP handling routines
+ */
+
+#include <common.h>
+#include <bmp_layout.h>
+#include <command.h>
+#include <dm.h>
+#include <gzip.h>
+#include <image.h>
+#include <lcd.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <splash.h>
+#include <video.h>
+#include <asm/byteorder.h>
+
+static int bmp_info (ulong addr);
+
+/*
+ * Allocate and decompress a BMP image using gunzip().
+ *
+ * Returns a pointer to the decompressed image data. This pointer is
+ * aligned to 32-bit-aligned-address + 2.
+ * See doc/README.displaying-bmps for explanation.
+ *
+ * The allocation address is passed to 'alloc_addr' and must be freed
+ * by the caller after use.
+ *
+ * Returns NULL if decompression failed, or if the decompressed data
+ * didn't contain a valid BMP signature.
+ */
+#ifdef CONFIG_VIDEO_BMP_GZIP
+struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
+ void **alloc_addr)
+{
+ void *dst;
+ unsigned long len;
+ struct bmp_image *bmp;
+
+ /*
+ * Decompress bmp image
+ */
+ len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
+ /* allocate extra 3 bytes for 32-bit-aligned-address + 2 alignment */
+ dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE + 3);
+ if (dst == NULL) {
+ puts("Error: malloc in gunzip failed!\n");
+ return NULL;
+ }
+
+ bmp = dst;
+
+ /* align to 32-bit-aligned-address + 2 */
+ bmp = (struct bmp_image *)((((uintptr_t)dst + 1) & ~3) + 2);
+
+ if (gunzip(bmp, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, map_sysmem(addr, 0),
+ &len) != 0) {
+ free(dst);
+ return NULL;
+ }
+ if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)
+ puts("Image could be truncated"
+ " (increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
+
+ /*
+ * Check for bmp mark 'BM'
+ */
+ if (!((bmp->header.signature[0] == 'B') &&
+ (bmp->header.signature[1] == 'M'))) {
+ free(dst);
+ return NULL;
+ }
+
+ debug("Gzipped BMP image detected!\n");
+
+ *alloc_addr = dst;
+ return bmp;
+}
+#else
+struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
+ void **alloc_addr)
+{
+ return NULL;
+}
+#endif
+
+static int do_bmp_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr;
+
+ switch (argc) {
+ case 1: /* use image_load_addr as default address */
+ addr = image_load_addr;
+ break;
+ case 2: /* use argument */
+ addr = simple_strtoul(argv[1], NULL, 16);
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ return (bmp_info(addr));
+}
+
+static int do_bmp_display(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr;
+ int x = 0, y = 0;
+
+ splash_get_pos(&x, &y);
+
+ switch (argc) {
+ case 1: /* use image_load_addr as default address */
+ addr = image_load_addr;
+ break;
+ case 2: /* use argument */
+ addr = simple_strtoul(argv[1], NULL, 16);
+ break;
+ case 4:
+ addr = simple_strtoul(argv[1], NULL, 16);
+ if (!strcmp(argv[2], "m"))
+ x = BMP_ALIGN_CENTER;
+ else
+ x = simple_strtoul(argv[2], NULL, 10);
+ if (!strcmp(argv[3], "m"))
+ y = BMP_ALIGN_CENTER;
+ else
+ y = simple_strtoul(argv[3], NULL, 10);
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ return (bmp_display(addr, x, y));
+}
+
+static struct cmd_tbl cmd_bmp_sub[] = {
+ U_BOOT_CMD_MKENT(info, 3, 0, do_bmp_info, "", ""),
+ U_BOOT_CMD_MKENT(display, 5, 0, do_bmp_display, "", ""),
+};
+
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+void bmp_reloc(void) {
+ fixup_cmdtable(cmd_bmp_sub, ARRAY_SIZE(cmd_bmp_sub));
+}
+#endif
+
+/*
+ * Subroutine: do_bmp
+ *
+ * Description: Handler for 'bmp' command..
+ *
+ * Inputs: argv[1] contains the subcommand
+ *
+ * Return: None
+ *
+ */
+static int do_bmp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ /* Strip off leading 'bmp' command argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], &cmd_bmp_sub[0], ARRAY_SIZE(cmd_bmp_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+ bmp, 5, 1, do_bmp,
+ "manipulate BMP image data",
+ "info <imageAddr> - display image info\n"
+ "bmp display <imageAddr> [x y] - display image at x,y"
+);
+
+/*
+ * Subroutine: bmp_info
+ *
+ * Description: Show information about bmp file in memory
+ *
+ * Inputs: addr address of the bmp file
+ *
+ * Return: None
+ *
+ */
+static int bmp_info(ulong addr)
+{
+ struct bmp_image *bmp = (struct bmp_image *)map_sysmem(addr, 0);
+ void *bmp_alloc_addr = NULL;
+ unsigned long len;
+
+ if (!((bmp->header.signature[0]=='B') &&
+ (bmp->header.signature[1]=='M')))
+ bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr);
+
+ if (bmp == NULL) {
+ printf("There is no valid bmp file at the given address\n");
+ return 1;
+ }
+
+ printf("Image size : %d x %d\n", le32_to_cpu(bmp->header.width),
+ le32_to_cpu(bmp->header.height));
+ printf("Bits per pixel: %d\n", le16_to_cpu(bmp->header.bit_count));
+ printf("Compression : %d\n", le32_to_cpu(bmp->header.compression));
+
+ if (bmp_alloc_addr)
+ free(bmp_alloc_addr);
+
+ return(0);
+}
+
+/*
+ * Subroutine: bmp_display
+ *
+ * Description: Display bmp file located in memory
+ *
+ * Inputs: addr address of the bmp file
+ *
+ * Return: None
+ *
+ */
+int bmp_display(ulong addr, int x, int y)
+{
+#ifdef CONFIG_DM_VIDEO
+ struct udevice *dev;
+#endif
+ int ret;
+ struct bmp_image *bmp = map_sysmem(addr, 0);
+ void *bmp_alloc_addr = NULL;
+ unsigned long len;
+
+ if (!((bmp->header.signature[0]=='B') &&
+ (bmp->header.signature[1]=='M')))
+ bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr);
+
+ if (!bmp) {
+ printf("There is no valid bmp file at the given address\n");
+ return 1;
+ }
+ addr = map_to_sysmem(bmp);
+
+#ifdef CONFIG_DM_VIDEO
+ ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
+ if (!ret) {
+ bool align = false;
+
+ if (CONFIG_IS_ENABLED(SPLASH_SCREEN_ALIGN) ||
+ x == BMP_ALIGN_CENTER ||
+ y == BMP_ALIGN_CENTER)
+ align = true;
+
+ ret = video_bmp_display(dev, addr, x, y, align);
+ }
+#elif defined(CONFIG_LCD)
+ ret = lcd_display_bitmap(addr, x, y);
+#elif defined(CONFIG_VIDEO)
+ ret = video_display_bitmap(addr, x, y);
+#else
+# error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO
+#endif
+
+ if (bmp_alloc_addr)
+ free(bmp_alloc_addr);
+
+ return ret ? CMD_RET_FAILURE : 0;
+}
diff --git a/roms/u-boot/cmd/boot.c b/roms/u-boot/cmd/boot.c
new file mode 100644
index 000000000..b84c0ed89
--- /dev/null
+++ b/roms/u-boot/cmd/boot.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Misc boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+
+#ifdef CONFIG_CMD_GO
+
+/* Allow ports to override the default behavior */
+__attribute__((weak))
+unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
+ char *const argv[])
+{
+ return entry (argc, argv);
+}
+
+static int do_go(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong addr, rc;
+ int rcode = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[1], NULL, 16);
+
+ printf ("## Starting application at 0x%08lX ...\n", addr);
+
+ /*
+ * pass address parameter as argv[0] (aka command name),
+ * and all remaining args
+ */
+ rc = do_go_exec ((void *)addr, argc - 1, argv + 1);
+ if (rc != 0) rcode = 1;
+
+ printf ("## Application terminated, rc = 0x%lX\n", rc);
+ return rcode;
+}
+
+/* -------------------------------------------------------------------- */
+
+U_BOOT_CMD(
+ go, CONFIG_SYS_MAXARGS, 1, do_go,
+ "start application at address 'addr'",
+ "addr [arg ...]\n - start application at address 'addr'\n"
+ " passing 'arg' as arguments"
+);
+
+#endif
+
+U_BOOT_CMD(
+ reset, 2, 0, do_reset,
+ "Perform RESET of the CPU",
+ ""
+);
+
+#ifdef CONFIG_CMD_POWEROFF
+U_BOOT_CMD(
+ poweroff, 1, 0, do_poweroff,
+ "Perform POWEROFF of the device",
+ ""
+);
+#endif
diff --git a/roms/u-boot/cmd/bootcount.c b/roms/u-boot/cmd/bootcount.c
new file mode 100644
index 000000000..654bbb805
--- /dev/null
+++ b/roms/u-boot/cmd/bootcount.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <command.h>
+#include <bootcount.h>
+
+static int do_bootcount_print(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ printf("%lu\n", bootcount_load());
+ return CMD_RET_SUCCESS;
+}
+
+static int do_bootcount_reset(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ /*
+ * note that we're explicitly not resetting the environment
+ * variable, so you still have the old bootcounter available
+ */
+ bootcount_store(0);
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl bootcount_sub[] = {
+ U_BOOT_CMD_MKENT(print, 1, 1, do_bootcount_print, "", ""),
+ U_BOOT_CMD_MKENT(reset, 1, 1, do_bootcount_reset, "", ""),
+};
+
+static int do_bootcount(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* drop initial "bootcount" arg */
+ argc--;
+ argv++;
+
+ cp = find_cmd_tbl(argv[0], bootcount_sub, ARRAY_SIZE(bootcount_sub));
+ if (cp)
+ return cp->cmd(cmdtp, flag, argc, argv);
+
+ return CMD_RET_USAGE;
+}
+
+#if CONFIG_IS_ENABLED(SYS_LONGHELP)
+static char bootcount_help_text[] =
+ "print - print current bootcounter\n"
+ "reset - reset the bootcounter"
+ ;
+#endif
+
+U_BOOT_CMD(bootcount, 2, 1, do_bootcount,
+ "bootcount",
+#if CONFIG_IS_ENABLED(SYS_LONGHELP)
+ bootcount_help_text
+#endif
+);
diff --git a/roms/u-boot/cmd/bootefi.c b/roms/u-boot/cmd/bootefi.c
new file mode 100644
index 000000000..cba81ffe7
--- /dev/null
+++ b/roms/u-boot/cmd/bootefi.c
@@ -0,0 +1,684 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI application loader
+ *
+ * Copyright (c) 2016 Alexander Graf
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+
+#include <common.h>
+#include <bootm.h>
+#include <charset.h>
+#include <command.h>
+#include <dm.h>
+#include <efi_loader.h>
+#include <efi_selftest.h>
+#include <env.h>
+#include <errno.h>
+#include <image.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <linux/libfdt.h>
+#include <linux/libfdt_env.h>
+#include <mapmem.h>
+#include <memalign.h>
+#include <asm-generic/sections.h>
+#include <linux/linkage.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct efi_device_path *bootefi_image_path;
+static struct efi_device_path *bootefi_device_path;
+static void *image_addr;
+static size_t image_size;
+
+/**
+ * efi_clear_bootdev() - clear boot device
+ */
+static void efi_clear_bootdev(void)
+{
+ efi_free_pool(bootefi_device_path);
+ efi_free_pool(bootefi_image_path);
+ bootefi_device_path = NULL;
+ bootefi_image_path = NULL;
+ image_addr = NULL;
+ image_size = 0;
+}
+
+/**
+ * efi_set_bootdev() - set boot device
+ *
+ * This function is called when a file is loaded, e.g. via the 'load' command.
+ * We use the path to this file to inform the UEFI binary about the boot device.
+ *
+ * @dev: device, e.g. "MMC"
+ * @devnr: number of the device, e.g. "1:2"
+ * @path: path to file loaded
+ * @buffer: buffer with file loaded
+ * @buffer_size: size of file loaded
+ */
+void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
+ void *buffer, size_t buffer_size)
+{
+ struct efi_device_path *device, *image;
+ efi_status_t ret;
+
+ /* Forget overwritten image */
+ if (buffer + buffer_size >= image_addr &&
+ image_addr + image_size >= buffer)
+ efi_clear_bootdev();
+
+ /* Remember only PE-COFF and FIT images */
+ if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) {
+#ifdef CONFIG_FIT
+ if (fit_check_format(buffer, IMAGE_SIZE_INVAL))
+ return;
+ /*
+ * FIT images of type EFI_OS are started via command bootm.
+ * We should not use their boot device with the bootefi command.
+ */
+ buffer = 0;
+ buffer_size = 0;
+#else
+ return;
+#endif
+ }
+
+ /* efi_set_bootdev() is typically called repeatedly, recover memory */
+ efi_clear_bootdev();
+
+ image_addr = buffer;
+ image_size = buffer_size;
+
+ ret = efi_dp_from_name(dev, devnr, path, &device, &image);
+ if (ret == EFI_SUCCESS) {
+ bootefi_device_path = device;
+ if (image) {
+ /* FIXME: image should not contain device */
+ struct efi_device_path *image_tmp = image;
+
+ efi_dp_split_file_path(image, &device, &image);
+ efi_free_pool(image_tmp);
+ }
+ bootefi_image_path = image;
+ } else {
+ efi_clear_bootdev();
+ }
+}
+
+/**
+ * efi_env_set_load_options() - set load options from environment variable
+ *
+ * @handle: the image handle
+ * @env_var: name of the environment variable
+ * @load_options: pointer to load options (output)
+ * Return: status code
+ */
+static efi_status_t efi_env_set_load_options(efi_handle_t handle,
+ const char *env_var,
+ u16 **load_options)
+{
+ const char *env = env_get(env_var);
+ size_t size;
+ u16 *pos;
+ efi_status_t ret;
+
+ *load_options = NULL;
+ if (!env)
+ return EFI_SUCCESS;
+ size = sizeof(u16) * (utf8_utf16_strlen(env) + 1);
+ pos = calloc(size, 1);
+ if (!pos)
+ return EFI_OUT_OF_RESOURCES;
+ *load_options = pos;
+ utf8_utf16_strcpy(&pos, env);
+ ret = efi_set_load_options(handle, size, *load_options);
+ if (ret != EFI_SUCCESS) {
+ free(*load_options);
+ *load_options = NULL;
+ }
+ return ret;
+}
+
+#if !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+
+/**
+ * copy_fdt() - Copy the device tree to a new location available to EFI
+ *
+ * The FDT is copied to a suitable location within the EFI memory map.
+ * Additional 12 KiB are added to the space in case the device tree needs to be
+ * expanded later with fdt_open_into().
+ *
+ * @fdtp: On entry a pointer to the flattened device tree.
+ * On exit a pointer to the copy of the flattened device tree.
+ * FDT start
+ * Return: status code
+ */
+static efi_status_t copy_fdt(void **fdtp)
+{
+ unsigned long fdt_ram_start = -1L, fdt_pages;
+ efi_status_t ret = 0;
+ void *fdt, *new_fdt;
+ u64 new_fdt_addr;
+ uint fdt_size;
+ int i;
+
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+ u64 ram_start = gd->bd->bi_dram[i].start;
+ u64 ram_size = gd->bd->bi_dram[i].size;
+
+ if (!ram_size)
+ continue;
+
+ if (ram_start < fdt_ram_start)
+ fdt_ram_start = ram_start;
+ }
+
+ /*
+ * Give us at least 12 KiB of breathing room in case the device tree
+ * needs to be expanded later.
+ */
+ fdt = *fdtp;
+ fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
+ fdt_size = fdt_pages << EFI_PAGE_SHIFT;
+
+ /*
+ * Safe fdt location is at 127 MiB.
+ * On the sandbox convert from the sandbox address space.
+ */
+ new_fdt_addr = (uintptr_t)map_sysmem(fdt_ram_start + 0x7f00000 +
+ fdt_size, 0);
+ ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
+ EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
+ &new_fdt_addr);
+ if (ret != EFI_SUCCESS) {
+ /* If we can't put it there, put it somewhere */
+ new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size);
+ ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
+ EFI_ACPI_RECLAIM_MEMORY, fdt_pages,
+ &new_fdt_addr);
+ if (ret != EFI_SUCCESS) {
+ log_err("ERROR: Failed to reserve space for FDT\n");
+ goto done;
+ }
+ }
+ new_fdt = (void *)(uintptr_t)new_fdt_addr;
+ memcpy(new_fdt, fdt, fdt_totalsize(fdt));
+ fdt_set_totalsize(new_fdt, fdt_size);
+
+ *fdtp = (void *)(uintptr_t)new_fdt_addr;
+done:
+ return ret;
+}
+
+/**
+ * get_config_table() - get configuration table
+ *
+ * @guid: GUID of the configuration table
+ * Return: pointer to configuration table or NULL
+ */
+static void *get_config_table(const efi_guid_t *guid)
+{
+ size_t i;
+
+ for (i = 0; i < systab.nr_tables; i++) {
+ if (!guidcmp(guid, &systab.tables[i].guid))
+ return systab.tables[i].table;
+ }
+ return NULL;
+}
+
+#endif /* !CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) */
+
+/**
+ * efi_install_fdt() - install device tree
+ *
+ * If fdt is not EFI_FDT_USE_INTERNAL, the device tree located at that memory
+ * address will will be installed as configuration table, otherwise the device
+ * tree located at the address indicated by environment variable fdt_addr or as
+ * fallback fdtcontroladdr will be used.
+ *
+ * On architectures using ACPI tables device trees shall not be installed as
+ * configuration table.
+ *
+ * @fdt: address of device tree or EFI_FDT_USE_INTERNAL to use the
+ * the hardware device tree as indicated by environment variable
+ * fdt_addr or as fallback the internal device tree as indicated by
+ * the environment variable fdtcontroladdr
+ * Return: status code
+ */
+efi_status_t efi_install_fdt(void *fdt)
+{
+ /*
+ * The EBBR spec requires that we have either an FDT or an ACPI table
+ * but not both.
+ */
+#if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE)
+ if (fdt) {
+ log_err("ERROR: can't have ACPI table and device tree.\n");
+ return EFI_LOAD_ERROR;
+ }
+#else
+ bootm_headers_t img = { 0 };
+ efi_status_t ret;
+
+ if (fdt == EFI_FDT_USE_INTERNAL) {
+ const char *fdt_opt;
+ uintptr_t fdt_addr;
+
+ /* Look for device tree that is already installed */
+ if (get_config_table(&efi_guid_fdt))
+ return EFI_SUCCESS;
+ /* Check if there is a hardware device tree */
+ fdt_opt = env_get("fdt_addr");
+ /* Use our own device tree as fallback */
+ if (!fdt_opt) {
+ fdt_opt = env_get("fdtcontroladdr");
+ if (!fdt_opt) {
+ log_err("ERROR: need device tree\n");
+ return EFI_NOT_FOUND;
+ }
+ }
+ fdt_addr = simple_strtoul(fdt_opt, NULL, 16);
+ if (!fdt_addr) {
+ log_err("ERROR: invalid $fdt_addr or $fdtcontroladdr\n");
+ return EFI_LOAD_ERROR;
+ }
+ fdt = map_sysmem(fdt_addr, 0);
+ }
+
+ /* Install device tree */
+ if (fdt_check_header(fdt)) {
+ log_err("ERROR: invalid device tree\n");
+ return EFI_LOAD_ERROR;
+ }
+
+ /* Prepare device tree for payload */
+ ret = copy_fdt(&fdt);
+ if (ret) {
+ log_err("ERROR: out of memory\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (image_setup_libfdt(&img, fdt, 0, NULL)) {
+ log_err("ERROR: failed to process device tree\n");
+ return EFI_LOAD_ERROR;
+ }
+
+ /* Create memory reservations as indicated by the device tree */
+ efi_carve_out_dt_rsv(fdt);
+
+ /* Install device tree as UEFI table */
+ ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
+ if (ret != EFI_SUCCESS) {
+ log_err("ERROR: failed to install device tree\n");
+ return ret;
+ }
+#endif /* GENERATE_ACPI_TABLE */
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * do_bootefi_exec() - execute EFI binary
+ *
+ * The image indicated by @handle is started. When it returns the allocated
+ * memory for the @load_options is freed.
+ *
+ * @handle: handle of loaded image
+ * @load_options: load options
+ * Return: status code
+ *
+ * Load the EFI binary into a newly assigned memory unwinding the relocation
+ * information, install the loaded image protocol, and call the binary.
+ */
+static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options)
+{
+ efi_status_t ret;
+ efi_uintn_t exit_data_size = 0;
+ u16 *exit_data = NULL;
+
+ /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
+ switch_to_non_secure_mode();
+
+ /* Call our payload! */
+ ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
+ if (ret != EFI_SUCCESS) {
+ log_err("## Application failed, r = %lu\n",
+ ret & ~EFI_ERROR_MASK);
+ if (exit_data) {
+ log_err("## %ls\n", exit_data);
+ efi_free_pool(exit_data);
+ }
+ }
+
+ efi_restore_gd();
+
+ free(load_options);
+
+ if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD))
+ efi_initrd_deregister();
+
+ return ret;
+}
+
+/**
+ * do_efibootmgr() - execute EFI boot manager
+ *
+ * Return: status code
+ */
+static int do_efibootmgr(void)
+{
+ efi_handle_t handle;
+ efi_status_t ret;
+ void *load_options;
+
+ ret = efi_bootmgr_load(&handle, &load_options);
+ if (ret != EFI_SUCCESS) {
+ log_notice("EFI boot manager: Cannot load any image\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = do_bootefi_exec(handle, load_options);
+
+ if (ret != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_bootefi_image() - execute EFI binary
+ *
+ * Set up memory image for the binary to be loaded, prepare device path, and
+ * then call do_bootefi_exec() to execute it.
+ *
+ * @image_opt: string of image start address
+ * Return: status code
+ */
+static int do_bootefi_image(const char *image_opt)
+{
+ void *image_buf;
+ unsigned long addr, size;
+ efi_status_t ret;
+
+#ifdef CONFIG_CMD_BOOTEFI_HELLO
+ if (!strcmp(image_opt, "hello")) {
+ image_buf = __efi_helloworld_begin;
+ size = __efi_helloworld_end - __efi_helloworld_begin;
+ efi_clear_bootdev();
+ } else
+#endif
+ {
+ addr = strtoul(image_opt, NULL, 16);
+ /* Check that a numeric value was passed */
+ if (!addr)
+ return CMD_RET_USAGE;
+
+ image_buf = map_sysmem(addr, 0);
+
+ if (image_buf != image_addr) {
+ log_err("No UEFI binary known at %s\n", image_opt);
+ return CMD_RET_FAILURE;
+ }
+ size = image_size;
+ }
+ ret = efi_run_image(image_buf, size);
+
+ if (ret != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * efi_run_image() - run loaded UEFI image
+ *
+ * @source_buffer: memory address of the UEFI image
+ * @source_size: size of the UEFI image
+ * Return: status code
+ */
+efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size)
+{
+ efi_handle_t mem_handle = NULL, handle;
+ struct efi_device_path *file_path = NULL;
+ struct efi_device_path *msg_path;
+ efi_status_t ret;
+ u16 *load_options;
+
+ if (!bootefi_device_path || !bootefi_image_path) {
+ /*
+ * Special case for efi payload not loaded from disk,
+ * such as 'bootefi hello' or for example payload
+ * loaded directly into memory via JTAG, etc:
+ */
+ file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
+ (uintptr_t)source_buffer,
+ source_size);
+ /*
+ * Make sure that device for device_path exist
+ * in load_image(). Otherwise, shell and grub will fail.
+ */
+ ret = efi_create_handle(&mem_handle);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ ret = efi_add_protocol(mem_handle, &efi_guid_device_path,
+ file_path);
+ if (ret != EFI_SUCCESS)
+ goto out;
+ msg_path = file_path;
+ } else {
+ file_path = efi_dp_append(bootefi_device_path,
+ bootefi_image_path);
+ msg_path = bootefi_image_path;
+ }
+
+ log_info("Booting %pD\n", msg_path);
+
+ ret = EFI_CALL(efi_load_image(false, efi_root, file_path, source_buffer,
+ source_size, &handle));
+ if (ret != EFI_SUCCESS) {
+ log_err("Loading image failed\n");
+ goto out;
+ }
+
+ /* Transfer environment variable as load options */
+ ret = efi_env_set_load_options(handle, "bootargs", &load_options);
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ ret = do_bootefi_exec(handle, load_options);
+
+out:
+ efi_delete_handle(mem_handle);
+ efi_free_pool(file_path);
+ return ret;
+}
+
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+static efi_status_t bootefi_run_prepare(const char *load_options_path,
+ struct efi_device_path *device_path,
+ struct efi_device_path *image_path,
+ struct efi_loaded_image_obj **image_objp,
+ struct efi_loaded_image **loaded_image_infop)
+{
+ efi_status_t ret;
+ u16 *load_options;
+
+ ret = efi_setup_loaded_image(device_path, image_path, image_objp,
+ loaded_image_infop);
+ if (ret != EFI_SUCCESS)
+ return ret;
+
+ /* Transfer environment variable as load options */
+ return efi_env_set_load_options((efi_handle_t)*image_objp,
+ load_options_path,
+ &load_options);
+}
+
+/**
+ * bootefi_test_prepare() - prepare to run an EFI test
+ *
+ * Prepare to run a test as if it were provided by a loaded image.
+ *
+ * @image_objp: pointer to be set to the loaded image handle
+ * @loaded_image_infop: pointer to be set to the loaded image protocol
+ * @path: dummy file path used to construct the device path
+ * set in the loaded image protocol
+ * @load_options_path: name of a U-Boot environment variable. Its value is
+ * set as load options in the loaded image protocol.
+ * Return: status code
+ */
+static efi_status_t bootefi_test_prepare
+ (struct efi_loaded_image_obj **image_objp,
+ struct efi_loaded_image **loaded_image_infop, const char *path,
+ const char *load_options_path)
+{
+ efi_status_t ret;
+
+ /* Construct a dummy device path */
+ bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 0, 0);
+ if (!bootefi_device_path)
+ return EFI_OUT_OF_RESOURCES;
+
+ bootefi_image_path = efi_dp_from_file(NULL, 0, path);
+ if (!bootefi_image_path) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto failure;
+ }
+
+ ret = bootefi_run_prepare(load_options_path, bootefi_device_path,
+ bootefi_image_path, image_objp,
+ loaded_image_infop);
+ if (ret == EFI_SUCCESS)
+ return ret;
+
+failure:
+ efi_clear_bootdev();
+ return ret;
+}
+
+/**
+ * bootefi_run_finish() - finish up after running an EFI test
+ *
+ * @loaded_image_info: Pointer to a struct which holds the loaded image info
+ * @image_obj: Pointer to a struct which holds the loaded image object
+ */
+static void bootefi_run_finish(struct efi_loaded_image_obj *image_obj,
+ struct efi_loaded_image *loaded_image_info)
+{
+ efi_restore_gd();
+ free(loaded_image_info->load_options);
+ efi_delete_handle(&image_obj->header);
+}
+
+/**
+ * do_efi_selftest() - execute EFI selftest
+ *
+ * Return: status code
+ */
+static int do_efi_selftest(void)
+{
+ struct efi_loaded_image_obj *image_obj;
+ struct efi_loaded_image *loaded_image_info;
+ efi_status_t ret;
+
+ ret = bootefi_test_prepare(&image_obj, &loaded_image_info,
+ "\\selftest", "efi_selftest");
+ if (ret != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+
+ /* Execute the test */
+ ret = EFI_CALL(efi_selftest(&image_obj->header, &systab));
+ bootefi_run_finish(image_obj, loaded_image_info);
+
+ return ret != EFI_SUCCESS;
+}
+#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */
+
+/**
+ * do_bootefi() - execute `bootefi` command
+ *
+ * @cmdtp: table entry describing command
+ * @flag: bitmap indicating how the command was invoked
+ * @argc: number of arguments
+ * @argv: command line arguments
+ * Return: status code
+ */
+static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ efi_status_t ret;
+ void *fdt;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* Initialize EFI drivers */
+ ret = efi_init_obj_list();
+ if (ret != EFI_SUCCESS) {
+ log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
+ ret & ~EFI_ERROR_MASK);
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc > 2) {
+ uintptr_t fdt_addr;
+
+ fdt_addr = simple_strtoul(argv[2], NULL, 16);
+ fdt = map_sysmem(fdt_addr, 0);
+ } else {
+ fdt = EFI_FDT_USE_INTERNAL;
+ }
+ ret = efi_install_fdt(fdt);
+ if (ret == EFI_INVALID_PARAMETER)
+ return CMD_RET_USAGE;
+ else if (ret != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+
+ if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) {
+ if (!strcmp(argv[1], "bootmgr"))
+ return do_efibootmgr();
+ }
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+ if (!strcmp(argv[1], "selftest"))
+ return do_efi_selftest();
+#endif
+
+ return do_bootefi_image(argv[1]);
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bootefi_help_text[] =
+ "<image address> [fdt address]\n"
+ " - boot EFI payload stored at address <image address>.\n"
+ " If specified, the device tree located at <fdt address> gets\n"
+ " exposed as EFI configuration table.\n"
+#ifdef CONFIG_CMD_BOOTEFI_HELLO
+ "bootefi hello\n"
+ " - boot a sample Hello World application stored within U-Boot\n"
+#endif
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+ "bootefi selftest [fdt address]\n"
+ " - boot an EFI selftest application stored within U-Boot\n"
+ " Use environment variable efi_selftest to select a single test.\n"
+ " Use 'setenv efi_selftest list' to enumerate all tests.\n"
+#endif
+#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
+ "bootefi bootmgr [fdt address]\n"
+ " - load and boot EFI payload based on BootOrder/BootXXXX variables.\n"
+ "\n"
+ " If specified, the device tree located at <fdt address> gets\n"
+ " exposed as EFI configuration table.\n"
+#endif
+ ;
+#endif
+
+U_BOOT_CMD(
+ bootefi, 3, 0, do_bootefi,
+ "Boots an EFI payload from memory",
+ bootefi_help_text
+);
diff --git a/roms/u-boot/cmd/booti.c b/roms/u-boot/cmd/booti.c
new file mode 100644
index 000000000..3df70ea9c
--- /dev/null
+++ b/roms/u-boot/cmd/booti.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <bootm.h>
+#include <command.h>
+#include <image.h>
+#include <irq_func.h>
+#include <lmb.h>
+#include <log.h>
+#include <mapmem.h>
+#include <asm/global_data.h>
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+/*
+ * Image booting support
+ */
+static int booti_start(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[], bootm_headers_t *images)
+{
+ int ret;
+ ulong ld;
+ ulong relocated_addr;
+ ulong image_size;
+ uint8_t *temp;
+ ulong dest;
+ ulong dest_end;
+ unsigned long comp_len;
+ unsigned long decomp_len;
+ int ctype;
+
+ ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
+ images, 1);
+
+ /* Setup Linux kernel Image entry point */
+ if (!argc) {
+ ld = image_load_addr;
+ debug("* kernel: default image load address = 0x%08lx\n",
+ image_load_addr);
+ } else {
+ ld = simple_strtoul(argv[0], NULL, 16);
+ debug("* kernel: cmdline image address = 0x%08lx\n", ld);
+ }
+
+ temp = map_sysmem(ld, 0);
+ ctype = image_decomp_type(temp, 2);
+ if (ctype > 0) {
+ dest = env_get_ulong("kernel_comp_addr_r", 16, 0);
+ comp_len = env_get_ulong("kernel_comp_size", 16, 0);
+ if (!dest || !comp_len) {
+ puts("kernel_comp_addr_r or kernel_comp_size is not provided!\n");
+ return -EINVAL;
+ }
+ if (dest < gd->ram_base || dest > gd->ram_top) {
+ puts("kernel_comp_addr_r is outside of DRAM range!\n");
+ return -EINVAL;
+ }
+
+ debug("kernel image compression type %d size = 0x%08lx address = 0x%08lx\n",
+ ctype, comp_len, (ulong)dest);
+ decomp_len = comp_len * 10;
+ ret = image_decomp(ctype, 0, ld, IH_TYPE_KERNEL,
+ (void *)dest, (void *)ld, comp_len,
+ decomp_len, &dest_end);
+ if (ret)
+ return ret;
+ /* dest_end contains the uncompressed Image size */
+ memmove((void *) ld, (void *)dest, dest_end);
+ }
+ unmap_sysmem((void *)ld);
+
+ ret = booti_setup(ld, &relocated_addr, &image_size, false);
+ if (ret != 0)
+ return 1;
+
+ /* Handle BOOTM_STATE_LOADOS */
+ if (relocated_addr != ld) {
+ printf("Moving Image from 0x%lx to 0x%lx, end=%lx\n", ld,
+ relocated_addr, relocated_addr + image_size);
+ memmove((void *)relocated_addr, (void *)ld, image_size);
+ }
+
+ images->ep = relocated_addr;
+ images->os.start = relocated_addr;
+ images->os.end = relocated_addr + image_size;
+
+ lmb_reserve(&images->lmb, images->ep, le32_to_cpu(image_size));
+
+ /*
+ * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
+ * have a header that provide this informaiton.
+ */
+ if (bootm_find_images(flag, argc, argv, relocated_addr, image_size))
+ return 1;
+
+ return 0;
+}
+
+int do_booti(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int ret;
+
+ /* Consume 'booti' */
+ argc--; argv++;
+
+ if (booti_start(cmdtp, flag, argc, argv, &images))
+ return 1;
+
+ /*
+ * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
+ * disable interrupts ourselves
+ */
+ bootm_disable_interrupts();
+
+ images.os.os = IH_OS_LINUX;
+#ifdef CONFIG_RISCV_SMODE
+ images.os.arch = IH_ARCH_RISCV;
+#elif CONFIG_ARM64
+ images.os.arch = IH_ARCH_ARM64;
+#endif
+ ret = do_bootm_states(cmdtp, flag, argc, argv,
+#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
+ BOOTM_STATE_RAMDISK |
+#endif
+ BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
+ BOOTM_STATE_OS_GO,
+ &images, 1);
+
+ return ret;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char booti_help_text[] =
+ "[addr [initrd[:size]] [fdt]]\n"
+ " - boot Linux flat or compressed 'Image' stored at 'addr'\n"
+ "\tThe argument 'initrd' is optional and specifies the address\n"
+ "\tof an initrd in memory. The optional parameter ':size' allows\n"
+ "\tspecifying the size of a RAW initrd.\n"
+ "\tCurrently only booting from gz, bz2, lzma and lz4 compression\n"
+ "\ttypes are supported. In order to boot from any of these compressed\n"
+ "\timages, user have to set kernel_comp_addr_r and kernel_comp_size environment\n"
+ "\tvariables beforehand.\n"
+#if defined(CONFIG_OF_LIBFDT)
+ "\tSince booting a Linux kernel requires a flat device-tree, a\n"
+ "\tthird argument providing the address of the device-tree blob\n"
+ "\tis required. To boot a kernel with a device-tree blob but\n"
+ "\twithout an initrd image, use a '-' for the initrd argument.\n"
+#endif
+ "";
+#endif
+
+U_BOOT_CMD(
+ booti, CONFIG_SYS_MAXARGS, 1, do_booti,
+ "boot Linux kernel 'Image' format from memory", booti_help_text
+);
diff --git a/roms/u-boot/cmd/bootm.c b/roms/u-boot/cmd/bootm.c
new file mode 100644
index 000000000..81c6b9397
--- /dev/null
+++ b/roms/u-boot/cmd/bootm.c
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <bootm.h>
+#include <command.h>
+#include <env.h>
+#include <errno.h>
+#include <image.h>
+#include <malloc.h>
+#include <nand.h>
+#include <asm/byteorder.h>
+#include <asm/global_data.h>
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <u-boot/zlib.h>
+#include <mapmem.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CMD_IMI)
+static int image_info(unsigned long addr);
+#endif
+
+#if defined(CONFIG_CMD_IMLS)
+#include <flash.h>
+#include <mtd/cfi_flash.h>
+extern flash_info_t flash_info[]; /* info for FLASH chips */
+#endif
+
+#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
+static int do_imls(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+#endif
+
+/* we overload the cmd field with our state machine info instead of a
+ * function pointer */
+static struct cmd_tbl cmd_bootm_sub[] = {
+ U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
+ U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
+#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
+ U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
+#endif
+#ifdef CONFIG_OF_LIBFDT
+ U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
+ U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
+ U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
+ U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
+ U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
+};
+
+static int do_bootm_subcommand(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret = 0;
+ long state;
+ struct cmd_tbl *c;
+
+ c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
+ argc--; argv++;
+
+ if (c) {
+ state = (long)c->cmd;
+ if (state == BOOTM_STATE_START)
+ state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
+ } else {
+ /* Unrecognized command */
+ return CMD_RET_USAGE;
+ }
+
+ if (((state & BOOTM_STATE_START) != BOOTM_STATE_START) &&
+ images.state >= state) {
+ printf("Trying to execute a command out of order\n");
+ return CMD_RET_USAGE;
+ }
+
+ ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
+
+ return ret;
+}
+
+/*******************************************************************/
+/* bootm - boot application image from image in memory */
+/*******************************************************************/
+
+int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+ static int relocated = 0;
+
+ if (!relocated) {
+ int i;
+
+ /* relocate names of sub-command table */
+ for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
+ cmd_bootm_sub[i].name += gd->reloc_off;
+
+ relocated = 1;
+ }
+#endif
+
+ /* determine if we have a sub command */
+ argc--; argv++;
+ if (argc > 0) {
+ char *endp;
+
+ simple_strtoul(argv[0], &endp, 16);
+ /* endp pointing to NULL means that argv[0] was just a
+ * valid number, pass it along to the normal bootm processing
+ *
+ * If endp is ':' or '#' assume a FIT identifier so pass
+ * along for normal processing.
+ *
+ * Right now we assume the first arg should never be '-'
+ */
+ if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
+ return do_bootm_subcommand(cmdtp, flag, argc, argv);
+ }
+
+ return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
+ BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
+ BOOTM_STATE_LOADOS |
+#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
+ BOOTM_STATE_RAMDISK |
+#endif
+#if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
+ BOOTM_STATE_OS_CMDLINE |
+#endif
+ BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
+ BOOTM_STATE_OS_GO, &images, 1);
+}
+
+int bootm_maybe_autostart(struct cmd_tbl *cmdtp, const char *cmd)
+{
+ const char *ep = env_get("autostart");
+
+ if (ep && !strcmp(ep, "yes")) {
+ char *local_args[2];
+ local_args[0] = (char *)cmd;
+ local_args[1] = NULL;
+ printf("Automatic boot of image at addr 0x%08lX ...\n",
+ image_load_addr);
+ return do_bootm(cmdtp, 0, 1, local_args);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bootm_help_text[] =
+ "[addr [arg ...]]\n - boot application image stored in memory\n"
+ "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
+ "\t'arg' can be the address of an initrd image\n"
+#if defined(CONFIG_OF_LIBFDT)
+ "\tWhen booting a Linux kernel which requires a flat device-tree\n"
+ "\ta third argument is required which is the address of the\n"
+ "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
+ "\tuse a '-' for the second argument. If you do not pass a third\n"
+ "\ta bd_info struct will be passed instead\n"
+#endif
+#if defined(CONFIG_FIT)
+ "\t\nFor the new multi component uImage format (FIT) addresses\n"
+ "\tmust be extended to include component or configuration unit name:\n"
+ "\taddr:<subimg_uname> - direct component image specification\n"
+ "\taddr#<conf_uname> - configuration specification\n"
+ "\tUse iminfo command to get the list of existing component\n"
+ "\timages and configurations.\n"
+#endif
+ "\nSub-commands to do part of the bootm sequence. The sub-commands "
+ "must be\n"
+ "issued in the order below (it's ok to not issue all sub-commands):\n"
+ "\tstart [addr [arg ...]]\n"
+ "\tloados - load OS image\n"
+#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
+ "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
+#endif
+#if defined(CONFIG_OF_LIBFDT)
+ "\tfdt - relocate flat device tree\n"
+#endif
+ "\tcmdline - OS specific command line processing/setup\n"
+ "\tbdt - OS specific bd_info processing\n"
+ "\tprep - OS specific prep before relocation or go\n"
+#if defined(CONFIG_TRACE)
+ "\tfake - OS specific fake start without go\n"
+#endif
+ "\tgo - start OS";
+#endif
+
+U_BOOT_CMD(
+ bootm, CONFIG_SYS_MAXARGS, 1, do_bootm,
+ "boot application image from memory", bootm_help_text
+);
+
+/*******************************************************************/
+/* bootd - boot default image */
+/*******************************************************************/
+#if defined(CONFIG_CMD_BOOTD)
+int do_bootd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return run_command(env_get("bootcmd"), flag);
+}
+
+U_BOOT_CMD(
+ boot, 1, 1, do_bootd,
+ "boot default, i.e., run 'bootcmd'",
+ ""
+);
+
+/* keep old command name "bootd" for backward compatibility */
+U_BOOT_CMD(
+ bootd, 1, 1, do_bootd,
+ "boot default, i.e., run 'bootcmd'",
+ ""
+);
+
+#endif
+
+
+/*******************************************************************/
+/* iminfo - print header info for a requested image */
+/*******************************************************************/
+#if defined(CONFIG_CMD_IMI)
+static int do_iminfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int arg;
+ ulong addr;
+ int rcode = 0;
+
+ if (argc < 2) {
+ return image_info(image_load_addr);
+ }
+
+ for (arg = 1; arg < argc; ++arg) {
+ addr = simple_strtoul(argv[arg], NULL, 16);
+ if (image_info(addr) != 0)
+ rcode = 1;
+ }
+ return rcode;
+}
+
+static int image_info(ulong addr)
+{
+ void *hdr = (void *)map_sysmem(addr, 0);
+
+ printf("\n## Checking Image at %08lx ...\n", addr);
+
+ switch (genimg_get_format(hdr)) {
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ case IMAGE_FORMAT_LEGACY:
+ puts(" Legacy image found\n");
+ if (!image_check_magic(hdr)) {
+ puts(" Bad Magic Number\n");
+ unmap_sysmem(hdr);
+ return 1;
+ }
+
+ if (!image_check_hcrc(hdr)) {
+ puts(" Bad Header Checksum\n");
+ unmap_sysmem(hdr);
+ return 1;
+ }
+
+ image_print_contents(hdr);
+
+ puts(" Verifying Checksum ... ");
+ if (!image_check_dcrc(hdr)) {
+ puts(" Bad Data CRC\n");
+ unmap_sysmem(hdr);
+ return 1;
+ }
+ puts("OK\n");
+ unmap_sysmem(hdr);
+ return 0;
+#endif
+#if defined(CONFIG_ANDROID_BOOT_IMAGE)
+ case IMAGE_FORMAT_ANDROID:
+ puts(" Android image found\n");
+ android_print_contents(hdr);
+ unmap_sysmem(hdr);
+ return 0;
+#endif
+#if defined(CONFIG_FIT)
+ case IMAGE_FORMAT_FIT:
+ puts(" FIT image found\n");
+
+ if (fit_check_format(hdr, IMAGE_SIZE_INVAL)) {
+ puts("Bad FIT image format!\n");
+ unmap_sysmem(hdr);
+ return 1;
+ }
+
+ fit_print_contents(hdr);
+
+ if (!fit_all_image_verify(hdr)) {
+ puts("Bad hash in FIT image!\n");
+ unmap_sysmem(hdr);
+ return 1;
+ }
+
+ unmap_sysmem(hdr);
+ return 0;
+#endif
+ default:
+ puts("Unknown image format!\n");
+ break;
+ }
+
+ unmap_sysmem(hdr);
+ return 1;
+}
+
+U_BOOT_CMD(
+ iminfo, CONFIG_SYS_MAXARGS, 1, do_iminfo,
+ "print header information for application image",
+ "addr [addr ...]\n"
+ " - print header information for application image starting at\n"
+ " address 'addr' in memory; this includes verification of the\n"
+ " image contents (magic number, header and payload checksums)"
+);
+#endif
+
+
+/*******************************************************************/
+/* imls - list all images found in flash */
+/*******************************************************************/
+#if defined(CONFIG_CMD_IMLS)
+static int do_imls_nor(void)
+{
+ flash_info_t *info;
+ int i, j;
+ void *hdr;
+
+ for (i = 0, info = &flash_info[0];
+ i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ goto next_bank;
+ for (j = 0; j < info->sector_count; ++j) {
+
+ hdr = (void *)info->start[j];
+ if (!hdr)
+ goto next_sector;
+
+ switch (genimg_get_format(hdr)) {
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ case IMAGE_FORMAT_LEGACY:
+ if (!image_check_hcrc(hdr))
+ goto next_sector;
+
+ printf("Legacy Image at %08lX:\n", (ulong)hdr);
+ image_print_contents(hdr);
+
+ puts(" Verifying Checksum ... ");
+ if (!image_check_dcrc(hdr)) {
+ puts("Bad Data CRC\n");
+ } else {
+ puts("OK\n");
+ }
+ break;
+#endif
+#if defined(CONFIG_FIT)
+ case IMAGE_FORMAT_FIT:
+ if (fit_check_format(hdr, IMAGE_SIZE_INVAL))
+ goto next_sector;
+
+ printf("FIT Image at %08lX:\n", (ulong)hdr);
+ fit_print_contents(hdr);
+ break;
+#endif
+ default:
+ goto next_sector;
+ }
+
+next_sector: ;
+ }
+next_bank: ;
+ }
+ return 0;
+}
+#endif
+
+#if defined(CONFIG_CMD_IMLS_NAND)
+static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev,
+ loff_t off, size_t len)
+{
+ void *imgdata;
+ int ret;
+
+ imgdata = malloc(len);
+ if (!imgdata) {
+ printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
+ nand_dev, off);
+ printf(" Low memory(cannot allocate memory for image)\n");
+ return -ENOMEM;
+ }
+
+ ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
+ if (ret < 0 && ret != -EUCLEAN) {
+ free(imgdata);
+ return ret;
+ }
+
+ if (!image_check_hcrc(imgdata)) {
+ free(imgdata);
+ return 0;
+ }
+
+ printf("Legacy Image at NAND device %d offset %08llX:\n",
+ nand_dev, off);
+ image_print_contents(imgdata);
+
+ puts(" Verifying Checksum ... ");
+ if (!image_check_dcrc(imgdata))
+ puts("Bad Data CRC\n");
+ else
+ puts("OK\n");
+
+ free(imgdata);
+
+ return 0;
+}
+
+static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
+ size_t len)
+{
+ void *imgdata;
+ int ret;
+
+ imgdata = malloc(len);
+ if (!imgdata) {
+ printf("May be a FIT Image at NAND device %d offset %08llX:\n",
+ nand_dev, off);
+ printf(" Low memory(cannot allocate memory for image)\n");
+ return -ENOMEM;
+ }
+
+ ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
+ if (ret < 0 && ret != -EUCLEAN) {
+ free(imgdata);
+ return ret;
+ }
+
+ if (fit_check_format(imgdata, IMAGE_SIZE_INVAL)) {
+ free(imgdata);
+ return 0;
+ }
+
+ printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
+
+ fit_print_contents(imgdata);
+ free(imgdata);
+
+ return 0;
+}
+
+static int do_imls_nand(void)
+{
+ struct mtd_info *mtd;
+ int nand_dev = nand_curr_device;
+ size_t len;
+ loff_t off;
+ u32 buffer[16];
+
+ if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
+ puts("\nNo NAND devices available\n");
+ return -ENODEV;
+ }
+
+ printf("\n");
+
+ for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
+ mtd = get_nand_dev_by_index(nand_dev);
+ if (!mtd->name || !mtd->size)
+ continue;
+
+ for (off = 0; off < mtd->size; off += mtd->erasesize) {
+ const image_header_t *header;
+ int ret;
+
+ if (nand_block_isbad(mtd, off))
+ continue;
+
+ len = sizeof(buffer);
+
+ ret = nand_read(mtd, off, &len, (u8 *)buffer);
+ if (ret < 0 && ret != -EUCLEAN) {
+ printf("NAND read error %d at offset %08llX\n",
+ ret, off);
+ continue;
+ }
+
+ switch (genimg_get_format(buffer)) {
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ case IMAGE_FORMAT_LEGACY:
+ header = (const image_header_t *)buffer;
+
+ len = image_get_image_size(header);
+ nand_imls_legacyimage(mtd, nand_dev, off, len);
+ break;
+#endif
+#if defined(CONFIG_FIT)
+ case IMAGE_FORMAT_FIT:
+ len = fit_get_size(buffer);
+ nand_imls_fitimage(mtd, nand_dev, off, len);
+ break;
+#endif
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
+
+#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
+static int do_imls(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret_nor = 0, ret_nand = 0;
+
+#if defined(CONFIG_CMD_IMLS)
+ ret_nor = do_imls_nor();
+#endif
+
+#if defined(CONFIG_CMD_IMLS_NAND)
+ ret_nand = do_imls_nand();
+#endif
+
+ if (ret_nor)
+ return ret_nor;
+
+ if (ret_nand)
+ return ret_nand;
+
+ return (0);
+}
+
+U_BOOT_CMD(
+ imls, 1, 1, do_imls,
+ "list all images found in flash",
+ "\n"
+ " - Prints information about all images found at sector/block\n"
+ " boundaries in nor/nand flash."
+);
+#endif
diff --git a/roms/u-boot/cmd/bootmenu.c b/roms/u-boot/cmd/bootmenu.c
new file mode 100644
index 000000000..409ef9a84
--- /dev/null
+++ b/roms/u-boot/cmd/bootmenu.c
@@ -0,0 +1,542 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011-2013 Pali Rohár <pali@kernel.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <ansi.h>
+#include <env.h>
+#include <log.h>
+#include <menu.h>
+#include <watchdog.h>
+#include <malloc.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+
+/* maximum bootmenu entries */
+#define MAX_COUNT 99
+
+/* maximal size of bootmenu env
+ * 9 = strlen("bootmenu_")
+ * 2 = strlen(MAX_COUNT)
+ * 1 = NULL term
+ */
+#define MAX_ENV_SIZE (9 + 2 + 1)
+
+struct bootmenu_entry {
+ unsigned short int num; /* unique number 0 .. MAX_COUNT */
+ char key[3]; /* key identifier of number */
+ char *title; /* title of entry */
+ char *command; /* hush command of entry */
+ struct bootmenu_data *menu; /* this bootmenu */
+ struct bootmenu_entry *next; /* next menu entry (num+1) */
+};
+
+struct bootmenu_data {
+ int delay; /* delay for autoboot */
+ int active; /* active menu entry */
+ int count; /* total count of menu entries */
+ struct bootmenu_entry *first; /* first menu entry */
+};
+
+enum bootmenu_key {
+ KEY_NONE = 0,
+ KEY_UP,
+ KEY_DOWN,
+ KEY_SELECT,
+ KEY_QUIT,
+};
+
+static char *bootmenu_getoption(unsigned short int n)
+{
+ char name[MAX_ENV_SIZE];
+
+ if (n > MAX_COUNT)
+ return NULL;
+
+ sprintf(name, "bootmenu_%d", n);
+ return env_get(name);
+}
+
+static void bootmenu_print_entry(void *data)
+{
+ struct bootmenu_entry *entry = data;
+ int reverse = (entry->menu->active == entry->num);
+
+ /*
+ * Move cursor to line where the entry will be drown (entry->num)
+ * First 3 lines contain bootmenu header + 1 empty line
+ */
+ printf(ANSI_CURSOR_POSITION, entry->num + 4, 1);
+
+ puts(" ");
+
+ if (reverse)
+ puts(ANSI_COLOR_REVERSE);
+
+ puts(entry->title);
+
+ if (reverse)
+ puts(ANSI_COLOR_RESET);
+}
+
+static void bootmenu_autoboot_loop(struct bootmenu_data *menu,
+ enum bootmenu_key *key, int *esc)
+{
+ int i, c;
+
+ if (menu->delay > 0) {
+ printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
+ printf(" Hit any key to stop autoboot: %2d ", menu->delay);
+ }
+
+ while (menu->delay > 0) {
+ for (i = 0; i < 100; ++i) {
+ if (!tstc()) {
+ WATCHDOG_RESET();
+ mdelay(10);
+ continue;
+ }
+
+ menu->delay = -1;
+ c = getchar();
+
+ switch (c) {
+ case '\e':
+ *esc = 1;
+ *key = KEY_NONE;
+ break;
+ case '\r':
+ *key = KEY_SELECT;
+ break;
+ case 0x3: /* ^C */
+ *key = KEY_QUIT;
+ break;
+ default:
+ *key = KEY_NONE;
+ break;
+ }
+
+ break;
+ }
+
+ if (menu->delay < 0)
+ break;
+
+ --menu->delay;
+ printf("\b\b\b%2d ", menu->delay);
+ }
+
+ printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
+ puts(ANSI_CLEAR_LINE);
+
+ if (menu->delay == 0)
+ *key = KEY_SELECT;
+}
+
+static void bootmenu_loop(struct bootmenu_data *menu,
+ enum bootmenu_key *key, int *esc)
+{
+ int c;
+
+ if (*esc == 1) {
+ if (tstc()) {
+ c = getchar();
+ } else {
+ WATCHDOG_RESET();
+ mdelay(10);
+ if (tstc())
+ c = getchar();
+ else
+ c = '\e';
+ }
+ } else {
+ while (!tstc()) {
+ WATCHDOG_RESET();
+ mdelay(10);
+ }
+ c = getchar();
+ }
+
+ switch (*esc) {
+ case 0:
+ /* First char of ANSI escape sequence '\e' */
+ if (c == '\e') {
+ *esc = 1;
+ *key = KEY_NONE;
+ }
+ break;
+ case 1:
+ /* Second char of ANSI '[' */
+ if (c == '[') {
+ *esc = 2;
+ *key = KEY_NONE;
+ } else {
+ /* Alone ESC key was pressed */
+ *key = KEY_QUIT;
+ *esc = (c == '\e') ? 1 : 0;
+ }
+ break;
+ case 2:
+ case 3:
+ /* Third char of ANSI (number '1') - optional */
+ if (*esc == 2 && c == '1') {
+ *esc = 3;
+ *key = KEY_NONE;
+ break;
+ }
+
+ *esc = 0;
+
+ /* ANSI 'A' - key up was pressed */
+ if (c == 'A')
+ *key = KEY_UP;
+ /* ANSI 'B' - key down was pressed */
+ else if (c == 'B')
+ *key = KEY_DOWN;
+ /* other key was pressed */
+ else
+ *key = KEY_NONE;
+
+ break;
+ }
+
+ /* enter key was pressed */
+ if (c == '\r')
+ *key = KEY_SELECT;
+
+ /* ^C was pressed */
+ if (c == 0x3)
+ *key = KEY_QUIT;
+}
+
+static char *bootmenu_choice_entry(void *data)
+{
+ struct bootmenu_data *menu = data;
+ struct bootmenu_entry *iter;
+ enum bootmenu_key key = KEY_NONE;
+ int esc = 0;
+ int i;
+
+ while (1) {
+ if (menu->delay >= 0) {
+ /* Autoboot was not stopped */
+ bootmenu_autoboot_loop(menu, &key, &esc);
+ } else {
+ /* Some key was pressed, so autoboot was stopped */
+ bootmenu_loop(menu, &key, &esc);
+ }
+
+ switch (key) {
+ case KEY_UP:
+ if (menu->active > 0)
+ --menu->active;
+ /* no menu key selected, regenerate menu */
+ return NULL;
+ case KEY_DOWN:
+ if (menu->active < menu->count - 1)
+ ++menu->active;
+ /* no menu key selected, regenerate menu */
+ return NULL;
+ case KEY_SELECT:
+ iter = menu->first;
+ for (i = 0; i < menu->active; ++i)
+ iter = iter->next;
+ return iter->key;
+ case KEY_QUIT:
+ /* Quit by choosing the last entry - U-Boot console */
+ iter = menu->first;
+ while (iter->next)
+ iter = iter->next;
+ return iter->key;
+ default:
+ break;
+ }
+ }
+
+ /* never happens */
+ debug("bootmenu: this should not happen");
+ return NULL;
+}
+
+static void bootmenu_destroy(struct bootmenu_data *menu)
+{
+ struct bootmenu_entry *iter = menu->first;
+ struct bootmenu_entry *next;
+
+ while (iter) {
+ next = iter->next;
+ free(iter->title);
+ free(iter->command);
+ free(iter);
+ iter = next;
+ }
+ free(menu);
+}
+
+static struct bootmenu_data *bootmenu_create(int delay)
+{
+ unsigned short int i = 0;
+ const char *option;
+ struct bootmenu_data *menu;
+ struct bootmenu_entry *iter = NULL;
+
+ int len;
+ char *sep;
+ char *default_str;
+ struct bootmenu_entry *entry;
+
+ menu = malloc(sizeof(struct bootmenu_data));
+ if (!menu)
+ return NULL;
+
+ menu->delay = delay;
+ menu->active = 0;
+ menu->first = NULL;
+
+ default_str = env_get("bootmenu_default");
+ if (default_str)
+ menu->active = (int)simple_strtol(default_str, NULL, 10);
+
+ while ((option = bootmenu_getoption(i))) {
+ sep = strchr(option, '=');
+ if (!sep) {
+ printf("Invalid bootmenu entry: %s\n", option);
+ break;
+ }
+
+ entry = malloc(sizeof(struct bootmenu_entry));
+ if (!entry)
+ goto cleanup;
+
+ len = sep-option;
+ entry->title = malloc(len + 1);
+ if (!entry->title) {
+ free(entry);
+ goto cleanup;
+ }
+ memcpy(entry->title, option, len);
+ entry->title[len] = 0;
+
+ len = strlen(sep + 1);
+ entry->command = malloc(len + 1);
+ if (!entry->command) {
+ free(entry->title);
+ free(entry);
+ goto cleanup;
+ }
+ memcpy(entry->command, sep + 1, len);
+ entry->command[len] = 0;
+
+ sprintf(entry->key, "%d", i);
+
+ entry->num = i;
+ entry->menu = menu;
+ entry->next = NULL;
+
+ if (!iter)
+ menu->first = entry;
+ else
+ iter->next = entry;
+
+ iter = entry;
+ ++i;
+
+ if (i == MAX_COUNT - 1)
+ break;
+ }
+
+ /* Add U-Boot console entry at the end */
+ if (i <= MAX_COUNT - 1) {
+ entry = malloc(sizeof(struct bootmenu_entry));
+ if (!entry)
+ goto cleanup;
+
+ entry->title = strdup("U-Boot console");
+ if (!entry->title) {
+ free(entry);
+ goto cleanup;
+ }
+
+ entry->command = strdup("");
+ if (!entry->command) {
+ free(entry->title);
+ free(entry);
+ goto cleanup;
+ }
+
+ sprintf(entry->key, "%d", i);
+
+ entry->num = i;
+ entry->menu = menu;
+ entry->next = NULL;
+
+ if (!iter)
+ menu->first = entry;
+ else
+ iter->next = entry;
+
+ iter = entry;
+ ++i;
+ }
+
+ menu->count = i;
+
+ if ((menu->active >= menu->count)||(menu->active < 0)) { //ensure active menuitem is inside menu
+ printf("active menuitem (%d) is outside menu (0..%d)\n",menu->active,menu->count-1);
+ menu->active=0;
+ }
+
+ return menu;
+
+cleanup:
+ bootmenu_destroy(menu);
+ return NULL;
+}
+
+static void menu_display_statusline(struct menu *m)
+{
+ struct bootmenu_entry *entry;
+ struct bootmenu_data *menu;
+
+ if (menu_default_choice(m, (void *)&entry) < 0)
+ return;
+
+ menu = entry->menu;
+
+ printf(ANSI_CURSOR_POSITION, 1, 1);
+ puts(ANSI_CLEAR_LINE);
+ printf(ANSI_CURSOR_POSITION, 2, 1);
+ puts(" *** U-Boot Boot Menu ***");
+ puts(ANSI_CLEAR_LINE_TO_END);
+ printf(ANSI_CURSOR_POSITION, 3, 1);
+ puts(ANSI_CLEAR_LINE);
+
+ /* First 3 lines are bootmenu header + 2 empty lines between entries */
+ printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
+ puts(ANSI_CLEAR_LINE);
+ printf(ANSI_CURSOR_POSITION, menu->count + 6, 1);
+ puts(" Press UP/DOWN to move, ENTER to select, ESC/CTRL+C to quit");
+ puts(ANSI_CLEAR_LINE_TO_END);
+ printf(ANSI_CURSOR_POSITION, menu->count + 7, 1);
+ puts(ANSI_CLEAR_LINE);
+}
+
+static void bootmenu_show(int delay)
+{
+ int init = 0;
+ void *choice = NULL;
+ char *title = NULL;
+ char *command = NULL;
+ struct menu *menu;
+ struct bootmenu_data *bootmenu;
+ struct bootmenu_entry *iter;
+ char *option, *sep;
+
+ /* If delay is 0 do not create menu, just run first entry */
+ if (delay == 0) {
+ option = bootmenu_getoption(0);
+ if (!option) {
+ puts("bootmenu option 0 was not found\n");
+ return;
+ }
+ sep = strchr(option, '=');
+ if (!sep) {
+ puts("bootmenu option 0 is invalid\n");
+ return;
+ }
+ run_command(sep+1, 0);
+ return;
+ }
+
+ bootmenu = bootmenu_create(delay);
+ if (!bootmenu)
+ return;
+
+ menu = menu_create(NULL, bootmenu->delay, 1, menu_display_statusline,
+ bootmenu_print_entry, bootmenu_choice_entry,
+ bootmenu);
+ if (!menu) {
+ bootmenu_destroy(bootmenu);
+ return;
+ }
+
+ for (iter = bootmenu->first; iter; iter = iter->next) {
+ if (!menu_item_add(menu, iter->key, iter))
+ goto cleanup;
+ }
+
+ /* Default menu entry is always first */
+ menu_default_set(menu, "0");
+
+ puts(ANSI_CURSOR_HIDE);
+ puts(ANSI_CLEAR_CONSOLE);
+ printf(ANSI_CURSOR_POSITION, 1, 1);
+
+ init = 1;
+
+ if (menu_get_choice(menu, &choice)) {
+ iter = choice;
+ title = strdup(iter->title);
+ command = strdup(iter->command);
+ }
+
+cleanup:
+ menu_destroy(menu);
+ bootmenu_destroy(bootmenu);
+
+ if (init) {
+ puts(ANSI_CURSOR_SHOW);
+ puts(ANSI_CLEAR_CONSOLE);
+ printf(ANSI_CURSOR_POSITION, 1, 1);
+ }
+
+ if (title && command) {
+ debug("Starting entry '%s'\n", title);
+ free(title);
+ run_command(command, 0);
+ free(command);
+ }
+
+#ifdef CONFIG_POSTBOOTMENU
+ run_command(CONFIG_POSTBOOTMENU, 0);
+#endif
+}
+
+#ifdef CONFIG_AUTOBOOT_MENU_SHOW
+int menu_show(int bootdelay)
+{
+ bootmenu_show(bootdelay);
+ return -1; /* -1 - abort boot and run monitor code */
+}
+#endif
+
+int do_bootmenu(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *delay_str = NULL;
+ int delay = 10;
+
+#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
+ delay = CONFIG_BOOTDELAY;
+#endif
+
+ if (argc >= 2)
+ delay_str = argv[1];
+
+ if (!delay_str)
+ delay_str = env_get("bootmenu_delay");
+
+ if (delay_str)
+ delay = (int)simple_strtol(delay_str, NULL, 10);
+
+ bootmenu_show(delay);
+ return 0;
+}
+
+U_BOOT_CMD(
+ bootmenu, 2, 1, do_bootmenu,
+ "ANSI terminal bootmenu",
+ "[delay]\n"
+ " - show ANSI terminal bootmenu with autoboot delay"
+);
diff --git a/roms/u-boot/cmd/bootstage.c b/roms/u-boot/cmd/bootstage.c
new file mode 100644
index 000000000..0e623f216
--- /dev/null
+++ b/roms/u-boot/cmd/bootstage.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2012, Google Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <bootstage.h>
+#include <command.h>
+
+static int do_bootstage_report(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bootstage_report();
+
+ return 0;
+}
+
+static int get_base_size(int argc, char *const argv[], ulong *basep,
+ ulong *sizep)
+{
+ char *endp;
+
+ *basep = CONFIG_BOOTSTAGE_STASH_ADDR;
+ *sizep = CONFIG_BOOTSTAGE_STASH_SIZE;
+ if (argc < 2)
+ return 0;
+ *basep = simple_strtoul(argv[1], &endp, 16);
+ if (*argv[1] == 0 || *endp != 0)
+ return -1;
+ if (argc == 2)
+ return 0;
+ *sizep = simple_strtoul(argv[2], &endp, 16);
+ if (*argv[2] == 0 || *endp != 0)
+ return -1;
+
+ return 0;
+}
+
+static int do_bootstage_stash(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong base, size;
+ int ret;
+
+ if (get_base_size(argc, argv, &base, &size))
+ return CMD_RET_USAGE;
+ if (base == -1UL) {
+ printf("No bootstage stash area defined\n");
+ return 1;
+ }
+
+ if (0 == strcmp(argv[0], "stash"))
+ ret = bootstage_stash((void *)base, size);
+ else
+ ret = bootstage_unstash((void *)base, size);
+ if (ret)
+ return 1;
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_bootstage_sub[] = {
+ U_BOOT_CMD_MKENT(report, 2, 1, do_bootstage_report, "", ""),
+ U_BOOT_CMD_MKENT(stash, 4, 0, do_bootstage_stash, "", ""),
+ U_BOOT_CMD_MKENT(unstash, 4, 0, do_bootstage_stash, "", ""),
+};
+
+/*
+ * Process a bootstage sub-command
+ */
+static int do_boostage(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ /* Strip off leading 'bootstage' command argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], cmd_bootstage_sub,
+ ARRAY_SIZE(cmd_bootstage_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+
+U_BOOT_CMD(bootstage, 4, 1, do_boostage,
+ "Boot stage command",
+ " - check boot progress and timing\n"
+ "report - Print a report\n"
+ "stash [<start> [<size>]] - Stash data into memory\n"
+ "unstash [<start> [<size>]] - Unstash data from memory"
+);
diff --git a/roms/u-boot/cmd/bootz.c b/roms/u-boot/cmd/bootz.c
new file mode 100644
index 000000000..7556cd275
--- /dev/null
+++ b/roms/u-boot/cmd/bootz.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <bootm.h>
+#include <command.h>
+#include <image.h>
+#include <irq_func.h>
+#include <lmb.h>
+#include <log.h>
+#include <linux/compiler.h>
+
+int __weak bootz_setup(ulong image, ulong *start, ulong *end)
+{
+ /* Please define bootz_setup() for your platform */
+
+ puts("Your platform's zImage format isn't supported yet!\n");
+ return -1;
+}
+
+/*
+ * zImage booting support
+ */
+static int bootz_start(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[], bootm_headers_t *images)
+{
+ int ret;
+ ulong zi_start, zi_end;
+
+ ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
+ images, 1);
+
+ /* Setup Linux kernel zImage entry point */
+ if (!argc) {
+ images->ep = image_load_addr;
+ debug("* kernel: default image load address = 0x%08lx\n",
+ image_load_addr);
+ } else {
+ images->ep = simple_strtoul(argv[0], NULL, 16);
+ debug("* kernel: cmdline image address = 0x%08lx\n",
+ images->ep);
+ }
+
+ ret = bootz_setup(images->ep, &zi_start, &zi_end);
+ if (ret != 0)
+ return 1;
+
+ lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
+
+ /*
+ * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
+ * have a header that provide this informaiton.
+ */
+ if (bootm_find_images(flag, argc, argv, images->ep, zi_end - zi_start))
+ return 1;
+
+ return 0;
+}
+
+int do_bootz(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int ret;
+
+ /* Consume 'bootz' */
+ argc--; argv++;
+
+ if (bootz_start(cmdtp, flag, argc, argv, &images))
+ return 1;
+
+ /*
+ * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
+ * disable interrupts ourselves
+ */
+ bootm_disable_interrupts();
+
+ images.os.os = IH_OS_LINUX;
+ ret = do_bootm_states(cmdtp, flag, argc, argv,
+#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
+ BOOTM_STATE_RAMDISK |
+#endif
+ BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
+ BOOTM_STATE_OS_GO,
+ &images, 1);
+
+ return ret;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bootz_help_text[] =
+ "[addr [initrd[:size]] [fdt]]\n"
+ " - boot Linux zImage stored in memory\n"
+ "\tThe argument 'initrd' is optional and specifies the address\n"
+ "\tof the initrd in memory. The optional argument ':size' allows\n"
+ "\tspecifying the size of RAW initrd.\n"
+#if defined(CONFIG_OF_LIBFDT)
+ "\tWhen booting a Linux kernel which requires a flat device-tree\n"
+ "\ta third argument is required which is the address of the\n"
+ "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
+ "\tuse a '-' for the second argument. If you do not pass a third\n"
+ "\ta bd_info struct will be passed instead\n"
+#endif
+ "";
+#endif
+
+U_BOOT_CMD(
+ bootz, CONFIG_SYS_MAXARGS, 1, do_bootz,
+ "boot Linux zImage image from memory", bootz_help_text
+);
diff --git a/roms/u-boot/cmd/broadcom/Makefile b/roms/u-boot/cmd/broadcom/Makefile
new file mode 100644
index 000000000..62268d98d
--- /dev/null
+++ b/roms/u-boot/cmd/broadcom/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2020 Broadcom
+
+obj-y += chimp_boot.o
+obj-y += nitro_image_load.o
+obj-y += chimp_handshake.o
diff --git a/roms/u-boot/cmd/broadcom/chimp_boot.c b/roms/u-boot/cmd/broadcom/chimp_boot.c
new file mode 100644
index 000000000..16f2b612c
--- /dev/null
+++ b/roms/u-boot/cmd/broadcom/chimp_boot.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 Broadcom
+ */
+
+#include <common.h>
+#include <command.h>
+#include <broadcom/chimp.h>
+
+static int do_chimp_fastboot_secure(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 health = 0;
+
+ if (chimp_health_status_optee(&health)) {
+ pr_err("Chimp health command fail\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (health == BCM_CHIMP_RUNNIG_GOOD) {
+ printf("skip fastboot...\n");
+ return CMD_RET_SUCCESS;
+ }
+
+ if (chimp_fastboot_optee()) {
+ pr_err("Failed to load secure ChiMP image\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD
+ (chimp_ld_secure, 1, 0, do_chimp_fastboot_secure,
+ "Invoke chimp fw load via optee",
+ "chimp_ld_secure\n"
+);
diff --git a/roms/u-boot/cmd/broadcom/chimp_handshake.c b/roms/u-boot/cmd/broadcom/chimp_handshake.c
new file mode 100644
index 000000000..a90a73a6d
--- /dev/null
+++ b/roms/u-boot/cmd/broadcom/chimp_handshake.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 Broadcom
+ */
+
+#include <common.h>
+#include <command.h>
+#include <broadcom/chimp.h>
+
+/* This command should be called after loading the nitro binaries */
+static int do_chimp_hs(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret = CMD_RET_USAGE;
+ u32 hstatus;
+
+ /* Returns 1, if handshake call is success */
+ if (chimp_handshake_status_optee(0, &hstatus))
+ ret = CMD_RET_SUCCESS;
+
+ if (hstatus == CHIMP_HANDSHAKE_SUCCESS)
+ printf("ChiMP Handshake successful\n");
+ else
+ printf("ERROR: ChiMP Handshake status 0x%x\n", hstatus);
+
+ return ret;
+}
+
+U_BOOT_CMD
+ (chimp_hs, 1, 1, do_chimp_hs,
+ "Verify the Chimp handshake",
+ "chimp_hs\n"
+);
diff --git a/roms/u-boot/cmd/broadcom/nitro_image_load.c b/roms/u-boot/cmd/broadcom/nitro_image_load.c
new file mode 100644
index 000000000..4a36b300c
--- /dev/null
+++ b/roms/u-boot/cmd/broadcom/nitro_image_load.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 Broadcom
+ */
+
+#include <common.h>
+#include <command.h>
+
+#define FW_IMAGE_SIG 0xff123456
+#define CFG_IMAGE_SIG 0xcf54321a
+
+/*
+ * structure for bin file
+ * signature: fw itb file
+ * size: fw itb file
+ * signature: NS3 config file
+ * size: NS3 config file
+ * Data: fw itb file
+ * ............................
+ * ............................
+ * Data: NS3 config file
+ * ............................
+ * ............................
+ */
+
+static struct img_header {
+ u32 bin_sig;
+ u32 bin_size;
+ u32 cfg1_sig;
+ u32 cfg1_size;
+} *img_header;
+
+static int env_set_val(const char *varname, ulong val)
+{
+ int ret;
+
+ ret = env_set_hex(varname, val);
+ if (ret)
+ pr_err("Failed to %s env var\n", varname);
+
+ return ret;
+}
+
+static int do_spi_images_addr(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uintptr_t images_load_addr;
+ uintptr_t spi_load_addr;
+ u32 len;
+ u32 spi_data_offset = sizeof(struct img_header);
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ /* convert command parameter to fastboot address (base 16), i.e. hex */
+ images_load_addr = simple_strtoul(argv[1], NULL, 16);
+ if (!images_load_addr) {
+ pr_err("Invalid load address\n");
+ return CMD_RET_USAGE;
+ }
+
+ spi_load_addr = simple_strtoul(argv[2], NULL, 16);
+ if (!spi_load_addr) {
+ pr_err("Invalid spi load address\n");
+ return CMD_RET_USAGE;
+ }
+
+ img_header = (struct img_header *)images_load_addr;
+
+ if (img_header->bin_sig != FW_IMAGE_SIG) {
+ pr_err("Invalid Nitro bin file\n");
+ goto error;
+ }
+
+ if (env_set_val("spi_nitro_fw_itb_start_addr", 0))
+ goto error;
+
+ if (env_set_val("spi_nitro_fw_itb_len", 0))
+ goto error;
+
+ if (env_set_val("spi_nitro_fw_ns3_cfg_start_addr", 0))
+ goto error;
+
+ if (env_set_val("spi_nitro_fw_ns3_cfg_len", 0))
+ goto error;
+
+ len = img_header->bin_size;
+
+ if (env_set_val("spi_nitro_fw_itb_start_addr",
+ (spi_load_addr + spi_data_offset)))
+ goto error;
+
+ if (env_set_val("spi_nitro_fw_itb_len", img_header->bin_size))
+ goto error;
+
+ spi_data_offset += len;
+
+ if (img_header->cfg1_sig == CFG_IMAGE_SIG) {
+ len = img_header->cfg1_size;
+
+ if (env_set_val("spi_nitro_fw_ns3_cfg_start_addr",
+ (spi_load_addr + spi_data_offset)))
+ goto error;
+
+ if (env_set_val("spi_nitro_fw_ns3_cfg_len", len))
+ goto error;
+
+ spi_data_offset += len;
+ }
+
+ /* disable secure boot */
+ if (env_set_val("nitro_fastboot_secure", 0))
+ goto error;
+
+ return CMD_RET_SUCCESS;
+
+error:
+ return CMD_RET_FAILURE;
+}
+
+U_BOOT_CMD
+ (spi_nitro_images_addr, 3, 1, do_spi_images_addr,
+ "Load the bnxt bin header and sets envs ",
+ "spi_nitro_images_addr <load_addr> <spi_base_addr>\n"
+);
diff --git a/roms/u-boot/cmd/btrfs.c b/roms/u-boot/cmd/btrfs.c
new file mode 100644
index 000000000..7e3cbe12c
--- /dev/null
+++ b/roms/u-boot/cmd/btrfs.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * 2017 by Marek Behun <marek.behun@nic.cz>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <btrfs.h>
+#include <fs.h>
+
+int do_btrsubvol(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ if (fs_set_blk_dev(argv[1], argv[2], FS_TYPE_BTRFS))
+ return 1;
+
+ btrfs_list_subvols();
+ return 0;
+}
+
+U_BOOT_CMD(btrsubvol, 3, 1, do_btrsubvol,
+ "list subvolumes of a BTRFS filesystem",
+ "<interface> <dev[:part]>\n"
+ " - List subvolumes of a BTRFS filesystem."
+)
diff --git a/roms/u-boot/cmd/button.c b/roms/u-boot/cmd/button.c
new file mode 100644
index 000000000..1b45d0a2a
--- /dev/null
+++ b/roms/u-boot/cmd/button.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Philippe Reynes <philippe.reynes@softathome.com>
+ *
+ * Based on led.c
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <button.h>
+#include <dm/uclass-internal.h>
+
+static const char *const state_label[] = {
+ [BUTTON_OFF] = "off",
+ [BUTTON_ON] = "on",
+};
+
+static int show_button_state(struct udevice *dev)
+{
+ int ret;
+
+ ret = button_get_state(dev);
+ if (ret >= BUTTON_COUNT)
+ ret = -EINVAL;
+ if (ret >= 0)
+ printf("%s\n", state_label[ret]);
+
+ return ret;
+}
+
+static int list_buttons(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ for (uclass_find_first_device(UCLASS_BUTTON, &dev);
+ dev;
+ uclass_find_next_device(&dev)) {
+ struct button_uc_plat *plat = dev_get_uclass_plat(dev);
+
+ if (!plat->label)
+ continue;
+ printf("%-15s ", plat->label);
+ if (device_active(dev)) {
+ ret = show_button_state(dev);
+ if (ret < 0)
+ printf("Error %d\n", ret);
+ } else {
+ printf("<inactive>\n");
+ }
+ }
+
+ return 0;
+}
+
+int do_button(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const char *button_label;
+ struct udevice *dev;
+ int ret;
+
+ /* Validate arguments */
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ button_label = argv[1];
+ if (strncmp(button_label, "list", 4) == 0)
+ return list_buttons();
+
+ ret = button_get_by_label(button_label, &dev);
+ if (ret) {
+ printf("Button '%s' not found (err=%d)\n", button_label, ret);
+ return CMD_RET_FAILURE;
+ }
+
+ ret = show_button_state(dev);
+
+ return !ret;
+}
+
+U_BOOT_CMD(
+ button, 2, 1, do_button,
+ "manage buttons",
+ "<button_label> \tGet button state\n"
+ "button list\t\tShow a list of buttons"
+);
diff --git a/roms/u-boot/cmd/cache.c b/roms/u-boot/cmd/cache.c
new file mode 100644
index 000000000..b68d45b98
--- /dev/null
+++ b/roms/u-boot/cmd/cache.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Cache support: switch on or off, get status
+ */
+#include <common.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <linux/compiler.h>
+
+static int parse_argv(const char *);
+
+void __weak invalidate_icache_all(void)
+{
+ /* please define arch specific invalidate_icache_all */
+ puts("No arch specific invalidate_icache_all available!\n");
+}
+
+__weak void noncached_set_region(void)
+{
+}
+
+static int do_icache(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ switch (argc) {
+ case 2: /* on / off / flush */
+ switch (parse_argv(argv[1])) {
+ case 0:
+ icache_disable();
+ break;
+ case 1:
+ icache_enable();
+ break;
+ case 2:
+ invalidate_icache_all();
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ break;
+ case 1: /* get status */
+ printf("Instruction Cache is %s\n",
+ icache_status() ? "ON" : "OFF");
+ return 0;
+ default:
+ return CMD_RET_USAGE;
+ }
+ return 0;
+}
+
+void __weak flush_dcache_all(void)
+{
+ puts("No arch specific flush_dcache_all available!\n");
+ /* please define arch specific flush_dcache_all */
+}
+
+static int do_dcache(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ switch (argc) {
+ case 2: /* on / off / flush */
+ switch (parse_argv(argv[1])) {
+ case 0:
+ dcache_disable();
+ break;
+ case 1:
+ dcache_enable();
+ noncached_set_region();
+ break;
+ case 2:
+ flush_dcache_all();
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ break;
+ case 1: /* get status */
+ printf("Data (writethrough) Cache is %s\n",
+ dcache_status() ? "ON" : "OFF");
+ return 0;
+ default:
+ return CMD_RET_USAGE;
+ }
+ return 0;
+}
+
+static int parse_argv(const char *s)
+{
+ if (strcmp(s, "flush") == 0)
+ return 2;
+ else if (strcmp(s, "on") == 0)
+ return 1;
+ else if (strcmp(s, "off") == 0)
+ return 0;
+
+ return -1;
+}
+
+
+U_BOOT_CMD(
+ icache, 2, 1, do_icache,
+ "enable or disable instruction cache",
+ "[on, off, flush]\n"
+ " - enable, disable, or flush instruction cache"
+);
+
+U_BOOT_CMD(
+ dcache, 2, 1, do_dcache,
+ "enable or disable data cache",
+ "[on, off, flush]\n"
+ " - enable, disable, or flush data (writethrough) cache"
+);
diff --git a/roms/u-boot/cmd/cbfs.c b/roms/u-boot/cmd/cbfs.c
new file mode 100644
index 000000000..10c2c929c
--- /dev/null
+++ b/roms/u-boot/cmd/cbfs.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ */
+
+/*
+ * CBFS commands
+ */
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <cbfs.h>
+
+static int do_cbfs_init(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uintptr_t end_of_rom = 0xffffffff;
+ char *ep;
+
+ if (argc > 2) {
+ printf("usage: cbfsls [end of rom]>\n");
+ return 0;
+ }
+ if (argc == 2) {
+ end_of_rom = simple_strtoul(argv[1], &ep, 16);
+ if (*ep) {
+ puts("\n** Invalid end of ROM **\n");
+ return 1;
+ }
+ }
+ if (file_cbfs_init(end_of_rom)) {
+ printf("%s.\n", file_cbfs_error());
+ return 1;
+ }
+ return 0;
+}
+
+U_BOOT_CMD(
+ cbfsinit, 2, 0, do_cbfs_init,
+ "initialize the cbfs driver",
+ "[end of rom]\n"
+ " - Initialize the cbfs driver. The optional 'end of rom'\n"
+ " parameter specifies where the end of the ROM is that the\n"
+ " CBFS is in. It defaults to 0xFFFFFFFF\n"
+);
+
+static int do_cbfs_fsload(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const struct cbfs_cachenode *file;
+ unsigned long offset;
+ unsigned long count;
+ long size;
+
+ if (argc < 3) {
+ printf("usage: cbfsload <addr> <filename> [bytes]\n");
+ return 1;
+ }
+
+ /* parse offset and count */
+ offset = simple_strtoul(argv[1], NULL, 16);
+ if (argc == 4)
+ count = simple_strtoul(argv[3], NULL, 16);
+ else
+ count = 0;
+
+ file = file_cbfs_find(argv[2]);
+ if (!file) {
+ if (cbfs_get_result() == CBFS_FILE_NOT_FOUND)
+ printf("%s: %s\n", file_cbfs_error(), argv[2]);
+ else
+ printf("%s.\n", file_cbfs_error());
+ return 1;
+ }
+
+ printf("reading %s\n", file_cbfs_name(file));
+
+ size = file_cbfs_read(file, (void *)offset, count);
+
+ printf("\n%ld bytes read\n", size);
+
+ env_set_hex("filesize", size);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ cbfsload, 4, 0, do_cbfs_fsload,
+ "load binary file from a cbfs filesystem",
+ "<addr> <filename> [bytes]\n"
+ " - load binary file 'filename' from the cbfs to address 'addr'\n"
+);
+
+static int do_cbfs_ls(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const struct cbfs_cachenode *file = file_cbfs_get_first();
+ int files = 0;
+
+ if (!file) {
+ printf("%s.\n", file_cbfs_error());
+ return 1;
+ }
+
+ printf(" size type name\n");
+ printf("------------------------------------------\n");
+ while (file) {
+ int type = file_cbfs_type(file);
+ char *type_name = NULL;
+ const char *filename = file_cbfs_name(file);
+
+ printf(" %8d", file_cbfs_size(file));
+
+ switch (type) {
+ case CBFS_TYPE_BOOTBLOCK:
+ type_name = "bootblock";
+ break;
+ case CBFS_TYPE_CBFSHEADER:
+ type_name = "cbfs header";
+ break;
+ case CBFS_TYPE_STAGE:
+ type_name = "stage";
+ break;
+ case CBFS_TYPE_PAYLOAD:
+ type_name = "payload";
+ break;
+ case CBFS_TYPE_FIT:
+ type_name = "fit";
+ break;
+ case CBFS_TYPE_OPTIONROM:
+ type_name = "option rom";
+ break;
+ case CBFS_TYPE_BOOTSPLASH:
+ type_name = "boot splash";
+ break;
+ case CBFS_TYPE_RAW:
+ type_name = "raw";
+ break;
+ case CBFS_TYPE_VSA:
+ type_name = "vsa";
+ break;
+ case CBFS_TYPE_MBI:
+ type_name = "mbi";
+ break;
+ case CBFS_TYPE_MICROCODE:
+ type_name = "microcode";
+ break;
+ case CBFS_TYPE_FSP:
+ type_name = "fsp";
+ break;
+ case CBFS_TYPE_MRC:
+ type_name = "mrc";
+ break;
+ case CBFS_TYPE_MMA:
+ type_name = "mma";
+ break;
+ case CBFS_TYPE_EFI:
+ type_name = "efi";
+ break;
+ case CBFS_TYPE_STRUCT:
+ type_name = "struct";
+ break;
+ case CBFS_TYPE_CMOS_DEFAULT:
+ type_name = "cmos default";
+ break;
+ case CBFS_TYPE_SPD:
+ type_name = "spd";
+ break;
+ case CBFS_TYPE_MRC_CACHE:
+ type_name = "mrc cache";
+ break;
+ case CBFS_TYPE_CMOS_LAYOUT:
+ type_name = "cmos layout";
+ break;
+ case -1:
+ case 0:
+ type_name = "null";
+ break;
+ }
+ if (type_name)
+ printf(" %16s", type_name);
+ else
+ printf(" %16d", type);
+
+ if (filename[0])
+ printf(" %s\n", filename);
+ else
+ printf(" %s\n", "(empty)");
+ file_cbfs_get_next(&file);
+ files++;
+ }
+
+ printf("\n%d file(s)\n\n", files);
+ return 0;
+}
+
+U_BOOT_CMD(
+ cbfsls, 1, 1, do_cbfs_ls,
+ "list files",
+ " - list the files in the cbfs\n"
+);
+
+static int do_cbfs_fsinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const struct cbfs_header *header = file_cbfs_get_header();
+
+ if (!header) {
+ printf("%s.\n", file_cbfs_error());
+ return 1;
+ }
+
+ printf("\n");
+ printf("CBFS version: %#x\n", header->version);
+ printf("ROM size: %#x\n", header->rom_size);
+ printf("Boot block size: %#x\n", header->boot_block_size);
+ printf("CBFS size: %#x\n",
+ header->rom_size - header->boot_block_size - header->offset);
+ printf("Alignment: %d\n", header->align);
+ printf("Offset: %#x\n", header->offset);
+ printf("\n");
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ cbfsinfo, 1, 1, do_cbfs_fsinfo,
+ "print information about filesystem",
+ " - print information about the cbfs filesystem\n"
+);
diff --git a/roms/u-boot/cmd/clk.c b/roms/u-boot/cmd/clk.c
new file mode 100644
index 000000000..e3c3d2f9b
--- /dev/null
+++ b/roms/u-boot/cmd/clk.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013 Xilinx, Inc.
+ */
+#include <common.h>
+#include <command.h>
+#include <clk.h>
+#if defined(CONFIG_DM) && defined(CONFIG_CLK)
+#include <dm.h>
+#include <dm/device.h>
+#include <dm/root.h>
+#include <dm/device-internal.h>
+#include <linux/clk-provider.h>
+#endif
+
+#if defined(CONFIG_DM) && defined(CONFIG_CLK)
+static void show_clks(struct udevice *dev, int depth, int last_flag)
+{
+ int i, is_last;
+ struct udevice *child;
+ struct clk *clkp;
+ u32 rate;
+
+ clkp = dev_get_clk_ptr(dev);
+ if (device_get_uclass_id(dev) == UCLASS_CLK && clkp) {
+ depth++;
+ rate = clk_get_rate(clkp);
+
+ printf(" %-12u %8d ", rate, clkp->enable_count);
+
+ for (i = depth; i >= 0; i--) {
+ is_last = (last_flag >> i) & 1;
+ if (i) {
+ if (is_last)
+ printf(" ");
+ else
+ printf("| ");
+ } else {
+ if (is_last)
+ printf("`-- ");
+ else
+ printf("|-- ");
+ }
+ }
+
+ printf("%s\n", dev->name);
+ }
+
+ list_for_each_entry(child, &dev->child_head, sibling_node) {
+ is_last = list_is_last(&child->sibling_node, &dev->child_head);
+ show_clks(child, depth, (last_flag << 1) | is_last);
+ }
+}
+
+int __weak soc_clk_dump(void)
+{
+ struct udevice *root;
+
+ root = dm_root();
+ if (root) {
+ printf(" Rate Usecnt Name\n");
+ printf("------------------------------------------\n");
+ show_clks(root, -1, 0);
+ }
+
+ return 0;
+}
+#else
+int __weak soc_clk_dump(void)
+{
+ puts("Not implemented\n");
+ return 1;
+}
+#endif
+
+static int do_clk_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+
+ ret = soc_clk_dump();
+ if (ret < 0) {
+ printf("Clock dump error %d\n", ret);
+ ret = CMD_RET_FAILURE;
+ }
+
+ return ret;
+}
+
+static struct cmd_tbl cmd_clk_sub[] = {
+ U_BOOT_CMD_MKENT(dump, 1, 1, do_clk_dump, "", ""),
+};
+
+static int do_clk(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* Strip off leading 'clk' command argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], &cmd_clk_sub[0], ARRAY_SIZE(cmd_clk_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char clk_help_text[] =
+ "dump - Print clock frequencies";
+#endif
+
+U_BOOT_CMD(clk, 2, 1, do_clk, "CLK sub-system", clk_help_text);
diff --git a/roms/u-boot/cmd/clone.c b/roms/u-boot/cmd/clone.c
new file mode 100644
index 000000000..32473a032
--- /dev/null
+++ b/roms/u-boot/cmd/clone.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 John Chau <john@harmon.hk>
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <part.h>
+#include <blk.h>
+#include <vsprintf.h>
+
+#define BUFSIZE (1 * 1024 * 1024)
+static int do_clone(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+ int srcdev, destdev;
+ struct blk_desc *srcdesc, *destdesc;
+ int srcbz, destbz, ret;
+ char *unit, *buf;
+ unsigned long wrcnt, rdcnt, requested, srcblk, destblk;
+ unsigned long timer;
+ const unsigned long buffersize = 1024 * 1024;
+
+ if (argc < 6)
+ return CMD_RET_USAGE;
+
+ srcdev = blk_get_device_by_str(argv[1], argv[2], &srcdesc);
+ destdev = blk_get_device_by_str(argv[3], argv[4], &destdesc);
+ if (srcdev < 0) {
+ printf("Unable to open source device\n");
+ return 1;
+ } else if (destdev < 0) {
+ printf("Unable to open destination device\n");
+ return 1;
+ }
+ requested = simple_strtoul(argv[5], &unit, 10);
+ srcbz = srcdesc->blksz;
+ destbz = destdesc->blksz;
+
+ if ((srcbz * (buffersize / srcbz) != buffersize) ||
+ (destbz * (buffersize / destbz) != buffersize)) {
+ printf("failed: cannot match device block sizes\n");
+ return 1;
+ }
+ if (requested == 0) {
+ unsigned long a = srcdesc->lba * srcdesc->blksz;
+ unsigned long b = destdesc->lba * destdesc->blksz;
+
+ if (a > b)
+ requested = a;
+ else
+ requested = b;
+ } else {
+ switch (unit[0]) {
+ case 'g':
+ case 'G':
+ requested *= 1024 * 1024 * 1024;
+ break;
+ case 'm':
+ case 'M':
+ requested *= 1024 * 1024;
+ break;
+ case 'k':
+ case 'K':
+ requested *= 1024;
+ break;
+ }
+ }
+ printf("Copying %ld bytes from %s:%s to %s:%s\n",
+ requested, argv[1], argv[2], argv[3], argv[4]);
+ wrcnt = 0;
+ rdcnt = 0;
+ buf = (char *)malloc(BUFSIZE);
+ srcblk = 0;
+ destblk = 0;
+ timer = get_timer(0);
+ while (wrcnt < requested) {
+ unsigned long toread = BUFSIZE / srcbz;
+ unsigned long towrite = BUFSIZE / destbz;
+ unsigned long offset = 0;
+
+read:
+ ret = blk_dread(srcdesc, srcblk, toread, buf + offset);
+ if (ret < 0) {
+ printf("Src read error @blk %ld\n", srcblk);
+ goto exit;
+ }
+ rdcnt += ret * srcbz;
+ srcblk += ret;
+ if (ret < toread) {
+ toread -= ret;
+ offset += ret * srcbz;
+ goto read;
+ }
+ offset = 0;
+write:
+ ret = blk_dwrite(destdesc, destblk, towrite, buf + offset);
+ if (ret < 0) {
+ printf("Dest write error @blk %ld\n", srcblk);
+ goto exit;
+ }
+ wrcnt += ret * destbz;
+ destblk += ret;
+ if (ret < towrite) {
+ towrite -= ret;
+ offset += ret * destbz;
+ goto write;
+ }
+ }
+
+exit:
+ timer = get_timer(timer);
+ timer = 1000 * timer / CONFIG_SYS_HZ;
+ printf("%ld read\n", rdcnt);
+ printf("%ld written\n", wrcnt);
+ printf("%ldms, %ldkB/s\n", timer, wrcnt / timer);
+ free(buf);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ clone, 6, 1, do_clone,
+ "simple storage cloning",
+ "<src interface> <src dev> <dest interface> <dest dev> <size[K/M/G]>\n"
+ "clone storage from 'src dev' on 'src interface' to 'dest dev' on 'dest interface' with maximum 'size' bytes (or 0 for clone to end)"
+);
diff --git a/roms/u-boot/cmd/cls.c b/roms/u-boot/cmd/cls.c
new file mode 100644
index 000000000..eab4e6993
--- /dev/null
+++ b/roms/u-boot/cmd/cls.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
+ *
+ * cls - clear screen command
+ */
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <lcd.h>
+#include <video.h>
+
+static int do_video_clear(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+#if defined(CONFIG_DM_VIDEO)
+ struct udevice *dev;
+
+ if (uclass_first_device_err(UCLASS_VIDEO, &dev))
+ return CMD_RET_FAILURE;
+
+ if (video_clear(dev))
+ return CMD_RET_FAILURE;
+#elif defined(CONFIG_CFB_CONSOLE)
+ video_clear();
+#elif defined(CONFIG_LCD)
+ lcd_clear();
+#else
+ return CMD_RET_FAILURE;
+#endif
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(cls, 1, 1, do_video_clear, "clear screen", "");
diff --git a/roms/u-boot/cmd/config.c b/roms/u-boot/cmd/config.c
new file mode 100644
index 000000000..cf30841a3
--- /dev/null
+++ b/roms/u-boot/cmd/config.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Masahiro Yamada <yamada.masahiro@socionext.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <gzip.h>
+#include <malloc.h>
+
+#include "config_data_gz.h"
+#include "config_data_size.h"
+
+static int do_config(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *dst;
+ unsigned long len = data_size;
+ int ret = CMD_RET_SUCCESS;
+
+ dst = malloc(data_size + 1);
+ if (!dst)
+ return CMD_RET_FAILURE;
+
+ ret = gunzip(dst, data_size, (unsigned char *)data_gz, &len);
+ if (ret) {
+ printf("failed to uncompress .config data\n");
+ ret = CMD_RET_FAILURE;
+ goto free;
+ }
+
+ dst[data_size] = 0;
+ puts(dst);
+
+free:
+ free(dst);
+
+ return ret;
+}
+
+U_BOOT_CMD(
+ config, 1, 1, do_config,
+ "print .config",
+ ""
+);
diff --git a/roms/u-boot/cmd/conitrace.c b/roms/u-boot/cmd/conitrace.c
new file mode 100644
index 000000000..d50f3bf3c
--- /dev/null
+++ b/roms/u-boot/cmd/conitrace.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The 'conitrace' command prints the codes received from the console input as
+ * hexadecimal numbers.
+ *
+ * Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+#include <common.h>
+#include <command.h>
+#include <linux/delay.h>
+
+static int do_conitrace(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bool first = true;
+
+ printf("Waiting for your input\n");
+ printf("To terminate type 'x'\n");
+
+ /* Empty input buffer */
+ while (tstc())
+ getchar();
+
+ for (;;) {
+ int c = getchar();
+
+ if (first && (c == 'x' || c == 'X'))
+ break;
+
+ printf("%02x ", c);
+ first = false;
+
+ /* 10 ms delay - serves to detect separate keystrokes */
+ udelay(10000);
+ if (!tstc()) {
+ printf("\n");
+ first = true;
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char conitrace_help_text[] = "";
+#endif
+
+U_BOOT_CMD_COMPLETE(
+ conitrace, 2, 0, do_conitrace,
+ "trace console input",
+ conitrace_help_text, NULL
+);
diff --git a/roms/u-boot/cmd/console.c b/roms/u-boot/cmd/console.c
new file mode 100644
index 000000000..9a1db83c7
--- /dev/null
+++ b/roms/u-boot/cmd/console.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <stdio_dev.h>
+
+extern void _do_coninfo (void);
+static int do_coninfo(struct cmd_tbl *cmd, int flag, int argc,
+ char *const argv[])
+{
+ int l;
+ struct list_head *list = stdio_get_list();
+ struct list_head *pos;
+ struct stdio_dev *dev;
+
+ /* Scan for valid output and input devices */
+
+ puts ("List of available devices:\n");
+
+ list_for_each(pos, list) {
+ dev = list_entry(pos, struct stdio_dev, list);
+
+ printf ("%-8s %08x %c%c ",
+ dev->name,
+ dev->flags,
+ (dev->flags & DEV_FLAGS_INPUT) ? 'I' : '.',
+ (dev->flags & DEV_FLAGS_OUTPUT) ? 'O' : '.');
+
+ for (l = 0; l < MAX_FILES; l++) {
+ if (stdio_devices[l] == dev) {
+ printf ("%s ", stdio_names[l]);
+ }
+ }
+ putc ('\n');
+ }
+ return 0;
+}
+
+
+/***************************************************/
+
+U_BOOT_CMD(
+ coninfo, 3, 1, do_coninfo,
+ "print console devices and information",
+ ""
+);
diff --git a/roms/u-boot/cmd/cpu.c b/roms/u-boot/cmd/cpu.c
new file mode 100644
index 000000000..67dbb044b
--- /dev/null
+++ b/roms/u-boot/cmd/cpu.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ * Copyright (c) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+
+static const char *cpu_feature_name[CPU_FEAT_COUNT] = {
+ "L1 cache",
+ "MMU",
+ "Microcode",
+ "Device ID",
+};
+
+static int print_cpu_list(bool detail)
+{
+ struct udevice *dev;
+ char buf[100];
+
+ for (uclass_first_device(UCLASS_CPU, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ struct cpu_plat *plat = dev_get_parent_plat(dev);
+ struct cpu_info info;
+ bool first = true;
+ int ret, i;
+
+ ret = cpu_get_desc(dev, buf, sizeof(buf));
+ printf("%3d: %-10s %s\n", dev_seq(dev), dev->name,
+ ret ? "<no description>" : buf);
+ if (!detail)
+ continue;
+ ret = cpu_get_info(dev, &info);
+ if (ret) {
+ printf("\t(no detail available");
+ if (ret != -ENOSYS)
+ printf(": err=%d", ret);
+ printf(")\n");
+ continue;
+ }
+ printf("\tID = %d, freq = ", plat->cpu_id);
+ print_freq(info.cpu_freq, "");
+ for (i = 0; i < CPU_FEAT_COUNT; i++) {
+ if (info.features & (1 << i)) {
+ printf("%s%s", first ? ": " : ", ",
+ cpu_feature_name[i]);
+ first = false;
+ }
+ }
+ printf("\n");
+ if (info.features & (1 << CPU_FEAT_UCODE))
+ printf("\tMicrocode version %#x\n",
+ plat->ucode_version);
+ if (info.features & (1 << CPU_FEAT_DEVICE_ID))
+ printf("\tDevice ID %#lx\n", plat->device_id);
+ }
+
+ return 0;
+}
+
+static int do_cpu_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (print_cpu_list(false))
+ return CMD_RET_FAILURE;
+
+ return 0;
+}
+
+static int do_cpu_detail(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (print_cpu_list(true))
+ return CMD_RET_FAILURE;
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_cpu_sub[] = {
+ U_BOOT_CMD_MKENT(list, 2, 1, do_cpu_list, "", ""),
+ U_BOOT_CMD_MKENT(detail, 4, 0, do_cpu_detail, "", ""),
+};
+
+/*
+ * Process a cpu sub-command
+ */
+static int do_cpu(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c = NULL;
+
+ /* Strip off leading 'cpu' command argument */
+ argc--;
+ argv++;
+
+ if (argc)
+ c = find_cmd_tbl(argv[0], cmd_cpu_sub,
+ ARRAY_SIZE(cmd_cpu_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+ cpu, 2, 1, do_cpu,
+ "display information about CPUs",
+ "list - list available CPUs\n"
+ "cpu detail - show CPU detail"
+);
diff --git a/roms/u-boot/cmd/cramfs.c b/roms/u-boot/cmd/cramfs.c
new file mode 100644
index 000000000..1aeb56702
--- /dev/null
+++ b/roms/u-boot/cmd/cramfs.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *
+ * based on: cmd_jffs2.c
+ *
+ * Add support for a CRAMFS located in RAM
+ */
+
+
+/*
+ * CRAMFS support
+ */
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <jffs2/jffs2.h>
+#include <jffs2/load_kernel.h>
+#include <cramfs/cramfs_fs.h>
+#include <asm/io.h>
+
+/* enable/disable debugging messages */
+#define DEBUG_CRAMFS
+#undef DEBUG_CRAMFS
+
+#ifdef DEBUG_CRAMFS
+# define DEBUGF(fmt, args...) printf(fmt ,##args)
+#else
+# define DEBUGF(fmt, args...)
+#endif
+
+#include <flash.h>
+
+#ifndef CONFIG_MTD_NOR_FLASH
+# define OFFSET_ADJUSTMENT 0
+#else
+# define OFFSET_ADJUSTMENT (flash_info[id.num].start[0])
+#endif
+
+#ifndef CONFIG_FS_JFFS2
+#include <linux/stat.h>
+char *mkmodestr(unsigned long mode, char *str)
+{
+ static const char *l = "xwr";
+ int mask = 1, i;
+ char c;
+
+ switch (mode & S_IFMT) {
+ case S_IFDIR: str[0] = 'd'; break;
+ case S_IFBLK: str[0] = 'b'; break;
+ case S_IFCHR: str[0] = 'c'; break;
+ case S_IFIFO: str[0] = 'f'; break;
+ case S_IFLNK: str[0] = 'l'; break;
+ case S_IFSOCK: str[0] = 's'; break;
+ case S_IFREG: str[0] = '-'; break;
+ default: str[0] = '?';
+ }
+
+ for(i = 0; i < 9; i++) {
+ c = l[i%3];
+ str[9-i] = (mode & mask)?c:'-';
+ mask = mask<<1;
+ }
+
+ if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S';
+ if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S';
+ if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T';
+ str[10] = '\0';
+ return str;
+}
+#endif /* CONFIG_FS_JFFS2 */
+
+extern int cramfs_check (struct part_info *info);
+extern int cramfs_load (char *loadoffset, struct part_info *info, char *filename);
+extern int cramfs_ls (struct part_info *info, char *filename);
+extern int cramfs_info (struct part_info *info);
+
+/***************************************************/
+/* U-Boot commands */
+/***************************************************/
+
+/**
+ * Routine implementing fsload u-boot command. This routine tries to load
+ * a requested file from cramfs filesystem at location 'cramfsaddr'.
+ * cramfsaddr is an evironment variable.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_cramfs_load(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *filename;
+ int size;
+ ulong offset = image_load_addr;
+ char *offset_virt;
+
+ struct part_info part;
+ struct mtd_device dev;
+ struct mtdids id;
+
+ ulong addr;
+ addr = simple_strtoul(env_get("cramfsaddr"), NULL, 16);
+
+ /* hack! */
+ /* cramfs_* only supports NOR flash chips */
+ /* fake the device type */
+ id.type = MTD_DEV_TYPE_NOR;
+ id.num = 0;
+ dev.id = &id;
+ part.dev = &dev;
+ /* fake the address offset */
+ part.offset = (u64)(uintptr_t) map_sysmem(addr - OFFSET_ADJUSTMENT, 0);
+
+ /* pre-set Boot file name */
+ filename = env_get("bootfile");
+ if (!filename)
+ filename = "uImage";
+
+ if (argc == 2) {
+ filename = argv[1];
+ }
+ if (argc == 3) {
+ offset = simple_strtoul(argv[1], NULL, 0);
+ image_load_addr = offset;
+ filename = argv[2];
+ }
+
+ offset_virt = map_sysmem(offset, 0);
+ size = 0;
+ if (cramfs_check(&part))
+ size = cramfs_load (offset_virt, &part, filename);
+
+ if (size > 0) {
+ printf("### CRAMFS load complete: %d bytes loaded to 0x%lx\n",
+ size, offset);
+ env_set_hex("filesize", size);
+ } else {
+ printf("### CRAMFS LOAD ERROR<%x> for %s!\n", size, filename);
+ }
+
+ unmap_sysmem(offset_virt);
+ unmap_sysmem((void *)(uintptr_t)part.offset);
+
+ return !(size > 0);
+}
+
+/**
+ * Routine implementing u-boot ls command which lists content of a given
+ * directory at location 'cramfsaddr'.
+ * cramfsaddr is an evironment variable.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_cramfs_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *filename = "/";
+ int ret;
+ struct part_info part;
+ struct mtd_device dev;
+ struct mtdids id;
+
+ ulong addr;
+ addr = simple_strtoul(env_get("cramfsaddr"), NULL, 16);
+
+ /* hack! */
+ /* cramfs_* only supports NOR flash chips */
+ /* fake the device type */
+ id.type = MTD_DEV_TYPE_NOR;
+ id.num = 0;
+ dev.id = &id;
+ part.dev = &dev;
+ /* fake the address offset */
+ part.offset = (u64)(uintptr_t) map_sysmem(addr - OFFSET_ADJUSTMENT, 0);
+
+ if (argc == 2)
+ filename = argv[1];
+
+ ret = 0;
+ if (cramfs_check(&part))
+ ret = cramfs_ls (&part, filename);
+ unmap_sysmem((void *)(uintptr_t)part.offset);
+
+ return ret ? 0 : 1;
+}
+
+/* command line only */
+
+/***************************************************/
+U_BOOT_CMD(
+ cramfsload, 3, 0, do_cramfs_load,
+ "load binary file from a filesystem image",
+ "[ off ] [ filename ]\n"
+ " - load binary file from address 'cramfsaddr'\n"
+ " with offset 'off'\n"
+);
+U_BOOT_CMD(
+ cramfsls, 2, 1, do_cramfs_ls,
+ "list files in a directory (default /)",
+ "[ directory ]\n"
+ " - list files in a directory.\n"
+);
diff --git a/roms/u-boot/cmd/cros_ec.c b/roms/u-boot/cmd/cros_ec.c
new file mode 100644
index 000000000..eb5053d64
--- /dev/null
+++ b/roms/u-boot/cmd/cros_ec.c
@@ -0,0 +1,570 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Chromium OS cros_ec driver
+ *
+ * Copyright (c) 2016 The Chromium OS Authors.
+ * Copyright (c) 2016 National Instruments Corp
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cros_ec.h>
+#include <dm.h>
+#include <flash.h>
+#include <log.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+/* Note: depends on enum ec_current_image */
+static const char * const ec_current_image_name[] = {"unknown", "RO", "RW"};
+
+/**
+ * Decode a flash region parameter
+ *
+ * @param argc Number of params remaining
+ * @param argv List of remaining parameters
+ * @return flash region (EC_FLASH_REGION_...) or -1 on error
+ */
+static int cros_ec_decode_region(int argc, char *const argv[])
+{
+ if (argc > 0) {
+ if (0 == strcmp(*argv, "rw"))
+ return EC_FLASH_REGION_ACTIVE;
+ else if (0 == strcmp(*argv, "ro"))
+ return EC_FLASH_REGION_RO;
+
+ debug("%s: Invalid region '%s'\n", __func__, *argv);
+ } else {
+ debug("%s: Missing region parameter\n", __func__);
+ }
+
+ return -1;
+}
+
+/**
+ * Perform a flash read or write command
+ *
+ * @param dev CROS-EC device to read/write
+ * @param is_write 1 do to a write, 0 to do a read
+ * @param argc Number of arguments
+ * @param argv Arguments (2 is region, 3 is address)
+ * @return 0 for ok, 1 for a usage error or -ve for ec command error
+ * (negative EC_RES_...)
+ */
+static int do_read_write(struct udevice *dev, int is_write, int argc,
+ char *const argv[])
+{
+ uint32_t offset, size = -1U, region_size;
+ unsigned long addr;
+ char *endp;
+ int region;
+ int ret;
+
+ region = cros_ec_decode_region(argc - 2, argv + 2);
+ if (region == -1)
+ return 1;
+ if (argc < 4)
+ return 1;
+ addr = simple_strtoul(argv[3], &endp, 16);
+ if (*argv[3] == 0 || *endp != 0)
+ return 1;
+ if (argc > 4) {
+ size = simple_strtoul(argv[4], &endp, 16);
+ if (*argv[4] == 0 || *endp != 0)
+ return 1;
+ }
+
+ ret = cros_ec_flash_offset(dev, region, &offset, &region_size);
+ if (ret) {
+ debug("%s: Could not read region info\n", __func__);
+ return ret;
+ }
+ if (size == -1U)
+ size = region_size;
+
+ ret = is_write ?
+ cros_ec_flash_write(dev, (uint8_t *)addr, offset, size) :
+ cros_ec_flash_read(dev, (uint8_t *)addr, offset, size);
+ if (ret) {
+ debug("%s: Could not %s region\n", __func__,
+ is_write ? "write" : "read");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const char *const feat_name[64] = {
+ "limited",
+ "flash",
+ "pwm_fan",
+ "pwm_keyb",
+ "lightbar",
+ "led",
+ "motion_sense",
+ "keyb",
+ "pstore",
+ "port80",
+ "thermal",
+ "bklight_switch",
+ "wifi_switch",
+ "host_events",
+ "gpio",
+ "i2c",
+ "charger",
+ "battery",
+ "smart_battery",
+ "hang_detect",
+ "pmu",
+ "sub_mcu",
+ "usb_pd",
+ "usb_mux",
+ "motion_sense_fifo",
+ "vstore",
+ "usbc_ss_mux_virtual",
+ "rtc",
+ "fingerprint",
+ "touchpad",
+ "rwsig",
+ "device_event",
+ "unified_wake_masks",
+ "host_event64",
+ "exec_in_ram",
+ "cec",
+ "motion_sense_tight_timestamps",
+ "refined_tablet_mode_hysteresis",
+ "efs2",
+ "scp",
+ "ish",
+ "typec_cmd",
+ "typec_require_ap_mode_entry",
+ "typec_mux_require_ap_ack",
+};
+
+static int do_show_features(struct udevice *dev)
+{
+ u64 feat;
+ int ret;
+ uint i;
+
+ ret = cros_ec_get_features(dev, &feat);
+ if (ret)
+ return ret;
+ for (i = 0; i < ARRAY_SIZE(feat_name); i++) {
+ if (feat & (1ULL << i)) {
+ if (feat_name[i])
+ printf("%s\n", feat_name[i]);
+ else
+ printf("unknown %d\n", i);
+ }
+ }
+
+ return 0;
+}
+
+static const char *const switch_name[8] = {
+ "lid open",
+ "power button pressed",
+ "write-protect disabled",
+ NULL,
+ "dedicated recovery",
+ NULL,
+ NULL,
+ NULL,
+};
+
+static int do_show_switches(struct udevice *dev)
+{
+ uint switches;
+ int ret;
+ uint i;
+
+ ret = cros_ec_get_switches(dev);
+ if (ret < 0)
+ return log_msg_ret("get", ret);
+ switches = ret;
+ for (i = 0; i < ARRAY_SIZE(switch_name); i++) {
+ uint mask = 1 << i;
+
+ if (switches & mask) {
+ if (switch_name[i])
+ printf("%s\n", switch_name[i]);
+ else
+ printf("unknown %02x\n", mask);
+ }
+ }
+
+ return 0;
+}
+
+static const char *const event_name[] = {
+ "lid_closed",
+ "lid_open",
+ "power_button",
+ "ac_connected",
+ "ac_disconnected",
+ "battery_low",
+ "battery_critical",
+ "battery",
+ "thermal_threshold",
+ "device",
+ "thermal",
+ "usb_charger",
+ "key_pressed",
+ "interface_ready",
+ "keyboard_recovery",
+ "thermal_shutdown",
+ "battery_shutdown",
+ "throttle_start",
+ "throttle_stop",
+ "hang_detect",
+ "hang_reboot",
+ "pd_mcu",
+ "battery_status",
+ "panic",
+ "keyboard_fastboot",
+ "rtc",
+ "mkbp",
+ "usb_mux",
+ "mode_change",
+ "keyboard_recovery_hw_reinit",
+ "extended",
+ "invalid",
+};
+
+static int do_show_events(struct udevice *dev)
+{
+ u32 events;
+ int ret;
+ uint i;
+
+ ret = cros_ec_get_host_events(dev, &events);
+ if (ret)
+ return ret;
+ printf("%08x\n", events);
+ for (i = 0; i < ARRAY_SIZE(event_name); i++) {
+ enum host_event_code code = i + 1;
+ u64 mask = EC_HOST_EVENT_MASK(code);
+
+ if (events & mask) {
+ if (event_name[i])
+ printf("%s\n", event_name[i]);
+ else
+ printf("unknown code %#x\n", code);
+ }
+ }
+
+ return 0;
+}
+
+static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ const char *cmd;
+ int ret = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ cmd = argv[1];
+ if (0 == strcmp("init", cmd)) {
+ /* Remove any existing device */
+ ret = uclass_find_device(UCLASS_CROS_EC, 0, &dev);
+ if (!ret)
+ device_remove(dev, DM_REMOVE_NORMAL);
+ ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
+ if (ret) {
+ printf("Could not init cros_ec device (err %d)\n", ret);
+ return 1;
+ }
+ return 0;
+ }
+
+ ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev);
+ if (ret) {
+ printf("Cannot get cros-ec device (err=%d)\n", ret);
+ return 1;
+ }
+ if (0 == strcmp("id", cmd)) {
+ char id[MSG_BYTES];
+
+ if (cros_ec_read_id(dev, id, sizeof(id))) {
+ debug("%s: Could not read KBC ID\n", __func__);
+ return 1;
+ }
+ printf("%s\n", id);
+ } else if (0 == strcmp("info", cmd)) {
+ struct ec_response_mkbp_info info;
+
+ if (cros_ec_info(dev, &info)) {
+ debug("%s: Could not read KBC info\n", __func__);
+ return 1;
+ }
+ printf("rows = %u\n", info.rows);
+ printf("cols = %u\n", info.cols);
+ } else if (!strcmp("features", cmd)) {
+ ret = do_show_features(dev);
+
+ if (ret)
+ printf("Error: %d\n", ret);
+ } else if (!strcmp("switches", cmd)) {
+ ret = do_show_switches(dev);
+
+ if (ret)
+ printf("Error: %d\n", ret);
+ } else if (0 == strcmp("curimage", cmd)) {
+ enum ec_current_image image;
+
+ if (cros_ec_read_current_image(dev, &image)) {
+ debug("%s: Could not read KBC image\n", __func__);
+ return 1;
+ }
+ printf("%d\n", image);
+ } else if (0 == strcmp("hash", cmd)) {
+ struct ec_response_vboot_hash hash;
+ int i;
+
+ if (cros_ec_read_hash(dev, EC_VBOOT_HASH_OFFSET_ACTIVE, &hash)) {
+ debug("%s: Could not read KBC hash\n", __func__);
+ return 1;
+ }
+
+ if (hash.hash_type == EC_VBOOT_HASH_TYPE_SHA256)
+ printf("type: SHA-256\n");
+ else
+ printf("type: %d\n", hash.hash_type);
+
+ printf("offset: 0x%08x\n", hash.offset);
+ printf("size: 0x%08x\n", hash.size);
+
+ printf("digest: ");
+ for (i = 0; i < hash.digest_size; i++)
+ printf("%02x", hash.hash_digest[i]);
+ printf("\n");
+ } else if (0 == strcmp("reboot", cmd)) {
+ int region;
+ enum ec_reboot_cmd cmd;
+
+ if (argc >= 3 && !strcmp(argv[2], "cold")) {
+ cmd = EC_REBOOT_COLD;
+ } else {
+ region = cros_ec_decode_region(argc - 2, argv + 2);
+ if (region == EC_FLASH_REGION_RO)
+ cmd = EC_REBOOT_JUMP_RO;
+ else if (region == EC_FLASH_REGION_ACTIVE)
+ cmd = EC_REBOOT_JUMP_RW;
+ else
+ return CMD_RET_USAGE;
+ }
+
+ if (cros_ec_reboot(dev, cmd, 0)) {
+ debug("%s: Could not reboot KBC\n", __func__);
+ return 1;
+ }
+ } else if (0 == strcmp("events", cmd)) {
+ ret = do_show_events(dev);
+
+ if (ret)
+ printf("Error: %d\n", ret);
+ } else if (0 == strcmp("clrevents", cmd)) {
+ uint32_t events = 0x7fffffff;
+
+ if (argc >= 3)
+ events = simple_strtol(argv[2], NULL, 0);
+
+ if (cros_ec_clear_host_events(dev, events)) {
+ debug("%s: Could not clear host events\n", __func__);
+ return 1;
+ }
+ } else if (0 == strcmp("read", cmd)) {
+ ret = do_read_write(dev, 0, argc, argv);
+ if (ret > 0)
+ return CMD_RET_USAGE;
+ } else if (0 == strcmp("write", cmd)) {
+ ret = do_read_write(dev, 1, argc, argv);
+ if (ret > 0)
+ return CMD_RET_USAGE;
+ } else if (0 == strcmp("erase", cmd)) {
+ int region = cros_ec_decode_region(argc - 2, argv + 2);
+ uint32_t offset, size;
+
+ if (region == -1)
+ return CMD_RET_USAGE;
+ if (cros_ec_flash_offset(dev, region, &offset, &size)) {
+ debug("%s: Could not read region info\n", __func__);
+ ret = -1;
+ } else {
+ ret = cros_ec_flash_erase(dev, offset, size);
+ if (ret) {
+ debug("%s: Could not erase region\n",
+ __func__);
+ }
+ }
+ } else if (0 == strcmp("regioninfo", cmd)) {
+ int region = cros_ec_decode_region(argc - 2, argv + 2);
+ uint32_t offset, size;
+
+ if (region == -1)
+ return CMD_RET_USAGE;
+ ret = cros_ec_flash_offset(dev, region, &offset, &size);
+ if (ret) {
+ debug("%s: Could not read region info\n", __func__);
+ } else {
+ printf("Region: %s\n", region == EC_FLASH_REGION_RO ?
+ "RO" : "RW");
+ printf("Offset: %x\n", offset);
+ printf("Size: %x\n", size);
+ }
+ } else if (0 == strcmp("flashinfo", cmd)) {
+ struct ec_response_flash_info p;
+
+ ret = cros_ec_read_flashinfo(dev, &p);
+ if (!ret) {
+ printf("Flash size: %u\n", p.flash_size);
+ printf("Write block size: %u\n", p.write_block_size);
+ printf("Erase block size: %u\n", p.erase_block_size);
+ }
+ } else if (0 == strcmp("vbnvcontext", cmd)) {
+ uint8_t block[EC_VBNV_BLOCK_SIZE];
+ char buf[3];
+ int i, len;
+ unsigned long result;
+
+ if (argc <= 2) {
+ ret = cros_ec_read_nvdata(dev, block,
+ EC_VBNV_BLOCK_SIZE);
+ if (!ret) {
+ printf("vbnv_block: ");
+ for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++)
+ printf("%02x", block[i]);
+ putc('\n');
+ }
+ } else {
+ /*
+ * TODO(clchiou): Move this to a utility function as
+ * cmd_spi might want to call it.
+ */
+ memset(block, 0, EC_VBNV_BLOCK_SIZE);
+ len = strlen(argv[2]);
+ buf[2] = '\0';
+ for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++) {
+ if (i * 2 >= len)
+ break;
+ buf[0] = argv[2][i * 2];
+ if (i * 2 + 1 >= len)
+ buf[1] = '0';
+ else
+ buf[1] = argv[2][i * 2 + 1];
+ strict_strtoul(buf, 16, &result);
+ block[i] = result;
+ }
+ ret = cros_ec_write_nvdata(dev, block,
+ EC_VBNV_BLOCK_SIZE);
+ }
+ if (ret) {
+ debug("%s: Could not %s VbNvContext\n", __func__,
+ argc <= 2 ? "read" : "write");
+ }
+ } else if (0 == strcmp("test", cmd)) {
+ int result = cros_ec_test(dev);
+
+ if (result)
+ printf("Test failed with error %d\n", result);
+ else
+ puts("Test passed\n");
+ } else if (0 == strcmp("version", cmd)) {
+ struct ec_response_get_version *p;
+ char *build_string;
+
+ ret = cros_ec_read_version(dev, &p);
+ if (!ret) {
+ /* Print versions */
+ printf("RO version: %1.*s\n",
+ (int)sizeof(p->version_string_ro),
+ p->version_string_ro);
+ printf("RW version: %1.*s\n",
+ (int)sizeof(p->version_string_rw),
+ p->version_string_rw);
+ printf("Firmware copy: %s\n",
+ (p->current_image <
+ ARRAY_SIZE(ec_current_image_name) ?
+ ec_current_image_name[p->current_image] :
+ "?"));
+ ret = cros_ec_read_build_info(dev, &build_string);
+ if (!ret)
+ printf("Build info: %s\n", build_string);
+ }
+ } else if (0 == strcmp("ldo", cmd)) {
+ uint8_t index, state;
+ char *endp;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+ index = simple_strtoul(argv[2], &endp, 10);
+ if (*argv[2] == 0 || *endp != 0)
+ return CMD_RET_USAGE;
+ if (argc > 3) {
+ state = simple_strtoul(argv[3], &endp, 10);
+ if (*argv[3] == 0 || *endp != 0)
+ return CMD_RET_USAGE;
+ ret = cros_ec_set_ldo(dev, index, state);
+ } else {
+ ret = cros_ec_get_ldo(dev, index, &state);
+ if (!ret) {
+ printf("LDO%d: %s\n", index,
+ state == EC_LDO_STATE_ON ?
+ "on" : "off");
+ }
+ }
+
+ if (ret) {
+ debug("%s: Could not access LDO%d\n", __func__, index);
+ return ret;
+ }
+ } else if (!strcmp("sku", cmd)) {
+ ret = cros_ec_get_sku_id(dev);
+
+ if (ret >= 0) {
+ printf("%d\n", ret);
+ ret = 0;
+ } else {
+ printf("Error: %d\n", ret);
+ }
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ if (ret < 0) {
+ printf("Error: CROS-EC command failed (error %d)\n", ret);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+U_BOOT_CMD(
+ crosec, 6, 1, do_cros_ec,
+ "CROS-EC utility command",
+ "init Re-init CROS-EC (done on startup automatically)\n"
+ "crosec id Read CROS-EC ID\n"
+ "crosec info Read CROS-EC info\n"
+ "crosec features Read CROS-EC features\n"
+ "crosec switches Read CROS-EC switches\n"
+ "crosec curimage Read CROS-EC current image\n"
+ "crosec hash Read CROS-EC hash\n"
+ "crosec reboot [rw | ro | cold] Reboot CROS-EC\n"
+ "crosec events Read CROS-EC host events\n"
+ "crosec eventsb Read CROS-EC host events_b\n"
+ "crosec clrevents [mask] Clear CROS-EC host events\n"
+ "crosec regioninfo <ro|rw> Read image info\n"
+ "crosec flashinfo Read flash info\n"
+ "crosec erase <ro|rw> Erase EC image\n"
+ "crosec read <ro|rw> <addr> [<size>] Read EC image\n"
+ "crosec write <ro|rw> <addr> [<size>] Write EC image\n"
+ "crosec vbnvcontext [hexstring] Read [write] VbNvContext from EC\n"
+ "crosec ldo <idx> [<state>] Switch/Read LDO state\n"
+ "crosec sku Read board SKU ID\n"
+ "crosec test run tests on cros_ec\n"
+ "crosec version Read CROS-EC version"
+);
diff --git a/roms/u-boot/cmd/dataflash_mmc_mux.c b/roms/u-boot/cmd/dataflash_mmc_mux.c
new file mode 100644
index 000000000..73876e946
--- /dev/null
+++ b/roms/u-boot/cmd/dataflash_mmc_mux.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int mmc_nspi (const char *);
+
+int do_dataflash_mmc_mux(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ switch (argc) {
+ case 2: /* on / off */
+ switch (mmc_nspi (argv[1])) {
+ case 0: AT91F_SelectSPI ();
+ break;
+ case 1: AT91F_SelectMMC ();
+ break;
+ }
+ case 1: /* get status */
+ printf ("Mux is configured to be %s\n",
+ AT91F_GetMuxStatus () ? "MMC" : "SPI");
+ return 0;
+ default:
+ return CMD_RET_USAGE;
+ }
+ return 0;
+}
+
+static int mmc_nspi (const char *s)
+{
+ if (strcmp (s, "mmc") == 0) {
+ return 1;
+ } else if (strcmp (s, "spi") == 0) {
+ return 0;
+ }
+ return -1;
+}
+
+U_BOOT_CMD(
+ dataflash_mmc_mux, 2, 1, do_dataflash_mmc_mux,
+ "enable or disable MMC or SPI\n",
+ "[mmc, spi]\n"
+ " - enable or disable MMC or SPI"
+);
diff --git a/roms/u-boot/cmd/date.c b/roms/u-boot/cmd/date.c
new file mode 100644
index 000000000..0e1189475
--- /dev/null
+++ b/roms/u-boot/cmd/date.c
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * RTC, Date & Time support: get and set date & time
+ */
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <rtc.h>
+#include <i2c.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const char * const weekdays[] = {
+ "Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
+};
+
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+#define RELOC(a) ((typeof(a))((unsigned long)(a) + gd->reloc_off))
+#else
+#define RELOC(a) a
+#endif
+
+int mk_date (const char *, struct rtc_time *);
+
+static struct rtc_time default_tm = { 0, 0, 0, 1, 1, 2000, 6, 0, 0 };
+
+static int do_date(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct rtc_time tm;
+ int rcode = 0;
+ int old_bus __maybe_unused;
+
+ /* switch to correct I2C bus */
+#ifdef CONFIG_DM_RTC
+ struct udevice *dev;
+
+ rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
+ if (rcode) {
+ printf("Cannot find RTC: err=%d\n", rcode);
+ return CMD_RET_FAILURE;
+ }
+#elif defined(CONFIG_SYS_I2C)
+ old_bus = i2c_get_bus_num();
+ i2c_set_bus_num(CONFIG_SYS_RTC_BUS_NUM);
+#else
+ old_bus = I2C_GET_BUS();
+ I2C_SET_BUS(CONFIG_SYS_RTC_BUS_NUM);
+#endif
+
+ switch (argc) {
+ case 2: /* set date & time */
+ if (strcmp(argv[1],"reset") == 0) {
+ puts ("Reset RTC...\n");
+#ifdef CONFIG_DM_RTC
+ rcode = dm_rtc_reset(dev);
+ if (!rcode)
+ rcode = dm_rtc_set(dev, &default_tm);
+#else
+ rtc_reset();
+ rcode = rtc_set(&default_tm);
+#endif
+ if (rcode)
+ puts("## Failed to set date after RTC reset\n");
+ } else {
+ /* initialize tm with current time */
+#ifdef CONFIG_DM_RTC
+ rcode = dm_rtc_get(dev, &tm);
+#else
+ rcode = rtc_get(&tm);
+#endif
+ if (!rcode) {
+ /* insert new date & time */
+ if (mk_date(argv[1], &tm) != 0) {
+ puts ("## Bad date format\n");
+ break;
+ }
+ /* and write to RTC */
+#ifdef CONFIG_DM_RTC
+ rcode = dm_rtc_set(dev, &tm);
+#else
+ rcode = rtc_set(&tm);
+#endif
+ if (rcode) {
+ printf("## Set date failed: err=%d\n",
+ rcode);
+ }
+ } else {
+ puts("## Get date failed\n");
+ }
+ }
+ /* FALL TROUGH */
+ case 1: /* get date & time */
+#ifdef CONFIG_DM_RTC
+ rcode = dm_rtc_get(dev, &tm);
+#else
+ rcode = rtc_get(&tm);
+#endif
+ if (rcode) {
+ puts("## Get date failed\n");
+ break;
+ }
+
+ printf ("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n",
+ tm.tm_year, tm.tm_mon, tm.tm_mday,
+ (tm.tm_wday<0 || tm.tm_wday>6) ?
+ "unknown " : RELOC(weekdays[tm.tm_wday]),
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+ break;
+ default:
+ rcode = CMD_RET_USAGE;
+ }
+
+ /* switch back to original I2C bus */
+#ifdef CONFIG_SYS_I2C
+ i2c_set_bus_num(old_bus);
+#elif !defined(CONFIG_DM_RTC)
+ I2C_SET_BUS(old_bus);
+#endif
+
+ return rcode ? CMD_RET_FAILURE : 0;
+}
+
+/*
+ * simple conversion of two-digit string with error checking
+ */
+static int cnvrt2 (const char *str, int *valp)
+{
+ int val;
+
+ if ((*str < '0') || (*str > '9'))
+ return (-1);
+
+ val = *str - '0';
+
+ ++str;
+
+ if ((*str < '0') || (*str > '9'))
+ return (-1);
+
+ *valp = 10 * val + (*str - '0');
+
+ return (0);
+}
+
+/*
+ * Convert date string: MMDDhhmm[[CC]YY][.ss]
+ *
+ * Some basic checking for valid values is done, but this will not catch
+ * all possible error conditions.
+ */
+int mk_date (const char *datestr, struct rtc_time *tmp)
+{
+ int len, val;
+ char *ptr;
+
+ ptr = strchr(datestr, '.');
+ len = strlen(datestr);
+
+ /* Set seconds */
+ if (ptr) {
+ int sec;
+
+ ptr++;
+ if ((len - (ptr - datestr)) != 2)
+ return (-1);
+
+ len -= 3;
+
+ if (cnvrt2 (ptr, &sec))
+ return (-1);
+
+ tmp->tm_sec = sec;
+ } else {
+ tmp->tm_sec = 0;
+ }
+
+ if (len == 12) { /* MMDDhhmmCCYY */
+ int year, century;
+
+ if (cnvrt2 (datestr+ 8, &century) ||
+ cnvrt2 (datestr+10, &year) ) {
+ return (-1);
+ }
+ tmp->tm_year = 100 * century + year;
+ } else if (len == 10) { /* MMDDhhmmYY */
+ int year, century;
+
+ century = tmp->tm_year / 100;
+ if (cnvrt2 (datestr+ 8, &year))
+ return (-1);
+ tmp->tm_year = 100 * century + year;
+ }
+
+ switch (len) {
+ case 8: /* MMDDhhmm */
+ /* fall thru */
+ case 10: /* MMDDhhmmYY */
+ /* fall thru */
+ case 12: /* MMDDhhmmCCYY */
+ if (cnvrt2 (datestr+0, &val) ||
+ val > 12) {
+ break;
+ }
+ tmp->tm_mon = val;
+ if (cnvrt2 (datestr+2, &val) ||
+ val > ((tmp->tm_mon==2) ? 29 : 31)) {
+ break;
+ }
+ tmp->tm_mday = val;
+
+ if (cnvrt2 (datestr+4, &val) ||
+ val > 23) {
+ break;
+ }
+ tmp->tm_hour = val;
+
+ if (cnvrt2 (datestr+6, &val) ||
+ val > 59) {
+ break;
+ }
+ tmp->tm_min = val;
+
+ /* calculate day of week */
+ rtc_calc_weekday(tmp);
+
+ return (0);
+ default:
+ break;
+ }
+
+ return (-1);
+}
+
+/***************************************************/
+
+U_BOOT_CMD(
+ date, 2, 1, do_date,
+ "get/set/reset date & time",
+ "[MMDDhhmm[[CC]YY][.ss]]\ndate reset\n"
+ " - without arguments: print date & time\n"
+ " - with numeric argument: set the system date & time\n"
+ " - with 'reset' argument: reset the RTC"
+);
diff --git a/roms/u-boot/cmd/demo.c b/roms/u-boot/cmd/demo.c
new file mode 100644
index 000000000..78a55f72b
--- /dev/null
+++ b/roms/u-boot/cmd/demo.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <dm-demo.h>
+#include <mapmem.h>
+#include <asm/io.h>
+
+struct udevice *demo_dev;
+
+static int do_demo_hello(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ch = 0;
+
+ if (argc)
+ ch = *argv[0];
+
+ return demo_hello(demo_dev, ch);
+}
+
+static int do_demo_status(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int status;
+ int ret;
+
+ ret = demo_status(demo_dev, &status);
+ if (ret)
+ return ret;
+
+ printf("Status: %d\n", status);
+
+ return 0;
+}
+
+static int do_demo_light(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int light;
+ int ret;
+
+ if (argc) {
+ light = simple_strtoul(argv[0], NULL, 16);
+ ret = demo_set_light(demo_dev, light);
+ } else {
+ ret = demo_get_light(demo_dev);
+ if (ret >= 0) {
+ printf("Light: %x\n", ret);
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+int do_demo_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct udevice *dev;
+ int i, ret;
+
+ puts("Demo uclass entries:\n");
+
+ for (i = 0, ret = uclass_first_device(UCLASS_DEMO, &dev);
+ dev;
+ ret = uclass_next_device(&dev)) {
+ printf("entry %d - instance %08x, ops %08x, plat %08x\n",
+ i++, (uint)map_to_sysmem(dev),
+ (uint)map_to_sysmem(dev->driver->ops),
+ (uint)map_to_sysmem(dev_get_plat(dev)));
+ }
+
+ return cmd_process_error(cmdtp, ret);
+}
+
+static struct cmd_tbl demo_commands[] = {
+ U_BOOT_CMD_MKENT(list, 0, 1, do_demo_list, "", ""),
+ U_BOOT_CMD_MKENT(hello, 2, 1, do_demo_hello, "", ""),
+ U_BOOT_CMD_MKENT(light, 2, 1, do_demo_light, "", ""),
+ U_BOOT_CMD_MKENT(status, 1, 1, do_demo_status, "", ""),
+};
+
+static int do_demo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *demo_cmd;
+ int devnum = 0;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ demo_cmd = find_cmd_tbl(argv[1], demo_commands,
+ ARRAY_SIZE(demo_commands));
+ argc -= 2;
+ argv += 2;
+
+ if ((!demo_cmd || argc > demo_cmd->maxargs) ||
+ ((demo_cmd->name[0] != 'l') && (argc < 1)))
+ return CMD_RET_USAGE;
+
+ if (argc) {
+ devnum = simple_strtoul(argv[0], NULL, 10);
+ ret = uclass_get_device(UCLASS_DEMO, devnum, &demo_dev);
+ if (ret)
+ return cmd_process_error(cmdtp, ret);
+ argc--;
+ argv++;
+ } else {
+ demo_dev = NULL;
+ if (demo_cmd->cmd != do_demo_list)
+ return CMD_RET_USAGE;
+ }
+
+ ret = demo_cmd->cmd(demo_cmd, flag, argc, argv);
+
+ return cmd_process_error(demo_cmd, ret);
+}
+
+U_BOOT_CMD(
+ demo, 4, 1, do_demo,
+ "Driver model (dm) demo operations",
+ "list List available demo devices\n"
+ "demo hello <num> [<char>] Say hello\n"
+ "demo light [<num>] Set or get the lights\n"
+ "demo status <num> Get demo device status\n"
+);
diff --git a/roms/u-boot/cmd/dfu.c b/roms/u-boot/cmd/dfu.c
new file mode 100644
index 000000000..4a288f74c
--- /dev/null
+++ b/roms/u-boot/cmd/dfu.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * cmd_dfu.c -- dfu command
+ *
+ * Copyright (C) 2015
+ * Lukasz Majewski <l.majewski@majess.pl>
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ * Lukasz Majewski <l.majewski@samsung.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <watchdog.h>
+#include <dfu.h>
+#include <console.h>
+#include <g_dnl.h>
+#include <usb.h>
+#include <net.h>
+
+static int do_dfu(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+#ifdef CONFIG_DFU_OVER_USB
+ char *usb_controller = argv[1];
+#endif
+#if defined(CONFIG_DFU_OVER_USB) || defined(CONFIG_DFU_OVER_TFTP)
+ char *interface = NULL;
+ char *devstring = NULL;
+#if defined(CONFIG_DFU_TIMEOUT) || defined(CONFIG_DFU_OVER_TFTP)
+ unsigned long value = 0;
+#endif
+ if (argc >= 4) {
+ interface = argv[2];
+ devstring = argv[3];
+ }
+
+#if defined(CONFIG_DFU_TIMEOUT) || defined(CONFIG_DFU_OVER_TFTP)
+ if (argc == 5 || argc == 3)
+ value = simple_strtoul(argv[argc - 1], NULL, 0);
+#endif
+#endif
+
+ int ret = 0;
+#ifdef CONFIG_DFU_OVER_TFTP
+ if (!strcmp(argv[1], "tftp"))
+ return update_tftp(value, interface, devstring);
+#endif
+#ifdef CONFIG_DFU_OVER_USB
+ ret = dfu_init_env_entities(interface, devstring);
+ if (ret)
+ goto done;
+
+#ifdef CONFIG_DFU_TIMEOUT
+ dfu_set_timeout(value * 1000);
+#endif
+
+ ret = CMD_RET_SUCCESS;
+ if (strcmp(argv[argc - 1], "list") == 0) {
+ dfu_show_entities();
+ goto done;
+ }
+
+ int controller_index = simple_strtoul(usb_controller, NULL, 0);
+ bool retry = false;
+ do {
+ ret = run_usb_dnl_gadget(controller_index, "usb_dnl_dfu");
+
+ if (dfu_reinit_needed) {
+ dfu_free_entities();
+ ret = dfu_init_env_entities(interface, devstring);
+ if (ret)
+ goto done;
+ retry = true;
+ }
+ } while (retry);
+
+done:
+ dfu_free_entities();
+#endif
+ return ret;
+}
+
+U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
+ "Device Firmware Upgrade",
+ ""
+#ifdef CONFIG_DFU_OVER_USB
+#ifdef CONFIG_DFU_TIMEOUT
+ "<USB_controller> [<interface> <dev>] [<timeout>] [list]\n"
+#else
+ "<USB_controller> [<interface> <dev>] [list]\n"
+#endif
+ " - device firmware upgrade via <USB_controller>\n"
+ " on device <dev>, attached to interface\n"
+ " <interface>\n"
+#ifdef CONFIG_DFU_TIMEOUT
+ " [<timeout>] - specify inactivity timeout in seconds\n"
+#endif
+ " [list] - list available alt settings\n"
+#endif
+#ifdef CONFIG_DFU_OVER_TFTP
+#ifdef CONFIG_DFU_OVER_USB
+ "dfu "
+#endif
+ "tftp [<interface> <dev>] [<addr>]\n"
+ " - device firmware upgrade via TFTP\n"
+ " on device <dev>, attached to interface\n"
+ " <interface>\n"
+ " [<addr>] - address where FIT image has been stored\n"
+#endif
+);
diff --git a/roms/u-boot/cmd/diag.c b/roms/u-boot/cmd/diag.c
new file mode 100644
index 000000000..f51536dbf
--- /dev/null
+++ b/roms/u-boot/cmd/diag.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Diagnostics support
+ */
+#include <common.h>
+#include <command.h>
+#include <post.h>
+
+int do_diag(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned int i;
+
+ if (argc == 1 || strcmp (argv[1], "run") != 0) {
+ /* List test info */
+ if (argc == 1) {
+ puts ("Available hardware tests:\n");
+ post_info (NULL);
+ puts ("Use 'diag [<test1> [<test2> ...]]'"
+ " to get more info.\n");
+ puts ("Use 'diag run [<test1> [<test2> ...]]'"
+ " to run tests.\n");
+ } else {
+ for (i = 1; i < argc; i++) {
+ if (post_info (argv[i]) != 0)
+ printf ("%s - no such test\n", argv[i]);
+ }
+ }
+ } else {
+ /* Run tests */
+ if (argc == 2) {
+ post_run (NULL, POST_RAM | POST_MANUAL);
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (post_run (argv[i], POST_RAM | POST_MANUAL) != 0)
+ printf ("%s - unable to execute the test\n",
+ argv[i]);
+ }
+ }
+ }
+
+ return 0;
+}
+/***************************************************/
+
+U_BOOT_CMD(
+ diag, CONFIG_SYS_MAXARGS, 0, do_diag,
+ "perform board diagnostics",
+ " - print list of available tests\n"
+ "diag [test1 [test2]]\n"
+ " - print information about specified tests\n"
+ "diag run - run all available tests\n"
+ "diag run [test1 [test2]]\n"
+ " - run specified tests"
+);
diff --git a/roms/u-boot/cmd/disk.c b/roms/u-boot/cmd/disk.c
new file mode 100644
index 000000000..2726115e8
--- /dev/null
+++ b/roms/u-boot/cmd/disk.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2011
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+#include <common.h>
+#include <bootstage.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <image.h>
+#include <log.h>
+#include <part.h>
+
+int common_diskboot(struct cmd_tbl *cmdtp, const char *intf, int argc,
+ char *const argv[])
+{
+ __maybe_unused int dev;
+ int part;
+ ulong addr = CONFIG_SYS_LOAD_ADDR;
+ ulong cnt;
+ struct disk_partition info;
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ image_header_t *hdr;
+#endif
+ struct blk_desc *dev_desc;
+
+#if CONFIG_IS_ENABLED(FIT)
+ const void *fit_hdr = NULL;
+#endif
+
+ bootstage_mark(BOOTSTAGE_ID_IDE_START);
+ if (argc > 3) {
+ bootstage_error(BOOTSTAGE_ID_IDE_ADDR);
+ return CMD_RET_USAGE;
+ }
+ bootstage_mark(BOOTSTAGE_ID_IDE_ADDR);
+
+ if (argc > 1)
+ addr = simple_strtoul(argv[1], NULL, 16);
+
+ bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
+
+ part = blk_get_device_part_str(intf, (argc == 3) ? argv[2] : NULL,
+ &dev_desc, &info, 1);
+ if (part < 0) {
+ bootstage_error(BOOTSTAGE_ID_IDE_TYPE);
+ return 1;
+ }
+
+ dev = dev_desc->devnum;
+ bootstage_mark(BOOTSTAGE_ID_IDE_TYPE);
+
+ printf("\nLoading from %s device %d, partition %d: "
+ "Name: %.32s Type: %.32s\n", intf, dev, part, info.name,
+ info.type);
+
+ debug("First Block: " LBAFU ", # of blocks: " LBAFU
+ ", Block Size: %ld\n",
+ info.start, info.size, info.blksz);
+
+ if (blk_dread(dev_desc, info.start, 1, (ulong *)addr) != 1) {
+ printf("** Read error on %d:%d\n", dev, part);
+ bootstage_error(BOOTSTAGE_ID_IDE_PART_READ);
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ);
+
+ switch (genimg_get_format((void *) addr)) {
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ case IMAGE_FORMAT_LEGACY:
+ hdr = (image_header_t *) addr;
+
+ bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT);
+
+ if (!image_check_hcrc(hdr)) {
+ puts("\n** Bad Header Checksum **\n");
+ bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM);
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM);
+
+ image_print_contents(hdr);
+
+ cnt = image_get_image_size(hdr);
+ break;
+#endif
+#if CONFIG_IS_ENABLED(FIT)
+ case IMAGE_FORMAT_FIT:
+ fit_hdr = (const void *) addr;
+ puts("Fit image detected...\n");
+
+ cnt = fit_get_size(fit_hdr);
+ break;
+#endif
+ default:
+ bootstage_error(BOOTSTAGE_ID_IDE_FORMAT);
+ puts("** Unknown image type\n");
+ return 1;
+ }
+
+ cnt += info.blksz - 1;
+ cnt /= info.blksz;
+ cnt -= 1;
+
+ if (blk_dread(dev_desc, info.start + 1, cnt,
+ (ulong *)(addr + info.blksz)) != cnt) {
+ printf("** Read error on %d:%d\n", dev, part);
+ bootstage_error(BOOTSTAGE_ID_IDE_READ);
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_IDE_READ);
+
+#if CONFIG_IS_ENABLED(FIT)
+ /* This cannot be done earlier,
+ * we need complete FIT image in RAM first */
+ if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) {
+ if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
+ bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ);
+ puts("** Bad FIT image format\n");
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK);
+ }
+#endif
+
+ flush_cache(addr, (cnt+1)*info.blksz);
+
+ /* Loading ok, update default load address */
+ image_load_addr = addr;
+
+ return bootm_maybe_autostart(cmdtp, argv[0]);
+}
diff --git a/roms/u-boot/cmd/dm.c b/roms/u-boot/cmd/dm.c
new file mode 100644
index 000000000..1dd19fe45
--- /dev/null
+++ b/roms/u-boot/cmd/dm.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Marek Vasut <marex@denx.de>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <dm/root.h>
+#include <dm/util.h>
+
+static int do_dm_dump_all(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ dm_dump_all();
+
+ return 0;
+}
+
+static int do_dm_dump_uclass(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ dm_dump_uclass();
+
+ return 0;
+}
+
+static int do_dm_dump_devres(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ dm_dump_devres();
+
+ return 0;
+}
+
+static int do_dm_dump_drivers(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ dm_dump_drivers();
+
+ return 0;
+}
+
+static int do_dm_dump_driver_compat(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ dm_dump_driver_compat();
+
+ return 0;
+}
+
+static int do_dm_dump_static_driver_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ dm_dump_static_driver_info();
+
+ return 0;
+}
+
+static struct cmd_tbl test_commands[] = {
+ U_BOOT_CMD_MKENT(tree, 0, 1, do_dm_dump_all, "", ""),
+ U_BOOT_CMD_MKENT(uclass, 1, 1, do_dm_dump_uclass, "", ""),
+ U_BOOT_CMD_MKENT(devres, 1, 1, do_dm_dump_devres, "", ""),
+ U_BOOT_CMD_MKENT(drivers, 1, 1, do_dm_dump_drivers, "", ""),
+ U_BOOT_CMD_MKENT(compat, 1, 1, do_dm_dump_driver_compat, "", ""),
+ U_BOOT_CMD_MKENT(static, 1, 1, do_dm_dump_static_driver_info, "", ""),
+};
+
+static __maybe_unused void dm_reloc(void)
+{
+ static int relocated;
+
+ if (!relocated) {
+ fixup_cmdtable(test_commands, ARRAY_SIZE(test_commands));
+ relocated = 1;
+ }
+}
+
+static int do_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *test_cmd;
+ int ret;
+
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+ dm_reloc();
+#endif
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ test_cmd = find_cmd_tbl(argv[1], test_commands,
+ ARRAY_SIZE(test_commands));
+ argc -= 2;
+ argv += 2;
+ if (!test_cmd || argc > test_cmd->maxargs)
+ return CMD_RET_USAGE;
+
+ ret = test_cmd->cmd(test_cmd, flag, argc, argv);
+
+ return cmd_process_error(test_cmd, ret);
+}
+
+U_BOOT_CMD(
+ dm, 3, 1, do_dm,
+ "Driver model low level access",
+ "tree Dump driver model tree ('*' = activated)\n"
+ "dm uclass Dump list of instances for each uclass\n"
+ "dm devres Dump list of device resources for each device\n"
+ "dm drivers Dump list of drivers with uclass and instances\n"
+ "dm compat Dump list of drivers with compatibility strings\n"
+ "dm static Dump list of drivers with static platform data"
+);
diff --git a/roms/u-boot/cmd/echo.c b/roms/u-boot/cmd/echo.c
new file mode 100644
index 000000000..fda844ee9
--- /dev/null
+++ b/roms/u-boot/cmd/echo.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_echo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int i = 1;
+ bool space = false;
+ bool newline = true;
+
+ if (argc > 1) {
+ if (!strcmp(argv[1], "-n")) {
+ newline = false;
+ ++i;
+ }
+ }
+
+ for (; i < argc; ++i) {
+ if (space) {
+ putc(' ');
+ }
+ puts(argv[i]);
+ space = true;
+ }
+
+ if (newline)
+ putc('\n');
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ echo, CONFIG_SYS_MAXARGS, 1, do_echo,
+ "echo args to console",
+ "[-n] [args..]\n"
+ " - echo args to console; -n suppresses newline"
+);
diff --git a/roms/u-boot/cmd/eeprom.c b/roms/u-boot/cmd/eeprom.c
new file mode 100644
index 000000000..b3fd37c82
--- /dev/null
+++ b/roms/u-boot/cmd/eeprom.c
@@ -0,0 +1,456 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Support for read and write access to EEPROM like memory devices. This
+ * includes regular EEPROM as well as FRAM (ferroelectic nonvolaile RAM).
+ * FRAM devices read and write data at bus speed. In particular, there is no
+ * write delay. Also, there is no limit imposed on the number of bytes that can
+ * be transferred with a single read or write.
+ *
+ * Use the following configuration options to ensure no unneeded performance
+ * degradation (typical for EEPROM) is incured for FRAM memory:
+ *
+ * #define CONFIG_SYS_I2C_FRAM
+ * #undef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
+ *
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <eeprom.h>
+#include <i2c.h>
+#include <eeprom_layout.h>
+#include <linux/delay.h>
+
+#ifndef CONFIG_SYS_I2C_SPEED
+#define CONFIG_SYS_I2C_SPEED 50000
+#endif
+
+#ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 0
+#endif
+
+#ifndef CONFIG_SYS_EEPROM_PAGE_WRITE_BITS
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 8
+#endif
+
+#ifndef I2C_RXTX_LEN
+#define I2C_RXTX_LEN 128
+#endif
+
+#define EEPROM_PAGE_SIZE (1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS)
+#define EEPROM_PAGE_OFFSET(x) ((x) & (EEPROM_PAGE_SIZE - 1))
+
+/*
+ * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
+ * 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
+ *
+ * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
+ * 0x00000nxx for EEPROM address selectors and page number at n.
+ */
+#if !defined(CONFIG_SPI) || defined(CONFIG_ENV_EEPROM_IS_ON_I2C)
+#if !defined(CONFIG_SYS_I2C_EEPROM_ADDR_LEN) || \
+ (CONFIG_SYS_I2C_EEPROM_ADDR_LEN < 1) || \
+ (CONFIG_SYS_I2C_EEPROM_ADDR_LEN > 2)
+#error CONFIG_SYS_I2C_EEPROM_ADDR_LEN must be 1 or 2
+#endif
+#endif
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+static int eeprom_i2c_bus;
+#endif
+
+__weak int eeprom_write_enable(unsigned dev_addr, int state)
+{
+ return 0;
+}
+
+void eeprom_init(int bus)
+{
+ /* I2C EEPROM */
+#if CONFIG_IS_ENABLED(DM_I2C)
+ eeprom_i2c_bus = bus;
+#elif defined(CONFIG_SYS_I2C)
+ if (bus >= 0)
+ i2c_set_bus_num(bus);
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+#endif
+}
+
+static int eeprom_addr(unsigned dev_addr, unsigned offset, uchar *addr)
+{
+ unsigned blk_off;
+ int alen;
+
+ blk_off = offset & 0xff; /* block offset */
+#if CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1
+ addr[0] = offset >> 8; /* block number */
+ addr[1] = blk_off; /* block offset */
+ alen = 2;
+#else
+ addr[0] = offset >> 16; /* block number */
+ addr[1] = offset >> 8; /* upper address octet */
+ addr[2] = blk_off; /* lower address octet */
+ alen = 3;
+#endif /* CONFIG_SYS_I2C_EEPROM_ADDR_LEN */
+
+ addr[0] |= dev_addr; /* insert device address */
+
+ return alen;
+}
+
+static int eeprom_len(unsigned offset, unsigned end)
+{
+ unsigned len = end - offset;
+
+ /*
+ * For a FRAM device there is no limit on the number of the
+ * bytes that can be accessed with the single read or write
+ * operation.
+ */
+#if !defined(CONFIG_SYS_I2C_FRAM)
+ unsigned blk_off = offset & 0xff;
+ unsigned maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off);
+
+ if (maxlen > I2C_RXTX_LEN)
+ maxlen = I2C_RXTX_LEN;
+
+ if (len > maxlen)
+ len = maxlen;
+#endif
+
+ return len;
+}
+
+static int eeprom_rw_block(unsigned offset, uchar *addr, unsigned alen,
+ uchar *buffer, unsigned len, bool read)
+{
+ int ret = 0;
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+
+ ret = i2c_get_chip_for_busnum(eeprom_i2c_bus, addr[0],
+ alen - 1, &dev);
+ if (ret) {
+ printf("%s: Cannot find udev for a bus %d\n", __func__,
+ eeprom_i2c_bus);
+ return CMD_RET_FAILURE;
+ }
+
+ if (read)
+ ret = dm_i2c_read(dev, offset, buffer, len);
+ else
+ ret = dm_i2c_write(dev, offset, buffer, len);
+
+#else /* Non DM I2C support - will be removed */
+
+ if (read)
+ ret = i2c_read(addr[0], offset, alen - 1, buffer, len);
+ else
+ ret = i2c_write(addr[0], offset, alen - 1, buffer, len);
+#endif /* CONFIG_DM_I2C */
+ if (ret)
+ ret = CMD_RET_FAILURE;
+
+ return ret;
+}
+
+static int eeprom_rw(unsigned dev_addr, unsigned offset, uchar *buffer,
+ unsigned cnt, bool read)
+{
+ unsigned end = offset + cnt;
+ unsigned alen, len;
+ int rcode = 0;
+ uchar addr[3];
+
+#if defined(CONFIG_SYS_I2C_EEPROM_BUS)
+ eeprom_init(CONFIG_SYS_I2C_EEPROM_BUS);
+#endif
+
+ while (offset < end) {
+ alen = eeprom_addr(dev_addr, offset, addr);
+
+ len = eeprom_len(offset, end);
+
+ rcode = eeprom_rw_block(offset, addr, alen, buffer, len, read);
+
+ buffer += len;
+ offset += len;
+
+ if (!read)
+ udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
+ }
+
+ return rcode;
+}
+
+int eeprom_read(unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
+{
+ /*
+ * Read data until done or would cross a page boundary.
+ * We must write the address again when changing pages
+ * because the next page may be in a different device.
+ */
+ return eeprom_rw(dev_addr, offset, buffer, cnt, 1);
+}
+
+int eeprom_write(unsigned dev_addr, unsigned offset,
+ uchar *buffer, unsigned cnt)
+{
+ int ret;
+
+ eeprom_write_enable(dev_addr, 1);
+
+ /*
+ * Write data until done or would cross a write page boundary.
+ * We must write the address again when changing pages
+ * because the address counter only increments within a page.
+ */
+ ret = eeprom_rw(dev_addr, offset, buffer, cnt, 0);
+
+ eeprom_write_enable(dev_addr, 0);
+ return ret;
+}
+
+static int parse_numeric_param(char *str)
+{
+ char *endptr;
+ int value = simple_strtol(str, &endptr, 16);
+
+ return (*endptr != '\0') ? -1 : value;
+}
+
+/**
+ * parse_i2c_bus_addr - parse the i2c bus and i2c devaddr parameters
+ *
+ * @i2c_bus: address to store the i2c bus
+ * @i2c_addr: address to store the device i2c address
+ * @argc: count of command line arguments left to parse
+ * @argv: command line arguments left to parse
+ * @argc_no_bus_addr: argc value we expect to see when bus & addr aren't given
+ *
+ * @returns: number of arguments parsed or CMD_RET_USAGE if error
+ */
+static int parse_i2c_bus_addr(int *i2c_bus, ulong *i2c_addr, int argc,
+ char *const argv[], int argc_no_bus_addr)
+{
+ int argc_no_bus = argc_no_bus_addr + 1;
+ int argc_bus_addr = argc_no_bus_addr + 2;
+
+#ifdef CONFIG_SYS_DEF_EEPROM_ADDR
+ if (argc == argc_no_bus_addr) {
+ *i2c_bus = -1;
+ *i2c_addr = CONFIG_SYS_DEF_EEPROM_ADDR;
+
+ return 0;
+ }
+#endif
+ if (argc == argc_no_bus) {
+ *i2c_bus = -1;
+ *i2c_addr = parse_numeric_param(argv[0]);
+
+ return 1;
+ }
+
+ if (argc == argc_bus_addr) {
+ *i2c_bus = parse_numeric_param(argv[0]);
+ *i2c_addr = parse_numeric_param(argv[1]);
+
+ return 2;
+ }
+
+ return CMD_RET_USAGE;
+}
+
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
+
+__weak int eeprom_parse_layout_version(char *str)
+{
+ return LAYOUT_VERSION_UNRECOGNIZED;
+}
+
+static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE];
+
+#endif
+
+enum eeprom_action {
+ EEPROM_READ,
+ EEPROM_WRITE,
+ EEPROM_PRINT,
+ EEPROM_UPDATE,
+ EEPROM_ACTION_INVALID,
+};
+
+static enum eeprom_action parse_action(char *cmd)
+{
+ if (!strncmp(cmd, "read", 4))
+ return EEPROM_READ;
+ if (!strncmp(cmd, "write", 5))
+ return EEPROM_WRITE;
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
+ if (!strncmp(cmd, "print", 5))
+ return EEPROM_PRINT;
+ if (!strncmp(cmd, "update", 6))
+ return EEPROM_UPDATE;
+#endif
+
+ return EEPROM_ACTION_INVALID;
+}
+
+static int eeprom_execute_command(enum eeprom_action action, int i2c_bus,
+ ulong i2c_addr, int layout_ver, char *key,
+ char *value, ulong addr, ulong off, ulong cnt)
+{
+ int rcode = 0;
+ const char *const fmt =
+ "\nEEPROM @0x%lX %s: addr 0x%08lx off 0x%04lx count %ld ... ";
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
+ struct eeprom_layout layout;
+#endif
+
+ if (action == EEPROM_ACTION_INVALID)
+ return CMD_RET_USAGE;
+
+ eeprom_init(i2c_bus);
+ if (action == EEPROM_READ) {
+ printf(fmt, i2c_addr, "read", addr, off, cnt);
+
+ rcode = eeprom_read(i2c_addr, off, (uchar *)addr, cnt);
+
+ puts("done\n");
+ return rcode;
+ } else if (action == EEPROM_WRITE) {
+ printf(fmt, i2c_addr, "write", addr, off, cnt);
+
+ rcode = eeprom_write(i2c_addr, off, (uchar *)addr, cnt);
+
+ puts("done\n");
+ return rcode;
+ }
+
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
+ rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE);
+ if (rcode < 0)
+ return rcode;
+
+ eeprom_layout_setup(&layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE,
+ layout_ver);
+
+ if (action == EEPROM_PRINT) {
+ layout.print(&layout);
+ return 0;
+ }
+
+ layout.update(&layout, key, value);
+
+ rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE);
+#endif
+
+ return rcode;
+}
+
+#define NEXT_PARAM(argc, index) { (argc)--; (index)++; }
+int do_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int layout_ver = LAYOUT_VERSION_AUTODETECT;
+ enum eeprom_action action = EEPROM_ACTION_INVALID;
+ int i2c_bus = -1, index = 0;
+ ulong i2c_addr = -1, addr = 0, cnt = 0, off = 0;
+ int ret;
+ char *field_name = "";
+ char *field_value = "";
+
+ if (argc <= 1)
+ return CMD_RET_USAGE;
+
+ NEXT_PARAM(argc, index); /* Skip program name */
+
+ action = parse_action(argv[index]);
+ NEXT_PARAM(argc, index);
+
+ if (action == EEPROM_ACTION_INVALID)
+ return CMD_RET_USAGE;
+
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
+ if (action == EEPROM_PRINT || action == EEPROM_UPDATE) {
+ if (!strcmp(argv[index], "-l")) {
+ NEXT_PARAM(argc, index);
+ layout_ver = eeprom_parse_layout_version(argv[index]);
+ NEXT_PARAM(argc, index);
+ }
+ }
+#endif
+
+ switch (action) {
+ case EEPROM_READ:
+ case EEPROM_WRITE:
+ ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc,
+ argv + index, 3);
+ break;
+ case EEPROM_PRINT:
+ ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc,
+ argv + index, 0);
+ break;
+ case EEPROM_UPDATE:
+ ret = parse_i2c_bus_addr(&i2c_bus, &i2c_addr, argc,
+ argv + index, 2);
+ break;
+ default:
+ /* Get compiler to stop whining */
+ return CMD_RET_USAGE;
+ }
+
+ if (ret == CMD_RET_USAGE)
+ return ret;
+
+ while (ret--)
+ NEXT_PARAM(argc, index);
+
+ if (action == EEPROM_READ || action == EEPROM_WRITE) {
+ addr = parse_numeric_param(argv[index]);
+ NEXT_PARAM(argc, index);
+ off = parse_numeric_param(argv[index]);
+ NEXT_PARAM(argc, index);
+ cnt = parse_numeric_param(argv[index]);
+ }
+
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
+ if (action == EEPROM_UPDATE) {
+ field_name = argv[index];
+ NEXT_PARAM(argc, index);
+ field_value = argv[index];
+ NEXT_PARAM(argc, index);
+ }
+#endif
+
+ return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver,
+ field_name, field_value, addr, off, cnt);
+}
+
+U_BOOT_CMD(
+ eeprom, 8, 1, do_eeprom,
+ "EEPROM sub-system",
+ "read <bus> <devaddr> addr off cnt\n"
+ "eeprom write <bus> <devaddr> addr off cnt\n"
+ " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'"
+#ifdef CONFIG_CMD_EEPROM_LAYOUT
+ "\n"
+ "eeprom print [-l <layout_version>] <bus> <devaddr>\n"
+ " - Print layout fields and their data in human readable format\n"
+ "eeprom update [-l <layout_version>] <bus> <devaddr> field_name field_value\n"
+ " - Update a specific eeprom field with new data.\n"
+ " The new data must be written in the same human readable format as shown by the print command.\n"
+ "\n"
+ "LAYOUT VERSIONS\n"
+ "The -l option can be used to force the command to interpret the EEPROM data using the chosen layout.\n"
+ "If the -l option is omitted, the command will auto detect the layout based on the data in the EEPROM.\n"
+ "The values which can be provided with the -l option are:\n"
+ CONFIG_EEPROM_LAYOUT_HELP_STRING"\n"
+#endif
+)
diff --git a/roms/u-boot/cmd/efi.c b/roms/u-boot/cmd/efi.c
new file mode 100644
index 000000000..f2ed26bd4
--- /dev/null
+++ b/roms/u-boot/cmd/efi.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <efi.h>
+#include <errno.h>
+#include <log.h>
+#include <malloc.h>
+#include <sort.h>
+#include <asm/global_data.h>
+
+static const char *const type_name[] = {
+ "reserved",
+ "loader_code",
+ "loader_data",
+ "bs_code",
+ "bs_data",
+ "rt_code",
+ "rt_data",
+ "conv",
+ "unusable",
+ "acpi_reclaim",
+ "acpi_nvs",
+ "io",
+ "io_port",
+ "pal_code",
+};
+
+static struct attr_info {
+ u64 val;
+ const char *name;
+} mem_attr[] = {
+ { EFI_MEMORY_UC, "uncached" },
+ { EFI_MEMORY_WC, "write-coalescing" },
+ { EFI_MEMORY_WT, "write-through" },
+ { EFI_MEMORY_WB, "write-back" },
+ { EFI_MEMORY_UCE, "uncached & exported" },
+ { EFI_MEMORY_WP, "write-protect" },
+ { EFI_MEMORY_RP, "read-protect" },
+ { EFI_MEMORY_XP, "execute-protect" },
+ { EFI_MEMORY_NV, "non-volatile" },
+ { EFI_MEMORY_MORE_RELIABLE, "higher reliability" },
+ { EFI_MEMORY_RO, "read-only" },
+ { EFI_MEMORY_SP, "specific purpose" },
+ { EFI_MEMORY_RUNTIME, "needs runtime mapping" }
+};
+
+/* Maximum different attribute values we can track */
+#define ATTR_SEEN_MAX 30
+
+static inline bool is_boot_services(int type)
+{
+ return type == EFI_LOADER_CODE || type == EFI_LOADER_DATA ||
+ type == EFI_BOOT_SERVICES_CODE ||
+ type == EFI_BOOT_SERVICES_DATA;
+}
+
+static int h_cmp_entry(const void *v1, const void *v2)
+{
+ const struct efi_mem_desc *desc1 = v1;
+ const struct efi_mem_desc *desc2 = v2;
+ int64_t diff = desc1->physical_start - desc2->physical_start;
+
+ /*
+ * Manually calculate the difference to avoid sign loss in the 64-bit
+ * to 32-bit conversion
+ */
+ return diff < 0 ? -1 : diff > 0 ? 1 : 0;
+}
+
+/**
+ * efi_build_mem_table() - make a sorted copy of the memory table
+ *
+ * @map: Pointer to EFI memory map table
+ * @size: Size of table in bytes
+ * @skip_bs: True to skip boot-time memory and merge it with conventional
+ * memory. This will significantly reduce the number of table
+ * entries.
+ * Return: pointer to the new table. It should be freed with free() by the
+ * caller.
+ */
+static void *efi_build_mem_table(struct efi_entry_memmap *map, int size,
+ bool skip_bs)
+{
+ struct efi_mem_desc *desc, *end, *base, *dest, *prev;
+ int count;
+ u64 addr;
+
+ base = malloc(size + sizeof(*desc));
+ if (!base) {
+ debug("%s: Cannot allocate %#x bytes\n", __func__, size);
+ return NULL;
+ }
+ end = (struct efi_mem_desc *)((ulong)map + size);
+ count = ((ulong)end - (ulong)map->desc) / map->desc_size;
+ memcpy(base, map->desc, (ulong)end - (ulong)map->desc);
+ qsort(base, count, map->desc_size, h_cmp_entry);
+ prev = NULL;
+ addr = 0;
+ dest = base;
+ end = (struct efi_mem_desc *)((ulong)base + count * map->desc_size);
+ for (desc = base; desc < end; desc = efi_get_next_mem_desc(map, desc)) {
+ bool merge = true;
+ u32 type = desc->type;
+
+ if (type >= EFI_MAX_MEMORY_TYPE) {
+ printf("Memory map contains invalid entry type %u\n",
+ type);
+ continue;
+ }
+
+ if (skip_bs && is_boot_services(desc->type))
+ type = EFI_CONVENTIONAL_MEMORY;
+
+ memcpy(dest, desc, map->desc_size);
+ dest->type = type;
+ if (!skip_bs || !prev)
+ merge = false;
+ else if (desc->physical_start != addr)
+ merge = false;
+ else if (type != EFI_CONVENTIONAL_MEMORY)
+ merge = false;
+ else if (prev->type != EFI_CONVENTIONAL_MEMORY)
+ merge = false;
+
+ if (merge) {
+ prev->num_pages += desc->num_pages;
+ } else {
+ prev = dest;
+ dest = efi_get_next_mem_desc(map, dest);
+ }
+ addr = desc->physical_start + (desc->num_pages <<
+ EFI_PAGE_SHIFT);
+ }
+
+ /* Mark the end */
+ dest->type = EFI_MAX_MEMORY_TYPE;
+
+ return base;
+}
+
+static void efi_print_mem_table(struct efi_entry_memmap *map,
+ struct efi_mem_desc *desc, bool skip_bs)
+{
+ u64 attr_seen[ATTR_SEEN_MAX];
+ int attr_seen_count;
+ int upto, i;
+ u64 addr;
+
+ printf(" # %-14s %10s %10s %10s %s\n", "Type", "Physical",
+ "Virtual", "Size", "Attributes");
+
+ /* Keep track of all the different attributes we have seen */
+ attr_seen_count = 0;
+ addr = 0;
+ for (upto = 0; desc->type != EFI_MAX_MEMORY_TYPE;
+ upto++, desc = efi_get_next_mem_desc(map, desc)) {
+ const char *name;
+ u64 size;
+
+ if (skip_bs && is_boot_services(desc->type))
+ continue;
+ if (desc->physical_start != addr) {
+ printf(" %-14s %010llx %10s %010llx\n", "<gap>",
+ addr, "", desc->physical_start - addr);
+ }
+ size = desc->num_pages << EFI_PAGE_SHIFT;
+
+ name = desc->type < ARRAY_SIZE(type_name) ?
+ type_name[desc->type] : "<invalid>";
+ printf("%2d %x:%-12s %010llx %010llx %010llx ", upto,
+ desc->type, name, desc->physical_start,
+ desc->virtual_start, size);
+ if (desc->attribute & EFI_MEMORY_RUNTIME)
+ putc('r');
+ printf("%llx", desc->attribute & ~EFI_MEMORY_RUNTIME);
+ putc('\n');
+
+ for (i = 0; i < attr_seen_count; i++) {
+ if (attr_seen[i] == desc->attribute)
+ break;
+ }
+ if (i == attr_seen_count && i < ATTR_SEEN_MAX)
+ attr_seen[attr_seen_count++] = desc->attribute;
+ addr = desc->physical_start + size;
+ }
+
+ printf("\nAttributes key:\n");
+ for (i = 0; i < attr_seen_count; i++) {
+ u64 attr = attr_seen[i];
+ bool first;
+ int j;
+
+ printf("%c%llx: ", (attr & EFI_MEMORY_RUNTIME) ? 'r' : ' ',
+ attr & ~EFI_MEMORY_RUNTIME);
+ for (j = 0, first = true; j < ARRAY_SIZE(mem_attr); j++) {
+ if (attr & mem_attr[j].val) {
+ if (first)
+ first = false;
+ else
+ printf(", ");
+ printf("%s", mem_attr[j].name);
+ }
+ }
+ putc('\n');
+ }
+ if (skip_bs)
+ printf("*Some areas are merged (use 'all' to see)\n");
+}
+
+static int do_efi_mem(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct efi_mem_desc *desc;
+ struct efi_entry_memmap *map;
+ int size, ret;
+ bool skip_bs;
+
+ skip_bs = !argc || *argv[0] != 'a';
+ ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
+ switch (ret) {
+ case -ENOENT:
+ printf("No EFI table available\n");
+ goto done;
+ case -EPROTONOSUPPORT:
+ printf("Incorrect EFI table version\n");
+ goto done;
+ }
+ printf("EFI table at %lx, memory map %p, size %x, version %x, descr. size %#x\n",
+ gd->arch.table, map, size, map->version, map->desc_size);
+ if (map->version != EFI_MEM_DESC_VERSION) {
+ printf("Incorrect memory map version\n");
+ ret = -EPROTONOSUPPORT;
+ goto done;
+ }
+
+ desc = efi_build_mem_table(map, size, skip_bs);
+ if (!desc) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ efi_print_mem_table(map, desc, skip_bs);
+ free(desc);
+done:
+ if (ret)
+ printf("Error: %d\n", ret);
+
+ return ret ? CMD_RET_FAILURE : 0;
+}
+
+static struct cmd_tbl efi_commands[] = {
+ U_BOOT_CMD_MKENT(mem, 1, 1, do_efi_mem, "", ""),
+};
+
+static int do_efi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *efi_cmd;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ efi_cmd = find_cmd_tbl(argv[1], efi_commands, ARRAY_SIZE(efi_commands));
+ argc -= 2;
+ argv += 2;
+ if (!efi_cmd || argc > efi_cmd->maxargs)
+ return CMD_RET_USAGE;
+
+ ret = efi_cmd->cmd(efi_cmd, flag, argc, argv);
+
+ return cmd_process_error(efi_cmd, ret);
+}
+
+U_BOOT_CMD(
+ efi, 3, 1, do_efi,
+ "EFI access",
+ "mem [all] Dump memory information [include boot services]"
+);
diff --git a/roms/u-boot/cmd/efidebug.c b/roms/u-boot/cmd/efidebug.c
new file mode 100644
index 000000000..8211a589a
--- /dev/null
+++ b/roms/u-boot/cmd/efidebug.c
@@ -0,0 +1,1787 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * UEFI Shell-like command
+ *
+ * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
+ */
+
+#include <charset.h>
+#include <common.h>
+#include <command.h>
+#include <efi_dt_fixup.h>
+#include <efi_load_initrd.h>
+#include <efi_loader.h>
+#include <efi_rng.h>
+#include <efi_variable.h>
+#include <exports.h>
+#include <hexdump.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <part.h>
+#include <search.h>
+#include <linux/ctype.h>
+#include <linux/err.h>
+
+#define BS systab.boottime
+#define RT systab.runtime
+
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
+/**
+ * do_efi_capsule_update() - process a capsule update
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule update" sub-command.
+ * process a capsule update.
+ *
+ * efidebug capsule update [-v] <capsule address>
+ */
+static int do_efi_capsule_update(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct efi_capsule_header *capsule;
+ int verbose = 0;
+ char *endp;
+ efi_status_t ret;
+
+ if (argc != 2 && argc != 3)
+ return CMD_RET_USAGE;
+
+ if (argc == 3) {
+ if (strcmp(argv[1], "-v"))
+ return CMD_RET_USAGE;
+
+ verbose = 1;
+ argc--;
+ argv++;
+ }
+
+ capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16);
+ if (endp == argv[1]) {
+ printf("Invalid address: %s", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ if (verbose) {
+ printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
+ printf("Capsule flags: 0x%x\n", capsule->flags);
+ printf("Capsule header size: 0x%x\n", capsule->header_size);
+ printf("Capsule image size: 0x%x\n",
+ capsule->capsule_image_size);
+ }
+
+ ret = EFI_CALL(RT->update_capsule(&capsule, 1, 0));
+ if (ret) {
+ printf("Cannot handle a capsule at %p", capsule);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_efi_capsule_on_disk_update(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ efi_status_t ret;
+
+ ret = efi_launch_capsules();
+
+ return ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+
+/**
+ * do_efi_capsule_show() - show capsule information
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule show" sub-command.
+ * show capsule information.
+ *
+ * efidebug capsule show <capsule address>
+ */
+static int do_efi_capsule_show(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct efi_capsule_header *capsule;
+ char *endp;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16);
+ if (endp == argv[1]) {
+ printf("Invalid address: %s", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Capsule guid: %pUl\n", &capsule->capsule_guid);
+ printf("Capsule flags: 0x%x\n", capsule->flags);
+ printf("Capsule header size: 0x%x\n", capsule->header_size);
+ printf("Capsule image size: 0x%x\n",
+ capsule->capsule_image_size);
+
+ return CMD_RET_SUCCESS;
+}
+
+#ifdef CONFIG_EFI_ESRT
+
+#define EFI_ESRT_FW_TYPE_NUM 4
+char *efi_fw_type_str[EFI_ESRT_FW_TYPE_NUM] = {"unknown", "system FW", "device FW",
+ "UEFI driver"};
+
+#define EFI_ESRT_UPDATE_STATUS_NUM 9
+char *efi_update_status_str[EFI_ESRT_UPDATE_STATUS_NUM] = {"success", "unsuccessful",
+ "insufficient resources", "incorrect version", "invalid format",
+ "auth error", "power event (AC)", "power event (batt)",
+ "unsatisfied dependencies"};
+
+#define EFI_FW_TYPE_STR_GET(idx) (\
+EFI_ESRT_FW_TYPE_NUM > (idx) ? efi_fw_type_str[(idx)] : "error"\
+)
+
+#define EFI_FW_STATUS_STR_GET(idx) (\
+EFI_ESRT_UPDATE_STATUS_NUM > (idx) ? efi_update_status_str[(idx)] : "error"\
+)
+
+/**
+ * do_efi_capsule_esrt() - manage UEFI capsules
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule esrt" sub-command.
+ * The prints the current ESRT table.
+ *
+ * efidebug capsule esrt
+ */
+static int do_efi_capsule_esrt(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct efi_system_resource_table *esrt = NULL;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ for (int idx = 0; idx < systab.nr_tables; idx++)
+ if (!guidcmp(&efi_esrt_guid, &systab.tables[idx].guid))
+ esrt = (struct efi_system_resource_table *)systab.tables[idx].table;
+
+ if (!esrt) {
+ log_info("ESRT: table not present\n");
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("========================================\n");
+ printf("ESRT: fw_resource_count=%d\n", esrt->fw_resource_count);
+ printf("ESRT: fw_resource_count_max=%d\n", esrt->fw_resource_count_max);
+ printf("ESRT: fw_resource_version=%lld\n", esrt->fw_resource_version);
+
+ for (int idx = 0; idx < esrt->fw_resource_count; idx++) {
+ printf("[entry %d]==============================\n", idx);
+ printf("ESRT: fw_class=%pUL\n", &esrt->entries[idx].fw_class);
+ printf("ESRT: fw_type=%s\n", EFI_FW_TYPE_STR_GET(esrt->entries[idx].fw_type));
+ printf("ESRT: fw_version=%d\n", esrt->entries[idx].fw_version);
+ printf("ESRT: lowest_supported_fw_version=%d\n",
+ esrt->entries[idx].lowest_supported_fw_version);
+ printf("ESRT: capsule_flags=%d\n",
+ esrt->entries[idx].capsule_flags);
+ printf("ESRT: last_attempt_version=%d\n",
+ esrt->entries[idx].last_attempt_version);
+ printf("ESRT: last_attempt_status=%s\n",
+ EFI_FW_STATUS_STR_GET(esrt->entries[idx].last_attempt_status));
+ }
+ printf("========================================\n");
+
+ return CMD_RET_SUCCESS;
+}
+#endif /* CONFIG_EFI_ESRT */
+/**
+ * do_efi_capsule_res() - show a capsule update result
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule result" sub-command.
+ * show a capsule update result.
+ * If result number is not specified, CapsuleLast will be shown.
+ *
+ * efidebug capsule result [<capsule result number>]
+ */
+static int do_efi_capsule_res(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ int capsule_id;
+ char *endp;
+ u16 var_name16[12];
+ efi_guid_t guid;
+ struct efi_capsule_result_variable_header *result = NULL;
+ efi_uintn_t size;
+ efi_status_t ret;
+
+ if (argc != 1 && argc != 2)
+ return CMD_RET_USAGE;
+
+ guid = efi_guid_capsule_report;
+ if (argc == 1) {
+ size = sizeof(var_name16);
+ ret = efi_get_variable_int(L"CapsuleLast", &guid, NULL,
+ &size, var_name16, NULL);
+
+ if (ret != EFI_SUCCESS) {
+ if (ret == EFI_NOT_FOUND)
+ printf("CapsuleLast doesn't exist\n");
+ else
+ printf("Failed to get CapsuleLast\n");
+
+ return CMD_RET_FAILURE;
+ }
+ printf("CapsuleLast is %ls\n", var_name16);
+ } else {
+ argc--;
+ argv++;
+
+ capsule_id = simple_strtoul(argv[0], &endp, 16);
+ if (capsule_id < 0 || capsule_id > 0xffff)
+ return CMD_RET_USAGE;
+
+ efi_create_indexed_name(var_name16, sizeof(var_name16),
+ "Capsule", capsule_id);
+ }
+
+ size = 0;
+ ret = efi_get_variable_int(var_name16, &guid, NULL, &size, NULL, NULL);
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ result = malloc(size);
+ if (!result)
+ return CMD_RET_FAILURE;
+ ret = efi_get_variable_int(var_name16, &guid, NULL, &size,
+ result, NULL);
+ }
+ if (ret != EFI_SUCCESS) {
+ free(result);
+ printf("Failed to get %ls\n", var_name16);
+
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Result total size: 0x%x\n", result->variable_total_size);
+ printf("Capsule guid: %pUl\n", &result->capsule_guid);
+ printf("Time processed: %04d-%02d-%02d %02d:%02d:%02d\n",
+ result->capsule_processed.year, result->capsule_processed.month,
+ result->capsule_processed.day, result->capsule_processed.hour,
+ result->capsule_processed.minute,
+ result->capsule_processed.second);
+ printf("Capsule status: 0x%lx\n", result->capsule_status);
+
+ free(result);
+
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_efidebug_capsule_sub[] = {
+ U_BOOT_CMD_MKENT(update, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_update,
+ "", ""),
+ U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show,
+ "", ""),
+#ifdef CONFIG_EFI_ESRT
+ U_BOOT_CMD_MKENT(esrt, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_esrt,
+ "", ""),
+#endif
+ U_BOOT_CMD_MKENT(disk-update, 0, 0, do_efi_capsule_on_disk_update,
+ "", ""),
+ U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res,
+ "", ""),
+};
+
+/**
+ * do_efi_capsule() - manage UEFI capsules
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "capsule" sub-command.
+ */
+static int do_efi_capsule(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct cmd_tbl *cp;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ argc--; argv++;
+
+ cp = find_cmd_tbl(argv[0], cmd_efidebug_capsule_sub,
+ ARRAY_SIZE(cmd_efidebug_capsule_sub));
+ if (!cp)
+ return CMD_RET_USAGE;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */
+
+/**
+ * efi_get_device_path_text() - get device path text
+ *
+ * Return the text representation of the device path of a handle.
+ *
+ * @handle: handle of UEFI device
+ * Return:
+ * Pointer to the device path text or NULL.
+ * The caller is responsible for calling FreePool().
+ */
+static u16 *efi_get_device_path_text(efi_handle_t handle)
+{
+ struct efi_handler *handler;
+ efi_status_t ret;
+
+ ret = efi_search_protocol(handle, &efi_guid_device_path, &handler);
+ if (ret == EFI_SUCCESS && handler->protocol_interface) {
+ struct efi_device_path *dp = handler->protocol_interface;
+
+ return efi_dp_str(dp);
+ } else {
+ return NULL;
+ }
+}
+
+#define EFI_HANDLE_WIDTH ((int)sizeof(efi_handle_t) * 2)
+
+static const char spc[] = " ";
+static const char sep[] = "================";
+
+/**
+ * do_efi_show_devices() - show UEFI devices
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "devices" sub-command.
+ * Show all UEFI devices and their information.
+ */
+static int do_efi_show_devices(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ efi_handle_t *handles;
+ efi_uintn_t num, i;
+ u16 *dev_path_text;
+ efi_status_t ret;
+
+ ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
+ &num, &handles));
+ if (ret != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+
+ if (!num)
+ return CMD_RET_SUCCESS;
+
+ printf("Device%.*s Device Path\n", EFI_HANDLE_WIDTH - 6, spc);
+ printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
+ for (i = 0; i < num; i++) {
+ dev_path_text = efi_get_device_path_text(handles[i]);
+ if (dev_path_text) {
+ printf("%p %ls\n", handles[i], dev_path_text);
+ efi_free_pool(dev_path_text);
+ }
+ }
+
+ efi_free_pool(handles);
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * efi_get_driver_handle_info() - get information of UEFI driver
+ *
+ * @handle: Handle of UEFI device
+ * @driver_name: Driver name
+ * @image_path: Pointer to text of device path
+ * Return: 0 on success, -1 on failure
+ *
+ * Currently return no useful information as all UEFI drivers are
+ * built-in..
+ */
+static int efi_get_driver_handle_info(efi_handle_t handle, u16 **driver_name,
+ u16 **image_path)
+{
+ struct efi_handler *handler;
+ struct efi_loaded_image *image;
+ efi_status_t ret;
+
+ /*
+ * driver name
+ * TODO: support EFI_COMPONENT_NAME2_PROTOCOL
+ */
+ *driver_name = NULL;
+
+ /* image name */
+ ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
+ if (ret != EFI_SUCCESS) {
+ *image_path = NULL;
+ return 0;
+ }
+
+ image = handler->protocol_interface;
+ *image_path = efi_dp_str(image->file_path);
+
+ return 0;
+}
+
+/**
+ * do_efi_show_drivers() - show UEFI drivers
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "drivers" sub-command.
+ * Show all UEFI drivers and their information.
+ */
+static int do_efi_show_drivers(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ efi_handle_t *handles;
+ efi_uintn_t num, i;
+ u16 *driver_name, *image_path_text;
+ efi_status_t ret;
+
+ ret = EFI_CALL(efi_locate_handle_buffer(
+ BY_PROTOCOL, &efi_guid_driver_binding_protocol,
+ NULL, &num, &handles));
+ if (ret != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+
+ if (!num)
+ return CMD_RET_SUCCESS;
+
+ printf("Driver%.*s Name Image Path\n",
+ EFI_HANDLE_WIDTH - 6, spc);
+ printf("%.*s ==================== ====================\n",
+ EFI_HANDLE_WIDTH, sep);
+ for (i = 0; i < num; i++) {
+ if (!efi_get_driver_handle_info(handles[i], &driver_name,
+ &image_path_text)) {
+ if (image_path_text)
+ printf("%p %-20ls %ls\n", handles[i],
+ driver_name, image_path_text);
+ else
+ printf("%p %-20ls <built-in>\n",
+ handles[i], driver_name);
+ efi_free_pool(driver_name);
+ efi_free_pool(image_path_text);
+ }
+ }
+
+ efi_free_pool(handles);
+
+ return CMD_RET_SUCCESS;
+}
+
+static const struct {
+ const char *text;
+ const efi_guid_t guid;
+} guid_list[] = {
+ {
+ "Device Path",
+ EFI_DEVICE_PATH_PROTOCOL_GUID,
+ },
+ {
+ "Device Path To Text",
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID,
+ },
+ {
+ "Device Path Utilities",
+ EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID,
+ },
+ {
+ "Unicode Collation 2",
+ EFI_UNICODE_COLLATION_PROTOCOL2_GUID,
+ },
+ {
+ "Driver Binding",
+ EFI_DRIVER_BINDING_PROTOCOL_GUID,
+ },
+ {
+ "Simple Text Input",
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID,
+ },
+ {
+ "Simple Text Input Ex",
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID,
+ },
+ {
+ "Simple Text Output",
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID,
+ },
+ {
+ "Block IO",
+ EFI_BLOCK_IO_PROTOCOL_GUID,
+ },
+ {
+ "Simple File System",
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
+ },
+ {
+ "Loaded Image",
+ EFI_LOADED_IMAGE_PROTOCOL_GUID,
+ },
+ {
+ "Graphics Output",
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID,
+ },
+ {
+ "HII String",
+ EFI_HII_STRING_PROTOCOL_GUID,
+ },
+ {
+ "HII Database",
+ EFI_HII_DATABASE_PROTOCOL_GUID,
+ },
+ {
+ "HII Config Routing",
+ EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID,
+ },
+ {
+ "Load File2",
+ EFI_LOAD_FILE2_PROTOCOL_GUID,
+ },
+ {
+ "Random Number Generator",
+ EFI_RNG_PROTOCOL_GUID,
+ },
+ {
+ "Simple Network",
+ EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
+ },
+ {
+ "PXE Base Code",
+ EFI_PXE_BASE_CODE_PROTOCOL_GUID,
+ },
+ {
+ "Device-Tree Fixup",
+ EFI_DT_FIXUP_PROTOCOL_GUID,
+ },
+ {
+ "System Partition",
+ PARTITION_SYSTEM_GUID
+ },
+ {
+ "Firmware Management",
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID
+ },
+ /* Configuration table GUIDs */
+ {
+ "ACPI table",
+ EFI_ACPI_TABLE_GUID,
+ },
+ {
+ "EFI System Resource Table",
+ EFI_SYSTEM_RESOURCE_TABLE_GUID,
+ },
+ {
+ "device tree",
+ EFI_FDT_GUID,
+ },
+ {
+ "SMBIOS table",
+ SMBIOS_TABLE_GUID,
+ },
+ {
+ "Runtime properties",
+ EFI_RT_PROPERTIES_TABLE_GUID,
+ },
+ {
+ "TCG2 Final Events Table",
+ EFI_TCG2_FINAL_EVENTS_TABLE_GUID,
+ },
+};
+
+/**
+ * get_guid_text - get string of GUID
+ *
+ * Return description of GUID.
+ *
+ * @guid: GUID
+ * Return: description of GUID or NULL
+ */
+static const char *get_guid_text(const void *guid)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(guid_list); i++) {
+ /*
+ * As guidcmp uses memcmp() we can safely accept unaligned
+ * GUIDs.
+ */
+ if (!guidcmp(&guid_list[i].guid, guid))
+ return guid_list[i].text;
+ }
+
+ return NULL;
+}
+
+/**
+ * do_efi_show_handles() - show UEFI handles
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "dh" sub-command.
+ * Show all UEFI handles and their information, currently all protocols
+ * added to handle.
+ */
+static int do_efi_show_handles(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ efi_handle_t *handles;
+ efi_guid_t **guid;
+ efi_uintn_t num, count, i, j;
+ const char *guid_text;
+ efi_status_t ret;
+
+ ret = EFI_CALL(efi_locate_handle_buffer(ALL_HANDLES, NULL, NULL,
+ &num, &handles));
+ if (ret != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+
+ if (!num)
+ return CMD_RET_SUCCESS;
+
+ printf("Handle%.*s Protocols\n", EFI_HANDLE_WIDTH - 6, spc);
+ printf("%.*s ====================\n", EFI_HANDLE_WIDTH, sep);
+ for (i = 0; i < num; i++) {
+ printf("%p", handles[i]);
+ ret = EFI_CALL(BS->protocols_per_handle(handles[i], &guid,
+ &count));
+ if (ret || !count) {
+ putc('\n');
+ continue;
+ }
+
+ for (j = 0; j < count; j++) {
+ if (j)
+ printf(", ");
+ else
+ putc(' ');
+
+ guid_text = get_guid_text(guid[j]);
+ if (guid_text)
+ puts(guid_text);
+ else
+ printf("%pUl", guid[j]);
+ }
+ putc('\n');
+ }
+
+ efi_free_pool(handles);
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_efi_show_images() - show UEFI images
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "images" sub-command.
+ * Show all UEFI loaded images and their information.
+ */
+static int do_efi_show_images(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ efi_print_image_infos(NULL);
+
+ return CMD_RET_SUCCESS;
+}
+
+static const char * const efi_mem_type_string[] = {
+ [EFI_RESERVED_MEMORY_TYPE] = "RESERVED",
+ [EFI_LOADER_CODE] = "LOADER CODE",
+ [EFI_LOADER_DATA] = "LOADER DATA",
+ [EFI_BOOT_SERVICES_CODE] = "BOOT CODE",
+ [EFI_BOOT_SERVICES_DATA] = "BOOT DATA",
+ [EFI_RUNTIME_SERVICES_CODE] = "RUNTIME CODE",
+ [EFI_RUNTIME_SERVICES_DATA] = "RUNTIME DATA",
+ [EFI_CONVENTIONAL_MEMORY] = "CONVENTIONAL",
+ [EFI_UNUSABLE_MEMORY] = "UNUSABLE MEM",
+ [EFI_ACPI_RECLAIM_MEMORY] = "ACPI RECLAIM MEM",
+ [EFI_ACPI_MEMORY_NVS] = "ACPI NVS",
+ [EFI_MMAP_IO] = "IO",
+ [EFI_MMAP_IO_PORT] = "IO PORT",
+ [EFI_PAL_CODE] = "PAL",
+ [EFI_PERSISTENT_MEMORY_TYPE] = "PERSISTENT",
+};
+
+static const struct efi_mem_attrs {
+ const u64 bit;
+ const char *text;
+} efi_mem_attrs[] = {
+ {EFI_MEMORY_UC, "UC"},
+ {EFI_MEMORY_UC, "UC"},
+ {EFI_MEMORY_WC, "WC"},
+ {EFI_MEMORY_WT, "WT"},
+ {EFI_MEMORY_WB, "WB"},
+ {EFI_MEMORY_UCE, "UCE"},
+ {EFI_MEMORY_WP, "WP"},
+ {EFI_MEMORY_RP, "RP"},
+ {EFI_MEMORY_XP, "WP"},
+ {EFI_MEMORY_NV, "NV"},
+ {EFI_MEMORY_MORE_RELIABLE, "REL"},
+ {EFI_MEMORY_RO, "RO"},
+ {EFI_MEMORY_SP, "SP"},
+ {EFI_MEMORY_RUNTIME, "RT"},
+};
+
+/**
+ * print_memory_attributes() - print memory map attributes
+ *
+ * @attributes: Attribute value
+ *
+ * Print memory map attributes
+ */
+static void print_memory_attributes(u64 attributes)
+{
+ int sep, i;
+
+ for (sep = 0, i = 0; i < ARRAY_SIZE(efi_mem_attrs); i++)
+ if (attributes & efi_mem_attrs[i].bit) {
+ if (sep) {
+ putc('|');
+ } else {
+ putc(' ');
+ sep = 1;
+ }
+ puts(efi_mem_attrs[i].text);
+ }
+}
+
+#define EFI_PHYS_ADDR_WIDTH (int)(sizeof(efi_physical_addr_t) * 2)
+
+/**
+ * do_efi_show_memmap() - show UEFI memory map
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "memmap" sub-command.
+ * Show UEFI memory map.
+ */
+static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct efi_mem_desc *memmap = NULL, *map;
+ efi_uintn_t map_size = 0;
+ const char *type;
+ int i;
+ efi_status_t ret;
+
+ ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ map_size += sizeof(struct efi_mem_desc); /* for my own */
+ ret = efi_allocate_pool(EFI_LOADER_DATA, map_size,
+ (void *)&memmap);
+ if (ret != EFI_SUCCESS)
+ return CMD_RET_FAILURE;
+ ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
+ }
+ if (ret != EFI_SUCCESS) {
+ efi_free_pool(memmap);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Type Start%.*s End%.*s Attributes\n",
+ EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);
+ printf("================ %.*s %.*s ==========\n",
+ EFI_PHYS_ADDR_WIDTH, sep, EFI_PHYS_ADDR_WIDTH, sep);
+ /*
+ * Coverity check: dereferencing null pointer "map."
+ * This is a false positive as memmap will always be
+ * populated by allocate_pool() above.
+ */
+ for (i = 0, map = memmap; i < map_size / sizeof(*map); map++, i++) {
+ if (map->type < ARRAY_SIZE(efi_mem_type_string))
+ type = efi_mem_type_string[map->type];
+ else
+ type = "(unknown)";
+
+ printf("%-16s %.*llx-%.*llx", type,
+ EFI_PHYS_ADDR_WIDTH,
+ (u64)map_to_sysmem((void *)(uintptr_t)
+ map->physical_start),
+ EFI_PHYS_ADDR_WIDTH,
+ (u64)map_to_sysmem((void *)(uintptr_t)
+ (map->physical_start +
+ map->num_pages * EFI_PAGE_SIZE)));
+
+ print_memory_attributes(map->attribute);
+ putc('\n');
+ }
+
+ efi_free_pool(memmap);
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_efi_show_tables() - show UEFI configuration tables
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "tables" sub-command.
+ * Show UEFI configuration tables.
+ */
+static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ efi_uintn_t i;
+ const char *guid_str;
+
+ for (i = 0; i < systab.nr_tables; ++i) {
+ guid_str = get_guid_text(&systab.tables[i].guid);
+ if (!guid_str)
+ guid_str = "";
+ printf("%pUl %s\n", &systab.tables[i].guid, guid_str);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * create_initrd_dp() - Create a special device for our Boot### option
+ *
+ * @dev: Device
+ * @part: Disk partition
+ * @file: Filename
+ * Return: Pointer to the device path or ERR_PTR
+ *
+ */
+static
+struct efi_device_path *create_initrd_dp(const char *dev, const char *part,
+ const char *file)
+
+{
+ struct efi_device_path *tmp_dp = NULL, *tmp_fp = NULL;
+ struct efi_device_path *initrd_dp = NULL;
+ efi_status_t ret;
+ const struct efi_initrd_dp id_dp = {
+ .vendor = {
+ {
+ DEVICE_PATH_TYPE_MEDIA_DEVICE,
+ DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
+ sizeof(id_dp.vendor),
+ },
+ EFI_INITRD_MEDIA_GUID,
+ },
+ .end = {
+ DEVICE_PATH_TYPE_END,
+ DEVICE_PATH_SUB_TYPE_END,
+ sizeof(id_dp.end),
+ }
+ };
+
+ ret = efi_dp_from_name(dev, part, file, &tmp_dp, &tmp_fp);
+ if (ret != EFI_SUCCESS) {
+ printf("Cannot create device path for \"%s %s\"\n", part, file);
+ goto out;
+ }
+
+ initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp,
+ tmp_fp);
+
+out:
+ efi_free_pool(tmp_dp);
+ efi_free_pool(tmp_fp);
+ return initrd_dp;
+}
+
+/**
+ * do_efi_boot_add() - set UEFI load option
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "boot add" sub-command. Create or change UEFI load option.
+ *
+ * efidebug boot add -b <id> <label> <interface> <devnum>[:<part>] <file>
+ * -i <file> <interface2> <devnum2>[:<part>] <initrd>
+ * -s '<options>'
+ */
+static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int id;
+ char *endp;
+ u16 var_name16[9];
+ efi_guid_t guid;
+ size_t label_len, label_len16;
+ u16 *label;
+ struct efi_device_path *device_path = NULL, *file_path = NULL;
+ struct efi_device_path *final_fp = NULL;
+ struct efi_device_path *initrd_dp = NULL;
+ struct efi_load_option lo;
+ void *data = NULL;
+ efi_uintn_t size;
+ efi_uintn_t fp_size = 0;
+ efi_status_t ret;
+ int r = CMD_RET_SUCCESS;
+
+ guid = efi_global_variable_guid;
+
+ /* attributes */
+ lo.attributes = LOAD_OPTION_ACTIVE; /* always ACTIVE */
+ lo.optional_data = NULL;
+ lo.label = NULL;
+
+ argc--;
+ argv++; /* 'add' */
+ for (; argc > 0; argc--, argv++) {
+ if (!strcmp(argv[0], "-b")) {
+ if (argc < 5 || lo.label) {
+ r = CMD_RET_USAGE;
+ goto out;
+ }
+ id = (int)simple_strtoul(argv[1], &endp, 16);
+ if (*endp != '\0' || id > 0xffff)
+ return CMD_RET_USAGE;
+
+ efi_create_indexed_name(var_name16, sizeof(var_name16),
+ "Boot", id);
+
+ /* label */
+ label_len = strlen(argv[2]);
+ label_len16 = utf8_utf16_strnlen(argv[2], label_len);
+ label = malloc((label_len16 + 1) * sizeof(u16));
+ if (!label)
+ return CMD_RET_FAILURE;
+ lo.label = label; /* label will be changed below */
+ utf8_utf16_strncpy(&label, argv[2], label_len);
+
+ /* file path */
+ ret = efi_dp_from_name(argv[3], argv[4], argv[5],
+ &device_path, &file_path);
+ if (ret != EFI_SUCCESS) {
+ printf("Cannot create device path for \"%s %s\"\n",
+ argv[3], argv[4]);
+ r = CMD_RET_FAILURE;
+ goto out;
+ }
+ fp_size += efi_dp_size(file_path) +
+ sizeof(struct efi_device_path);
+ argc -= 5;
+ argv += 5;
+ } else if (!strcmp(argv[0], "-i")) {
+ if (argc < 3 || initrd_dp) {
+ r = CMD_RET_USAGE;
+ goto out;
+ }
+
+ initrd_dp = create_initrd_dp(argv[1], argv[2], argv[3]);
+ if (!initrd_dp) {
+ printf("Cannot add an initrd\n");
+ r = CMD_RET_FAILURE;
+ goto out;
+ }
+ argc -= 3;
+ argv += 3;
+ fp_size += efi_dp_size(initrd_dp) +
+ sizeof(struct efi_device_path);
+ } else if (!strcmp(argv[0], "-s")) {
+ if (argc < 1 || lo.optional_data) {
+ r = CMD_RET_USAGE;
+ goto out;
+ }
+ lo.optional_data = (const u8 *)argv[1];
+ argc -= 1;
+ argv += 1;
+ } else {
+ r = CMD_RET_USAGE;
+ goto out;
+ }
+ }
+
+ if (!file_path) {
+ printf("Missing binary\n");
+ r = CMD_RET_USAGE;
+ goto out;
+ }
+
+ final_fp = efi_dp_concat(file_path, initrd_dp);
+ if (!final_fp) {
+ printf("Cannot create final device path\n");
+ r = CMD_RET_FAILURE;
+ goto out;
+ }
+
+ lo.file_path = final_fp;
+ lo.file_path_length = fp_size;
+
+ size = efi_serialize_load_option(&lo, (u8 **)&data);
+ if (!size) {
+ r = CMD_RET_FAILURE;
+ goto out;
+ }
+
+ ret = efi_set_variable_int(var_name16, &guid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ size, data, false);
+ if (ret != EFI_SUCCESS) {
+ printf("Cannot set %ls\n", var_name16);
+ r = CMD_RET_FAILURE;
+ }
+
+out:
+ free(data);
+ efi_free_pool(final_fp);
+ efi_free_pool(initrd_dp);
+ efi_free_pool(device_path);
+ efi_free_pool(file_path);
+ free(lo.label);
+
+ return r;
+}
+
+/**
+ * do_efi_boot_rm() - delete UEFI load options
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "boot rm" sub-command.
+ * Delete UEFI load options.
+ *
+ * efidebug boot rm <id> ...
+ */
+static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ efi_guid_t guid;
+ int id, i;
+ char *endp;
+ u16 var_name16[9];
+ efi_status_t ret;
+
+ if (argc == 1)
+ return CMD_RET_USAGE;
+
+ guid = efi_global_variable_guid;
+ for (i = 1; i < argc; i++, argv++) {
+ id = (int)simple_strtoul(argv[1], &endp, 16);
+ if (*endp != '\0' || id > 0xffff)
+ return CMD_RET_FAILURE;
+
+ efi_create_indexed_name(var_name16, sizeof(var_name16),
+ "Boot", id);
+ ret = efi_set_variable_int(var_name16, &guid, 0, 0, NULL,
+ false);
+ if (ret) {
+ printf("Cannot remove %ls\n", var_name16);
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * show_efi_boot_opt_data() - dump UEFI load option
+ *
+ * @varname16: variable name
+ * @data: value of UEFI load option variable
+ * @size: size of the boot option
+ *
+ * Decode the value of UEFI load option variable and print information.
+ */
+static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size)
+{
+ struct efi_device_path *initrd_path = NULL;
+ struct efi_load_option lo;
+ u16 *dp_str;
+ efi_status_t ret;
+ efi_uintn_t initrd_dp_size;
+ const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID;
+
+ ret = efi_deserialize_load_option(&lo, data, size);
+ if (ret != EFI_SUCCESS) {
+ printf("%ls: invalid load option\n", varname16);
+ return;
+ }
+
+ printf("%ls:\nattributes: %c%c%c (0x%08x)\n",
+ varname16,
+ /* ACTIVE */
+ lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
+ /* FORCE RECONNECT */
+ lo.attributes & LOAD_OPTION_FORCE_RECONNECT ? 'R' : '-',
+ /* HIDDEN */
+ lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
+ lo.attributes);
+ printf(" label: %ls\n", lo.label);
+
+ dp_str = efi_dp_str(lo.file_path);
+ printf(" file_path: %ls\n", dp_str);
+ efi_free_pool(dp_str);
+
+ initrd_path = efi_dp_from_lo(&lo, &initrd_dp_size, lf2_initrd_guid);
+ if (initrd_path) {
+ dp_str = efi_dp_str(initrd_path);
+ printf(" initrd_path: %ls\n", dp_str);
+ efi_free_pool(dp_str);
+ efi_free_pool(initrd_path);
+ }
+
+ printf(" data:\n");
+ print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
+ lo.optional_data, *size, true);
+}
+
+/**
+ * show_efi_boot_opt() - dump UEFI load option
+ *
+ * @varname16: variable name
+ *
+ * Dump information defined by UEFI load option.
+ */
+static void show_efi_boot_opt(u16 *varname16)
+{
+ void *data;
+ efi_uintn_t size;
+ efi_status_t ret;
+
+ size = 0;
+ ret = EFI_CALL(efi_get_variable(varname16, &efi_global_variable_guid,
+ NULL, &size, NULL));
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ data = malloc(size);
+ if (!data) {
+ printf("ERROR: Out of memory\n");
+ return;
+ }
+ ret = EFI_CALL(efi_get_variable(varname16,
+ &efi_global_variable_guid,
+ NULL, &size, data));
+ if (ret == EFI_SUCCESS)
+ show_efi_boot_opt_data(varname16, data, &size);
+ free(data);
+ }
+}
+
+static int u16_tohex(u16 c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+
+ /* not hexadecimal */
+ return -1;
+}
+
+/**
+ * show_efi_boot_dump() - dump all UEFI load options
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "boot dump" sub-command.
+ * Dump information of all UEFI load options defined.
+ *
+ * efidebug boot dump
+ */
+static int do_efi_boot_dump(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ u16 *var_name16, *p;
+ efi_uintn_t buf_size, size;
+ efi_guid_t guid;
+ int id, i, digit;
+ efi_status_t ret;
+
+ if (argc > 1)
+ return CMD_RET_USAGE;
+
+ buf_size = 128;
+ var_name16 = malloc(buf_size);
+ if (!var_name16)
+ return CMD_RET_FAILURE;
+
+ var_name16[0] = 0;
+ for (;;) {
+ size = buf_size;
+ ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
+ &guid));
+ if (ret == EFI_NOT_FOUND)
+ break;
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ buf_size = size;
+ p = realloc(var_name16, buf_size);
+ if (!p) {
+ free(var_name16);
+ return CMD_RET_FAILURE;
+ }
+ var_name16 = p;
+ ret = EFI_CALL(efi_get_next_variable_name(&size,
+ var_name16,
+ &guid));
+ }
+ if (ret != EFI_SUCCESS) {
+ free(var_name16);
+ return CMD_RET_FAILURE;
+ }
+
+ if (memcmp(var_name16, L"Boot", 8))
+ continue;
+
+ for (id = 0, i = 0; i < 4; i++) {
+ digit = u16_tohex(var_name16[4 + i]);
+ if (digit < 0)
+ break;
+ id = (id << 4) + digit;
+ }
+ if (i == 4 && !var_name16[8])
+ show_efi_boot_opt(var_name16);
+ }
+
+ free(var_name16);
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * show_efi_boot_order() - show order of UEFI load options
+ *
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Show order of UEFI load options defined by BootOrder variable.
+ */
+static int show_efi_boot_order(void)
+{
+ u16 *bootorder;
+ efi_uintn_t size;
+ int num, i;
+ u16 var_name16[9];
+ void *data;
+ struct efi_load_option lo;
+ efi_status_t ret;
+
+ size = 0;
+ ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
+ NULL, &size, NULL));
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ if (ret == EFI_NOT_FOUND) {
+ printf("BootOrder not defined\n");
+ return CMD_RET_SUCCESS;
+ } else {
+ return CMD_RET_FAILURE;
+ }
+ }
+ bootorder = malloc(size);
+ if (!bootorder) {
+ printf("ERROR: Out of memory\n");
+ return CMD_RET_FAILURE;
+ }
+ ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid,
+ NULL, &size, bootorder));
+ if (ret != EFI_SUCCESS) {
+ ret = CMD_RET_FAILURE;
+ goto out;
+ }
+
+ num = size / sizeof(u16);
+ for (i = 0; i < num; i++) {
+ efi_create_indexed_name(var_name16, sizeof(var_name16),
+ "Boot", bootorder[i]);
+
+ size = 0;
+ ret = EFI_CALL(efi_get_variable(var_name16,
+ &efi_global_variable_guid, NULL,
+ &size, NULL));
+ if (ret != EFI_BUFFER_TOO_SMALL) {
+ printf("%2d: %ls: (not defined)\n", i + 1, var_name16);
+ continue;
+ }
+
+ data = malloc(size);
+ if (!data) {
+ ret = CMD_RET_FAILURE;
+ goto out;
+ }
+ ret = EFI_CALL(efi_get_variable(var_name16,
+ &efi_global_variable_guid, NULL,
+ &size, data));
+ if (ret != EFI_SUCCESS) {
+ free(data);
+ ret = CMD_RET_FAILURE;
+ goto out;
+ }
+
+ ret = efi_deserialize_load_option(&lo, data, &size);
+ if (ret != EFI_SUCCESS) {
+ printf("%ls: invalid load option\n", var_name16);
+ ret = CMD_RET_FAILURE;
+ goto out;
+ }
+
+ printf("%2d: %ls: %ls\n", i + 1, var_name16, lo.label);
+
+ free(data);
+ }
+out:
+ free(bootorder);
+
+ return ret;
+}
+
+/**
+ * do_efi_boot_next() - manage UEFI BootNext variable
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "boot next" sub-command.
+ * Set BootNext variable.
+ *
+ * efidebug boot next <id>
+ */
+static int do_efi_boot_next(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ u16 bootnext;
+ efi_uintn_t size;
+ char *endp;
+ efi_guid_t guid;
+ efi_status_t ret;
+ int r = CMD_RET_SUCCESS;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ bootnext = (u16)simple_strtoul(argv[1], &endp, 16);
+ if (*endp) {
+ printf("invalid value: %s\n", argv[1]);
+ r = CMD_RET_FAILURE;
+ goto out;
+ }
+
+ guid = efi_global_variable_guid;
+ size = sizeof(u16);
+ ret = efi_set_variable_int(L"BootNext", &guid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ size, &bootnext, false);
+ if (ret != EFI_SUCCESS) {
+ printf("Cannot set BootNext\n");
+ r = CMD_RET_FAILURE;
+ }
+out:
+ return r;
+}
+
+/**
+ * do_efi_boot_order() - manage UEFI BootOrder variable
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "boot order" sub-command.
+ * Show order of UEFI load options, or change it in BootOrder variable.
+ *
+ * efidebug boot order [<id> ...]
+ */
+static int do_efi_boot_order(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ u16 *bootorder = NULL;
+ efi_uintn_t size;
+ int id, i;
+ char *endp;
+ efi_guid_t guid;
+ efi_status_t ret;
+ int r = CMD_RET_SUCCESS;
+
+ if (argc == 1)
+ return show_efi_boot_order();
+
+ argc--;
+ argv++;
+
+ size = argc * sizeof(u16);
+ bootorder = malloc(size);
+ if (!bootorder)
+ return CMD_RET_FAILURE;
+
+ for (i = 0; i < argc; i++) {
+ id = (int)simple_strtoul(argv[i], &endp, 16);
+ if (*endp != '\0' || id > 0xffff) {
+ printf("invalid value: %s\n", argv[i]);
+ r = CMD_RET_FAILURE;
+ goto out;
+ }
+
+ bootorder[i] = (u16)id;
+ }
+
+ guid = efi_global_variable_guid;
+ ret = efi_set_variable_int(L"BootOrder", &guid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ size, bootorder, true);
+ if (ret != EFI_SUCCESS) {
+ printf("Cannot set BootOrder\n");
+ r = CMD_RET_FAILURE;
+ }
+out:
+ free(bootorder);
+
+ return r;
+}
+
+static struct cmd_tbl cmd_efidebug_boot_sub[] = {
+ U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""),
+ U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""),
+ U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_efi_boot_dump, "", ""),
+ U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""),
+ U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order,
+ "", ""),
+};
+
+/**
+ * do_efi_boot_opt() - manage UEFI load options
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "boot" sub-command.
+ */
+static int do_efi_boot_opt(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ argc--; argv++;
+
+ cp = find_cmd_tbl(argv[0], cmd_efidebug_boot_sub,
+ ARRAY_SIZE(cmd_efidebug_boot_sub));
+ if (!cp)
+ return CMD_RET_USAGE;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+/**
+ * do_efi_test_bootmgr() - run simple bootmgr for test
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "test bootmgr" sub-command.
+ * Run simple bootmgr for test.
+ *
+ * efidebug test bootmgr
+ */
+static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ efi_handle_t image;
+ efi_uintn_t exit_data_size = 0;
+ u16 *exit_data = NULL;
+ efi_status_t ret;
+ void *load_options = NULL;
+
+ ret = efi_bootmgr_load(&image, &load_options);
+ printf("efi_bootmgr_load() returned: %ld\n", ret & ~EFI_ERROR_MASK);
+
+ /* We call efi_start_image() even if error for test purpose. */
+ ret = EFI_CALL(efi_start_image(image, &exit_data_size, &exit_data));
+ printf("efi_start_image() returned: %ld\n", ret & ~EFI_ERROR_MASK);
+ if (ret && exit_data)
+ efi_free_pool(exit_data);
+
+ efi_restore_gd();
+
+ free(load_options);
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_efidebug_test_sub[] = {
+#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
+ U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr,
+ "", ""),
+#endif
+};
+
+/**
+ * do_efi_test() - manage UEFI load options
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug "test" sub-command.
+ */
+static int do_efi_test(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ struct cmd_tbl *cp;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ argc--; argv++;
+
+ cp = find_cmd_tbl(argv[0], cmd_efidebug_test_sub,
+ ARRAY_SIZE(cmd_efidebug_test_sub));
+ if (!cp)
+ return CMD_RET_USAGE;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+/**
+ * do_efi_query_info() - QueryVariableInfo EFI service
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_FAILURE on failure
+ *
+ * Implement efidebug "test" sub-command.
+ */
+
+static int do_efi_query_info(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ efi_status_t ret;
+ u32 attr = 0;
+ u64 max_variable_storage_size;
+ u64 remain_variable_storage_size;
+ u64 max_variable_size;
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-bs"))
+ attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ else if (!strcmp(argv[i], "-rt"))
+ attr |= EFI_VARIABLE_RUNTIME_ACCESS;
+ else if (!strcmp(argv[i], "-nv"))
+ attr |= EFI_VARIABLE_NON_VOLATILE;
+ else if (!strcmp(argv[i], "-at"))
+ attr |=
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+ }
+
+ ret = EFI_CALL(efi_query_variable_info(attr,
+ &max_variable_storage_size,
+ &remain_variable_storage_size,
+ &max_variable_size));
+ if (ret != EFI_SUCCESS) {
+ printf("Error: Cannot query UEFI variables, r = %lu\n",
+ ret & ~EFI_ERROR_MASK);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Max storage size %llu\n", max_variable_storage_size);
+ printf("Remaining storage size %llu\n", remain_variable_storage_size);
+ printf("Max variable size %llu\n", max_variable_size);
+
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_efidebug_sub[] = {
+ U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""),
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
+ U_BOOT_CMD_MKENT(capsule, CONFIG_SYS_MAXARGS, 1, do_efi_capsule,
+ "", ""),
+#endif
+ U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices,
+ "", ""),
+ U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers,
+ "", ""),
+ U_BOOT_CMD_MKENT(dh, CONFIG_SYS_MAXARGS, 1, do_efi_show_handles,
+ "", ""),
+ U_BOOT_CMD_MKENT(images, CONFIG_SYS_MAXARGS, 1, do_efi_show_images,
+ "", ""),
+ U_BOOT_CMD_MKENT(memmap, CONFIG_SYS_MAXARGS, 1, do_efi_show_memmap,
+ "", ""),
+ U_BOOT_CMD_MKENT(tables, CONFIG_SYS_MAXARGS, 1, do_efi_show_tables,
+ "", ""),
+ U_BOOT_CMD_MKENT(test, CONFIG_SYS_MAXARGS, 1, do_efi_test,
+ "", ""),
+ U_BOOT_CMD_MKENT(query, CONFIG_SYS_MAXARGS, 1, do_efi_query_info,
+ "", ""),
+};
+
+/**
+ * do_efidebug() - display and configure UEFI environment
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success,
+ * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure
+ *
+ * Implement efidebug command which allows us to display and
+ * configure UEFI environment.
+ */
+static int do_efidebug(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct cmd_tbl *cp;
+ efi_status_t r;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ argc--; argv++;
+
+ /* Initialize UEFI drivers */
+ r = efi_init_obj_list();
+ if (r != EFI_SUCCESS) {
+ printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
+ r & ~EFI_ERROR_MASK);
+ return CMD_RET_FAILURE;
+ }
+
+ cp = find_cmd_tbl(argv[0], cmd_efidebug_sub,
+ ARRAY_SIZE(cmd_efidebug_sub));
+ if (!cp)
+ return CMD_RET_USAGE;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char efidebug_help_text[] =
+ " - UEFI Shell-like interface to configure UEFI environment\n"
+ "\n"
+ "efidebug boot add "
+ "-b <bootid> <label> <interface> <devnum>[:<part>] <file path> "
+ "-i <interface> <devnum>[:<part>] <initrd file path> "
+ "-s '<optional data>'\n"
+ " - set UEFI BootXXXX variable\n"
+ " <load options> will be passed to UEFI application\n"
+ "efidebug boot rm <bootid#1> [<bootid#2> [<bootid#3> [...]]]\n"
+ " - delete UEFI BootXXXX variables\n"
+ "efidebug boot dump\n"
+ " - dump all UEFI BootXXXX variables\n"
+ "efidebug boot next <bootid>\n"
+ " - set UEFI BootNext variable\n"
+ "efidebug boot order [<bootid#1> [<bootid#2> [<bootid#3> [...]]]]\n"
+ " - set/show UEFI boot order\n"
+ "\n"
+#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT
+ "efidebug capsule update [-v] <capsule address>\n"
+ " - process a capsule\n"
+ "efidebug capsule disk-update\n"
+ " - update a capsule from disk\n"
+ "efidebug capsule show <capsule address>\n"
+ " - show capsule information\n"
+ "efidebug capsule result [<capsule result var>]\n"
+ " - show a capsule update result\n"
+#ifdef CONFIG_EFI_ESRT
+ "efidebug capsule esrt\n"
+ " - print the ESRT\n"
+#endif
+ "\n"
+#endif
+ "efidebug devices\n"
+ " - show UEFI devices\n"
+ "efidebug drivers\n"
+ " - show UEFI drivers\n"
+ "efidebug dh\n"
+ " - show UEFI handles\n"
+ "efidebug images\n"
+ " - show loaded images\n"
+ "efidebug memmap\n"
+ " - show UEFI memory map\n"
+ "efidebug tables\n"
+ " - show UEFI configuration tables\n"
+#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR
+ "efidebug test bootmgr\n"
+ " - run simple bootmgr for test\n"
+#endif
+ "efidebug query [-nv][-bs][-rt][-at]\n"
+ " - show size of UEFI variables store\n";
+#endif
+
+U_BOOT_CMD(
+ efidebug, CONFIG_SYS_MAXARGS, 0, do_efidebug,
+ "Configure UEFI environment",
+ efidebug_help_text
+);
diff --git a/roms/u-boot/cmd/elf.c b/roms/u-boot/cmd/elf.c
new file mode 100644
index 000000000..d44b95d90
--- /dev/null
+++ b/roms/u-boot/cmd/elf.c
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <elf.h>
+#include <env.h>
+#include <image.h>
+#include <log.h>
+#include <net.h>
+#include <vxworks.h>
+#ifdef CONFIG_X86
+#include <vbe.h>
+#include <asm/cache.h>
+#include <asm/e820.h>
+#include <linux/linkage.h>
+#endif
+
+/* Allow ports to override the default behavior */
+static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
+ int argc, char *const argv[])
+{
+ unsigned long ret;
+
+ /*
+ * pass address parameter as argv[0] (aka command name),
+ * and all remaining args
+ */
+ ret = entry(argc, argv);
+
+ return ret;
+}
+
+/* Interpreter command to boot an arbitrary ELF image from memory */
+int do_bootelf(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned long addr; /* Address of the ELF image */
+ unsigned long rc; /* Return value from user code */
+ char *sload = NULL;
+ const char *ep = env_get("autostart");
+ int rcode = 0;
+
+ /* Consume 'bootelf' */
+ argc--; argv++;
+
+ /* Check for flag. */
+ if (argc >= 1 && (argv[0][0] == '-' && \
+ (argv[0][1] == 'p' || argv[0][1] == 's'))) {
+ sload = argv[0];
+ /* Consume flag. */
+ argc--; argv++;
+ }
+ /* Check for address. */
+ if (argc >= 1 && strict_strtoul(argv[0], 16, &addr) != -EINVAL) {
+ /* Consume address */
+ argc--; argv++;
+ } else
+ addr = image_load_addr;
+
+ if (!valid_elf_image(addr))
+ return 1;
+
+ if (sload && sload[1] == 'p')
+ addr = load_elf_image_phdr(addr);
+ else
+ addr = load_elf_image_shdr(addr);
+
+ if (ep && !strcmp(ep, "no"))
+ return rcode;
+
+ printf("## Starting application at 0x%08lx ...\n", addr);
+
+ /*
+ * pass address parameter as argv[0] (aka command name),
+ * and all remaining args
+ */
+ rc = do_bootelf_exec((void *)addr, argc, argv);
+ if (rc != 0)
+ rcode = 1;
+
+ printf("## Application terminated, rc = 0x%lx\n", rc);
+
+ return rcode;
+}
+
+/*
+ * Interpreter command to boot VxWorks from a memory image. The image can
+ * be either an ELF image or a raw binary. Will attempt to setup the
+ * bootline and other parameters correctly.
+ */
+int do_bootvx(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned long addr; /* Address of image */
+ unsigned long bootaddr = 0; /* Address to put the bootline */
+ char *bootline; /* Text of the bootline */
+ char *tmp; /* Temporary char pointer */
+ char build_buf[128]; /* Buffer for building the bootline */
+ int ptr = 0;
+#ifdef CONFIG_X86
+ ulong base;
+ struct e820_info *info;
+ struct e820_entry *data;
+ struct efi_gop_info *gop;
+ struct vesa_mode_info *vesa = &mode_info.vesa;
+#endif
+
+ /*
+ * Check the loadaddr variable.
+ * If we don't know where the image is then we're done.
+ */
+ if (argc < 2)
+ addr = image_load_addr;
+ else
+ addr = simple_strtoul(argv[1], NULL, 16);
+
+#if defined(CONFIG_CMD_NET)
+ /*
+ * Check to see if we need to tftp the image ourselves
+ * before starting
+ */
+ if ((argc == 2) && (strcmp(argv[1], "tftp") == 0)) {
+ if (net_loop(TFTPGET) <= 0)
+ return 1;
+ printf("Automatic boot of VxWorks image at address 0x%08lx ...\n",
+ addr);
+ }
+#endif
+
+ /*
+ * This should equate to
+ * NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
+ * from the VxWorks BSP header files.
+ * This will vary from board to board
+ */
+#if defined(CONFIG_SYS_VXWORKS_MAC_PTR)
+ tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR;
+ eth_env_get_enetaddr("ethaddr", (uchar *)build_buf);
+ memcpy(tmp, build_buf, 6);
+#else
+ puts("## Ethernet MAC address not copied to NV RAM\n");
+#endif
+
+#ifdef CONFIG_X86
+ /*
+ * Get VxWorks's physical memory base address from environment,
+ * if we don't specify it in the environment, use a default one.
+ */
+ base = env_get_hex("vx_phys_mem_base", VXWORKS_PHYS_MEM_BASE);
+ data = (struct e820_entry *)(base + E820_DATA_OFFSET);
+ info = (struct e820_info *)(base + E820_INFO_OFFSET);
+
+ memset(info, 0, sizeof(struct e820_info));
+ info->sign = E820_SIGNATURE;
+ info->entries = install_e820_map(E820MAX, data);
+ info->addr = (info->entries - 1) * sizeof(struct e820_entry) +
+ E820_DATA_OFFSET;
+
+ /*
+ * Explicitly clear the bootloader image size otherwise if memory
+ * at this offset happens to contain some garbage data, the final
+ * available memory size for the kernel is insane.
+ */
+ *(u32 *)(base + BOOT_IMAGE_SIZE_OFFSET) = 0;
+
+ /*
+ * Prepare compatible framebuffer information block.
+ * The VESA mode has to be 32-bit RGBA.
+ */
+ if (vesa->x_resolution && vesa->y_resolution) {
+ gop = (struct efi_gop_info *)(base + EFI_GOP_INFO_OFFSET);
+ gop->magic = EFI_GOP_INFO_MAGIC;
+ gop->info.version = 0;
+ gop->info.width = vesa->x_resolution;
+ gop->info.height = vesa->y_resolution;
+ gop->info.pixel_format = EFI_GOT_RGBA8;
+ gop->info.pixels_per_scanline = vesa->bytes_per_scanline / 4;
+ gop->fb_base = vesa->phys_base_ptr;
+ gop->fb_size = vesa->bytes_per_scanline * vesa->y_resolution;
+ }
+#endif
+
+ /*
+ * Use bootaddr to find the location in memory that VxWorks
+ * will look for the bootline string. The default value is
+ * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by
+ * VxWorks BSP. For example, on PowerPC it defaults to 0x4200.
+ */
+ tmp = env_get("bootaddr");
+ if (!tmp) {
+#ifdef CONFIG_X86
+ bootaddr = base + X86_BOOT_LINE_OFFSET;
+#else
+ printf("## VxWorks bootline address not specified\n");
+ return 1;
+#endif
+ }
+
+ if (!bootaddr)
+ bootaddr = simple_strtoul(tmp, NULL, 16);
+
+ /*
+ * Check to see if the bootline is defined in the 'bootargs' parameter.
+ * If it is not defined, we may be able to construct the info.
+ */
+ bootline = env_get("bootargs");
+ if (!bootline) {
+ tmp = env_get("bootdev");
+ if (tmp) {
+ strcpy(build_buf, tmp);
+ ptr = strlen(tmp);
+ } else {
+ printf("## VxWorks boot device not specified\n");
+ }
+
+ tmp = env_get("bootfile");
+ if (tmp)
+ ptr += sprintf(build_buf + ptr, "host:%s ", tmp);
+ else
+ ptr += sprintf(build_buf + ptr, "host:vxWorks ");
+
+ /*
+ * The following parameters are only needed if 'bootdev'
+ * is an ethernet device, otherwise they are optional.
+ */
+ tmp = env_get("ipaddr");
+ if (tmp) {
+ ptr += sprintf(build_buf + ptr, "e=%s", tmp);
+ tmp = env_get("netmask");
+ if (tmp) {
+ u32 mask = env_get_ip("netmask").s_addr;
+ ptr += sprintf(build_buf + ptr,
+ ":%08x ", ntohl(mask));
+ } else {
+ ptr += sprintf(build_buf + ptr, " ");
+ }
+ }
+
+ tmp = env_get("serverip");
+ if (tmp)
+ ptr += sprintf(build_buf + ptr, "h=%s ", tmp);
+
+ tmp = env_get("gatewayip");
+ if (tmp)
+ ptr += sprintf(build_buf + ptr, "g=%s ", tmp);
+
+ tmp = env_get("hostname");
+ if (tmp)
+ ptr += sprintf(build_buf + ptr, "tn=%s ", tmp);
+
+ tmp = env_get("othbootargs");
+ if (tmp) {
+ strcpy(build_buf + ptr, tmp);
+ ptr += strlen(tmp);
+ }
+
+ bootline = build_buf;
+ }
+
+ memcpy((void *)bootaddr, bootline, max(strlen(bootline), (size_t)255));
+ flush_cache(bootaddr, max(strlen(bootline), (size_t)255));
+ printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, (char *)bootaddr);
+
+ /*
+ * If the data at the load address is an elf image, then
+ * treat it like an elf image. Otherwise, assume that it is a
+ * binary image.
+ */
+ if (valid_elf_image(addr))
+ addr = load_elf_image_phdr(addr);
+ else
+ puts("## Not an ELF image, assuming binary\n");
+
+ printf("## Starting vxWorks at 0x%08lx ...\n", addr);
+
+ dcache_disable();
+#if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI)
+ armv8_setup_psci();
+ smp_kick_all_cpus();
+#endif
+
+#ifdef CONFIG_X86
+ /* VxWorks on x86 uses stack to pass parameters */
+ ((asmlinkage void (*)(int))addr)(0);
+#else
+ ((void (*)(int))addr)(0);
+#endif
+
+ puts("## vxWorks terminated\n");
+
+ return 1;
+}
+
+U_BOOT_CMD(
+ bootelf, CONFIG_SYS_MAXARGS, 0, do_bootelf,
+ "Boot from an ELF image in memory",
+ "[-p|-s] [address]\n"
+ "\t- load ELF image at [address] via program headers (-p)\n"
+ "\t or via section headers (-s)"
+);
+
+U_BOOT_CMD(
+ bootvx, 2, 0, do_bootvx,
+ "Boot vxWorks from an ELF image",
+ " [address] - load address of vxWorks ELF image."
+);
diff --git a/roms/u-boot/cmd/ethsw.c b/roms/u-boot/cmd/ethsw.c
new file mode 100644
index 000000000..f8b8a798b
--- /dev/null
+++ b/roms/u-boot/cmd/ethsw.c
@@ -0,0 +1,1103 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ *
+ * Ethernet Switch commands
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <errno.h>
+#include <env_flags.h>
+#include <ethsw.h>
+#include <net.h>
+
+static const char *ethsw_name;
+
+#define ETHSW_PORT_STATS_HELP "ethsw [port <port_no>] statistics " \
+"{ [help] | [clear] } - show an l2 switch port's statistics"
+
+static int ethsw_port_stats_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_PORT_STATS_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ETHSW_LEARN_HELP "ethsw [port <port_no>] learning " \
+"{ [help] | show | auto | disable } " \
+"- enable/disable/show learning configuration on a port"
+
+static int ethsw_learn_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_LEARN_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ETHSW_FDB_HELP "ethsw [port <port_no>] [vlan <vid>] fdb " \
+"{ [help] | show | flush | { add | del } <mac> } " \
+"- Add/delete a mac entry in FDB; use show to see FDB entries; " \
+"if vlan <vid> is missing, VID 1 will be used"
+
+static int ethsw_fdb_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_FDB_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ETHSW_PVID_HELP "ethsw [port <port_no>] " \
+"pvid { [help] | show | <pvid> } " \
+"- set/show PVID (ingress and egress VLAN tagging) for a port"
+
+static int ethsw_pvid_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_PVID_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ETHSW_VLAN_HELP "ethsw [port <port_no>] vlan " \
+"{ [help] | show | add <vid> | del <vid> } " \
+"- add a VLAN to a port (VLAN members)"
+
+static int ethsw_vlan_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_VLAN_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ETHSW_PORT_UNTAG_HELP "ethsw [port <port_no>] untagged " \
+"{ [help] | show | all | none | pvid } " \
+" - set egress tagging mode for a port"
+
+static int ethsw_port_untag_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_PORT_UNTAG_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ETHSW_EGR_VLAN_TAG_HELP "ethsw [port <port_no>] egress tag " \
+"{ [help] | show | pvid | classified } " \
+"- Configure VID source for egress tag. " \
+"Tag's VID could be the frame's classified VID or the PVID of the port"
+
+static int ethsw_egr_tag_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_EGR_VLAN_TAG_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ETHSW_VLAN_FDB_HELP "ethsw vlan fdb " \
+"{ [help] | show | shared | private } " \
+"- make VLAN learning shared or private"
+
+static int ethsw_vlan_learn_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_VLAN_FDB_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ETHSW_PORT_INGR_FLTR_HELP "ethsw [port <port_no>] ingress filtering" \
+" { [help] | show | enable | disable } " \
+"- enable/disable VLAN ingress filtering on port"
+
+static int ethsw_ingr_fltr_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_PORT_INGR_FLTR_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ETHSW_PORT_AGGR_HELP "ethsw [port <port_no>] aggr" \
+" { [help] | show | <lag_group_no> } " \
+"- get/set LAG group for a port"
+
+static int ethsw_port_aggr_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_PORT_AGGR_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+static struct keywords_to_function {
+ enum ethsw_keyword_id cmd_keyword[ETHSW_MAX_CMD_PARAMS];
+ int cmd_func_offset;
+ int (*keyword_function)(struct ethsw_command_def *parsed_cmd);
+} ethsw_cmd_def[] = {
+ {
+ .cmd_keyword = {
+ ethsw_id_enable,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_enable),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_disable,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_disable),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_statistics,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_port_stats_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_statistics,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_stats),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_statistics,
+ ethsw_id_clear,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_stats_clear),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_learning,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_learn_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_learning,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_learn_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_learning,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_learn_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_learning,
+ ethsw_id_auto,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_learn),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_learning,
+ ethsw_id_disable,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_learn),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_fdb,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_fdb_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_fdb,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_fdb_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_fdb,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ fdb_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_fdb,
+ ethsw_id_flush,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ fdb_flush),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_fdb,
+ ethsw_id_add,
+ ethsw_id_add_del_mac,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ fdb_entry_add),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_fdb,
+ ethsw_id_del,
+ ethsw_id_add_del_mac,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ fdb_entry_del),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_pvid,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_pvid_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_pvid,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_pvid_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_pvid,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ pvid_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_pvid,
+ ethsw_id_pvid_no,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ pvid_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_vlan_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_vlan_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ vlan_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_add,
+ ethsw_id_add_del_no,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ vlan_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_del,
+ ethsw_id_add_del_no,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ vlan_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_untagged,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_port_untag_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_untagged,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_port_untag_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_untagged,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_untag_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_untagged,
+ ethsw_id_all,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_untag_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_untagged,
+ ethsw_id_none,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_untag_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_untagged,
+ ethsw_id_pvid,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_untag_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_egress,
+ ethsw_id_tag,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_egr_tag_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_egress,
+ ethsw_id_tag,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_egr_tag_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_egress,
+ ethsw_id_tag,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_egr_vlan_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_egress,
+ ethsw_id_tag,
+ ethsw_id_pvid,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_egr_vlan_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_egress,
+ ethsw_id_tag,
+ ethsw_id_classified,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_egr_vlan_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_vlan_learn_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_vlan_learn_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ vlan_learn_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_shared,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ vlan_learn_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_private,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ vlan_learn_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_ingress,
+ ethsw_id_filtering,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_ingr_fltr_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_ingress,
+ ethsw_id_filtering,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_ingr_fltr_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_ingress,
+ ethsw_id_filtering,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_ingr_filt_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_ingress,
+ ethsw_id_filtering,
+ ethsw_id_enable,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_ingr_filt_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_ingress,
+ ethsw_id_filtering,
+ ethsw_id_disable,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_ingr_filt_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_aggr,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_port_aggr_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_aggr,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_port_aggr_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_aggr,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_aggr_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_aggr,
+ ethsw_id_aggr_no,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ port_aggr_set),
+ .keyword_function = NULL,
+ },
+};
+
+struct keywords_optional {
+ int cmd_keyword[ETHSW_MAX_CMD_PARAMS];
+} cmd_opt_def[] = {
+ {
+ .cmd_keyword = {
+ ethsw_id_port,
+ ethsw_id_port_no,
+ ethsw_id_key_end,
+ },
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_vlan_no,
+ ethsw_id_key_end,
+ },
+ }, {
+ .cmd_keyword = {
+ ethsw_id_port,
+ ethsw_id_port_no,
+ ethsw_id_vlan,
+ ethsw_id_vlan_no,
+ ethsw_id_key_end,
+ },
+ },
+};
+
+static int keyword_match_gen(enum ethsw_keyword_id key_id, int argc, char
+ *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd);
+static int keyword_match_port(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd);
+static int keyword_match_vlan(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd);
+static int keyword_match_pvid(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd);
+static int keyword_match_mac_addr(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd);
+static int keyword_match_aggr(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd);
+
+/*
+ * Define properties for each keyword;
+ * keep the order synced with enum ethsw_keyword_id
+ */
+struct keyword_def {
+ const char *keyword_name;
+ int (*match)(enum ethsw_keyword_id key_id, int argc, char *const argv[],
+ int *argc_nr, struct ethsw_command_def *parsed_cmd);
+} keyword[] = {
+ {
+ .keyword_name = "help",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "show",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "port",
+ .match = &keyword_match_port
+ }, {
+ .keyword_name = "enable",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "disable",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "statistics",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "clear",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "learning",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "auto",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "vlan",
+ .match = &keyword_match_vlan,
+ }, {
+ .keyword_name = "fdb",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "add",
+ .match = &keyword_match_mac_addr,
+ }, {
+ .keyword_name = "del",
+ .match = &keyword_match_mac_addr,
+ }, {
+ .keyword_name = "flush",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "pvid",
+ .match = &keyword_match_pvid,
+ }, {
+ .keyword_name = "untagged",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "all",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "none",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "egress",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "tag",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "classified",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "shared",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "private",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "ingress",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "filtering",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "aggr",
+ .match = &keyword_match_aggr,
+ },
+};
+
+/*
+ * Function used by an Ethernet Switch driver to set the functions
+ * that must be called by the parser when an ethsw command is given
+ */
+int ethsw_define_functions(const struct ethsw_command_func *cmd_func)
+{
+ int i;
+ void **aux_p;
+ int (*cmd_func_aux)(struct ethsw_command_def *);
+
+ if (!cmd_func->ethsw_name)
+ return -EINVAL;
+
+ ethsw_name = cmd_func->ethsw_name;
+
+ for (i = 0; i < ARRAY_SIZE(ethsw_cmd_def); i++) {
+ /*
+ * get the pointer to the function send by the Ethernet Switch
+ * driver that corresponds to the proper ethsw command
+ */
+ if (ethsw_cmd_def[i].keyword_function)
+ continue;
+
+ aux_p = (void *)cmd_func + ethsw_cmd_def[i].cmd_func_offset;
+
+ cmd_func_aux = (int (*)(struct ethsw_command_def *)) *aux_p;
+ ethsw_cmd_def[i].keyword_function = cmd_func_aux;
+ }
+
+ return 0;
+}
+
+/* Generic function used to match a keyword only by a string */
+static int keyword_match_gen(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd)
+{
+ if (strcmp(argv[*argc_nr], keyword[key_id].keyword_name) == 0) {
+ parsed_cmd->cmd_to_keywords[*argc_nr] = key_id;
+
+ return 1;
+ }
+ return 0;
+}
+
+/* Function used to match the command's port */
+static int keyword_match_port(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd)
+{
+ unsigned long val;
+
+ if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd))
+ return 0;
+
+ if (*argc_nr + 1 >= argc)
+ return 0;
+
+ if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) {
+ parsed_cmd->port = val;
+ (*argc_nr)++;
+ parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_port_no;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Function used to match the command's vlan */
+static int keyword_match_vlan(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd)
+{
+ unsigned long val;
+ int aux;
+
+ if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd))
+ return 0;
+
+ if (*argc_nr + 1 >= argc)
+ return 0;
+
+ if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) {
+ parsed_cmd->vid = val;
+ (*argc_nr)++;
+ parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_vlan_no;
+ return 1;
+ }
+
+ aux = *argc_nr + 1;
+
+ if (keyword_match_gen(ethsw_id_add, argc, argv, &aux, parsed_cmd))
+ parsed_cmd->cmd_to_keywords[*argc_nr + 1] = ethsw_id_add;
+ else if (keyword_match_gen(ethsw_id_del, argc, argv, &aux, parsed_cmd))
+ parsed_cmd->cmd_to_keywords[*argc_nr + 1] = ethsw_id_del;
+ else
+ return 0;
+
+ if (*argc_nr + 2 >= argc)
+ return 0;
+
+ if (strict_strtoul(argv[*argc_nr + 2], 10, &val) != -EINVAL) {
+ parsed_cmd->vid = val;
+ (*argc_nr) += 2;
+ parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_add_del_no;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Function used to match the command's pvid */
+static int keyword_match_pvid(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd)
+{
+ unsigned long val;
+
+ if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd))
+ return 0;
+
+ if (*argc_nr + 1 >= argc)
+ return 1;
+
+ if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) {
+ parsed_cmd->vid = val;
+ (*argc_nr)++;
+ parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_pvid_no;
+ }
+
+ return 1;
+}
+
+/* Function used to match the command's MAC address */
+static int keyword_match_mac_addr(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd)
+{
+ if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd))
+ return 0;
+
+ if ((*argc_nr + 1 >= argc) ||
+ !is_broadcast_ethaddr(parsed_cmd->ethaddr))
+ return 1;
+
+ if (eth_validate_ethaddr_str(argv[*argc_nr + 1])) {
+ printf("Invalid MAC address: %s\n", argv[*argc_nr + 1]);
+ return 0;
+ }
+
+ string_to_enetaddr(argv[*argc_nr + 1], parsed_cmd->ethaddr);
+
+ if (is_broadcast_ethaddr(parsed_cmd->ethaddr)) {
+ memset(parsed_cmd->ethaddr, 0xFF, sizeof(parsed_cmd->ethaddr));
+ return 0;
+ }
+
+ parsed_cmd->cmd_to_keywords[*argc_nr + 1] = ethsw_id_add_del_mac;
+
+ return 1;
+}
+
+/* Function used to match the command's aggregation number */
+static int keyword_match_aggr(enum ethsw_keyword_id key_id, int argc,
+ char *const argv[], int *argc_nr,
+ struct ethsw_command_def *parsed_cmd)
+{
+ unsigned long val;
+
+ if (!keyword_match_gen(key_id, argc, argv, argc_nr, parsed_cmd))
+ return 0;
+
+ if (*argc_nr + 1 >= argc)
+ return 1;
+
+ if (strict_strtoul(argv[*argc_nr + 1], 10, &val) != -EINVAL) {
+ parsed_cmd->aggr_grp = val;
+ (*argc_nr)++;
+ parsed_cmd->cmd_to_keywords[*argc_nr] = ethsw_id_aggr_no;
+ }
+
+ return 1;
+}
+
+/* Finds optional keywords and modifies *argc_va to skip them */
+static void cmd_keywords_opt_check(const struct ethsw_command_def *parsed_cmd,
+ int *argc_val)
+{
+ int i;
+ int keyw_opt_matched;
+ int argc_val_max;
+ int const *cmd_keyw_p;
+ int const *cmd_keyw_opt_p;
+
+ /* remember the best match */
+ argc_val_max = *argc_val;
+
+ /*
+ * check if our command's optional keywords match the optional
+ * keywords of an available command
+ */
+ for (i = 0; i < ARRAY_SIZE(cmd_opt_def); i++) {
+ keyw_opt_matched = 0;
+ cmd_keyw_p = &parsed_cmd->cmd_to_keywords[keyw_opt_matched];
+ cmd_keyw_opt_p = &cmd_opt_def[i].cmd_keyword[keyw_opt_matched];
+
+ /*
+ * increase the number of keywords that
+ * matched with a command
+ */
+ while (keyw_opt_matched + *argc_val <
+ parsed_cmd->cmd_keywords_nr &&
+ *cmd_keyw_opt_p != ethsw_id_key_end &&
+ *(cmd_keyw_p + *argc_val) == *cmd_keyw_opt_p) {
+ keyw_opt_matched++;
+ cmd_keyw_p++;
+ cmd_keyw_opt_p++;
+ }
+
+ /*
+ * if all our optional command's keywords perfectly match an
+ * optional pattern, then we can move to the next defined
+ * keywords in our command; remember the one that matched the
+ * greatest number of keywords
+ */
+ if (keyw_opt_matched + *argc_val <=
+ parsed_cmd->cmd_keywords_nr &&
+ *cmd_keyw_opt_p == ethsw_id_key_end &&
+ *argc_val + keyw_opt_matched > argc_val_max)
+ argc_val_max = *argc_val + keyw_opt_matched;
+ }
+
+ *argc_val = argc_val_max;
+}
+
+/*
+ * Finds the function to call based on keywords and
+ * modifies *argc_va to skip them
+ */
+static void cmd_keywords_check(struct ethsw_command_def *parsed_cmd,
+ int *argc_val)
+{
+ int i;
+ int keyw_matched;
+ int *cmd_keyw_p;
+ int *cmd_keyw_def_p;
+
+ /*
+ * check if our command's keywords match the
+ * keywords of an available command
+ */
+ for (i = 0; i < ARRAY_SIZE(ethsw_cmd_def); i++) {
+ keyw_matched = 0;
+ cmd_keyw_p = &parsed_cmd->cmd_to_keywords[keyw_matched];
+ cmd_keyw_def_p = &ethsw_cmd_def[i].cmd_keyword[keyw_matched];
+
+ /*
+ * increase the number of keywords that
+ * matched with a command
+ */
+ while (keyw_matched + *argc_val < parsed_cmd->cmd_keywords_nr &&
+ *cmd_keyw_def_p != ethsw_id_key_end &&
+ *(cmd_keyw_p + *argc_val) == *cmd_keyw_def_p) {
+ keyw_matched++;
+ cmd_keyw_p++;
+ cmd_keyw_def_p++;
+ }
+
+ /*
+ * if all our command's keywords perfectly match an
+ * available command, then we get the function we need to call
+ * to configure the Ethernet Switch
+ */
+ if (keyw_matched && keyw_matched + *argc_val ==
+ parsed_cmd->cmd_keywords_nr &&
+ *cmd_keyw_def_p == ethsw_id_key_end) {
+ *argc_val += keyw_matched;
+ parsed_cmd->cmd_function =
+ ethsw_cmd_def[i].keyword_function;
+ return;
+ }
+ }
+}
+
+/* find all the keywords in the command */
+static int keywords_find(int argc, char *const argv[],
+ struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+ int j;
+ int argc_val;
+ int rc = CMD_RET_SUCCESS;
+
+ for (i = 1; i < argc; i++) {
+ for (j = 0; j < ethsw_id_count; j++) {
+ if (keyword[j].match(j, argc, argv, &i, parsed_cmd))
+ break;
+ }
+ }
+
+ /* if there is no keyword match for a word, the command is invalid */
+ for (i = 1; i < argc; i++)
+ if (parsed_cmd->cmd_to_keywords[i] == ethsw_id_key_end)
+ rc = CMD_RET_USAGE;
+
+ parsed_cmd->cmd_keywords_nr = argc;
+ argc_val = 1;
+
+ /* get optional parameters first */
+ cmd_keywords_opt_check(parsed_cmd, &argc_val);
+
+ if (argc_val == parsed_cmd->cmd_keywords_nr)
+ return CMD_RET_USAGE;
+
+ /*
+ * check the keywords and if a match is found,
+ * get the function to call
+ */
+ cmd_keywords_check(parsed_cmd, &argc_val);
+
+ /* error if not all commands' parameters were matched */
+ if (argc_val == parsed_cmd->cmd_keywords_nr) {
+ if (!parsed_cmd->cmd_function) {
+ printf("Command not available for: %s\n", ethsw_name);
+ rc = CMD_RET_FAILURE;
+ }
+ } else {
+ rc = CMD_RET_USAGE;
+ }
+
+ return rc;
+}
+
+static void command_def_init(struct ethsw_command_def *parsed_cmd)
+{
+ int i;
+
+ for (i = 0; i < ETHSW_MAX_CMD_PARAMS; i++)
+ parsed_cmd->cmd_to_keywords[i] = ethsw_id_key_end;
+
+ parsed_cmd->port = ETHSW_CMD_PORT_ALL;
+ parsed_cmd->vid = ETHSW_CMD_VLAN_ALL;
+ parsed_cmd->aggr_grp = ETHSW_CMD_AGGR_GRP_NONE;
+ parsed_cmd->cmd_function = NULL;
+
+ /* We initialize the MAC address with the Broadcast address */
+ memset(parsed_cmd->ethaddr, 0xff, sizeof(parsed_cmd->ethaddr));
+}
+
+/* function to interpret commands starting with "ethsw " */
+static int do_ethsw(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct ethsw_command_def parsed_cmd;
+ int rc = CMD_RET_SUCCESS;
+
+ if (argc == 1 || argc >= ETHSW_MAX_CMD_PARAMS)
+ return CMD_RET_USAGE;
+
+ command_def_init(&parsed_cmd);
+
+ rc = keywords_find(argc, argv, &parsed_cmd);
+
+ if (rc == CMD_RET_SUCCESS)
+ rc = parsed_cmd.cmd_function(&parsed_cmd);
+
+ return rc;
+}
+
+#define ETHSW_PORT_CONF_HELP "[port <port_no>] { enable | disable | show } " \
+"- enable/disable a port; show a port's configuration"
+
+U_BOOT_CMD(ethsw, ETHSW_MAX_CMD_PARAMS, 0, do_ethsw,
+ "Ethernet l2 switch commands",
+ ETHSW_PORT_CONF_HELP"\n"
+ ETHSW_PORT_STATS_HELP"\n"
+ ETHSW_LEARN_HELP"\n"
+ ETHSW_FDB_HELP"\n"
+ ETHSW_PVID_HELP"\n"
+ ETHSW_VLAN_HELP"\n"
+ ETHSW_PORT_UNTAG_HELP"\n"
+ ETHSW_EGR_VLAN_TAG_HELP"\n"
+ ETHSW_VLAN_FDB_HELP"\n"
+ ETHSW_PORT_INGR_FLTR_HELP"\n"
+ ETHSW_PORT_AGGR_HELP"\n"
+);
diff --git a/roms/u-boot/cmd/exit.c b/roms/u-boot/cmd/exit.c
new file mode 100644
index 000000000..923f0870f
--- /dev/null
+++ b/roms/u-boot/cmd/exit.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_exit(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc > 1)
+ return simple_strtoul(argv[1], NULL, 10);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ exit, 2, 1, do_exit,
+ "exit script",
+ ""
+);
diff --git a/roms/u-boot/cmd/ext2.c b/roms/u-boot/cmd/ext2.c
new file mode 100644
index 000000000..57a99516a
--- /dev/null
+++ b/roms/u-boot/cmd/ext2.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011 - 2012 Samsung Electronics
+ * EXT4 filesystem implementation in Uboot by
+ * Uma Shankar <uma.shankar@samsung.com>
+ * Manjunatha C Achar <a.manjunatha@samsung.com>
+
+ * (C) Copyright 2004
+ * esd gmbh <www.esd-electronics.com>
+ * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
+ *
+ * made from cmd_reiserfs by
+ *
+ * (C) Copyright 2003 - 2004
+ * Sysgo Real-Time Solutions, AG <www.elinos.com>
+ * Pavel Bartusek <pba@sysgo.com>
+ */
+
+/*
+ * Ext2fs support
+ */
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+
+static int do_ext2ls(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_ls(cmdtp, flag, argc, argv, FS_TYPE_EXT);
+}
+
+/******************************************************************************
+ * Ext2fs boot command intepreter. Derived from diskboot
+ */
+int do_ext2load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return do_load(cmdtp, flag, argc, argv, FS_TYPE_EXT);
+}
+
+U_BOOT_CMD(
+ ext2ls, 4, 1, do_ext2ls,
+ "list files in a directory (default /)",
+ "<interface> <dev[:part]> [directory]\n"
+ " - list files from 'dev' on 'interface' in a 'directory'"
+)
+
+U_BOOT_CMD(
+ ext2load, 6, 0, do_ext2load,
+ "load binary file from a Ext2 filesystem",
+ "<interface> [<dev[:part]> [addr [filename [bytes [pos]]]]]\n"
+ " - load binary file 'filename' from 'dev' on 'interface'\n"
+ " to address 'addr' from ext2 filesystem."
+)
diff --git a/roms/u-boot/cmd/ext4.c b/roms/u-boot/cmd/ext4.c
new file mode 100644
index 000000000..4791b69fd
--- /dev/null
+++ b/roms/u-boot/cmd/ext4.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011 - 2012 Samsung Electronics
+ * EXT4 filesystem implementation in Uboot by
+ * Uma Shankar <uma.shankar@samsung.com>
+ * Manjunatha C Achar <a.manjunatha@samsung.com>
+ *
+ * Ext4fs support
+ * made from existing cmd_ext2.c file of Uboot
+ *
+ * (C) Copyright 2004
+ * esd gmbh <www.esd-electronics.com>
+ * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
+ *
+ * made from cmd_reiserfs by
+ *
+ * (C) Copyright 2003 - 2004
+ * Sysgo Real-Time Solutions, AG <www.elinos.com>
+ * Pavel Bartusek <pba@sysgo.com>
+ */
+
+/*
+ * Changelog:
+ * 0.1 - Newly created file for ext4fs support. Taken from cmd_ext2.c
+ * file in uboot. Added ext4fs ls load and write support.
+ */
+
+#include <common.h>
+#include <part.h>
+#include <config.h>
+#include <command.h>
+#include <image.h>
+#include <linux/ctype.h>
+#include <asm/byteorder.h>
+#include <ext4fs.h>
+#include <linux/stat.h>
+#include <malloc.h>
+#include <fs.h>
+
+#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
+#include <usb.h>
+#endif
+
+int do_ext4_size(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return do_size(cmdtp, flag, argc, argv, FS_TYPE_EXT);
+}
+
+int do_ext4_load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return do_load(cmdtp, flag, argc, argv, FS_TYPE_EXT);
+}
+
+int do_ext4_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return do_ls(cmdtp, flag, argc, argv, FS_TYPE_EXT);
+}
+
+#if defined(CONFIG_CMD_EXT4_WRITE)
+int do_ext4_write(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_save(cmdtp, flag, argc, argv, FS_TYPE_EXT);
+}
+
+U_BOOT_CMD(ext4write, 7, 1, do_ext4_write,
+ "create a file in the root directory",
+ "<interface> <dev[:part]> <addr> <absolute filename path>\n"
+ " [sizebytes] [file offset]\n"
+ " - create a file in / directory");
+
+#endif
+
+U_BOOT_CMD(
+ ext4size, 4, 0, do_ext4_size,
+ "determine a file's size",
+ "<interface> <dev[:part]> <filename>\n"
+ " - Find file 'filename' from 'dev' on 'interface'\n"
+ " and determine its size."
+);
+
+U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls,
+ "list files in a directory (default /)",
+ "<interface> <dev[:part]> [directory]\n"
+ " - list files from 'dev' on 'interface' in a 'directory'");
+
+U_BOOT_CMD(ext4load, 7, 0, do_ext4_load,
+ "load binary file from a Ext4 filesystem",
+ "<interface> [<dev[:part]> [addr [filename [bytes [pos]]]]]\n"
+ " - load binary file 'filename' from 'dev' on 'interface'\n"
+ " to address 'addr' from ext4 filesystem");
diff --git a/roms/u-boot/cmd/extension_board.c b/roms/u-boot/cmd/extension_board.c
new file mode 100644
index 000000000..bbb4812ff
--- /dev/null
+++ b/roms/u-boot/cmd/extension_board.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021
+ * Köry Maincent, Bootlin, <kory.maincent@bootlin.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <extension_board.h>
+#include <mapmem.h>
+#include <linux/libfdt.h>
+#include <fdt_support.h>
+
+static LIST_HEAD(extension_list);
+
+static int extension_apply(struct extension *extension)
+{
+ char *overlay_cmd;
+ ulong extrasize, overlay_addr;
+ struct fdt_header *blob;
+
+ if (!working_fdt) {
+ printf("No FDT memory address configured. Please configure\n"
+ "the FDT address via \"fdt addr <address>\" command.\n");
+ return CMD_RET_FAILURE;
+ }
+
+ overlay_cmd = env_get("extension_overlay_cmd");
+ if (!overlay_cmd) {
+ printf("Environment extension_overlay_cmd is missing\n");
+ return CMD_RET_FAILURE;
+ }
+
+ overlay_addr = env_get_hex("extension_overlay_addr", 0);
+ if (!overlay_addr) {
+ printf("Environment extension_overlay_addr is missing\n");
+ return CMD_RET_FAILURE;
+ }
+
+ env_set("extension_overlay_name", extension->overlay);
+ if (run_command(overlay_cmd, 0) != 0)
+ return CMD_RET_FAILURE;
+
+ extrasize = env_get_hex("filesize", 0);
+ if (!extrasize)
+ return CMD_RET_FAILURE;
+
+ fdt_shrink_to_minimum(working_fdt, extrasize);
+
+ blob = map_sysmem(overlay_addr, 0);
+ if (!fdt_valid(&blob))
+ return CMD_RET_FAILURE;
+
+ /* apply method prints messages on error */
+ if (fdt_overlay_apply_verbose(working_fdt, blob))
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_extension_list(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int i = 0;
+ struct extension *extension;
+
+ if (list_empty(&extension_list)) {
+ printf("No extension registered - Please run \"extension scan\"\n");
+ return CMD_RET_SUCCESS;
+ }
+
+ list_for_each_entry(extension, &extension_list, list) {
+ printf("Extension %d: %s\n", i++, extension->name);
+ printf("\tManufacturer: \t\t%s\n", extension->owner);
+ printf("\tVersion: \t\t%s\n", extension->version);
+ printf("\tDevicetree overlay: \t%s\n", extension->overlay);
+ printf("\tOther information: \t%s\n", extension->other);
+ }
+ return CMD_RET_SUCCESS;
+}
+
+static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct extension *extension, *next;
+ int extension_num;
+
+ list_for_each_entry_safe(extension, next, &extension_list, list) {
+ list_del(&extension->list);
+ free(extension);
+ }
+ extension_num = extension_board_scan(&extension_list);
+
+ if (extension_num < 0)
+ return CMD_RET_FAILURE;
+
+ printf("Found %d extension board(s).\n", extension_num);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_extension_apply(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct extension *extension = NULL;
+ struct list_head *entry;
+ int i = 0, extension_id, ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "all") == 0) {
+ list_for_each_entry(extension, &extension_list, list) {
+ ret = extension_apply(extension);
+ if (ret != CMD_RET_SUCCESS)
+ break;
+ }
+ } else {
+ extension_id = simple_strtol(argv[1], NULL, 10);
+ list_for_each(entry, &extension_list) {
+ if (i == extension_id) {
+ extension = list_entry(entry, struct extension, list);
+ break;
+ }
+ i++;
+ }
+
+ if (!extension) {
+ printf("Wrong extension number\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = extension_apply(extension);
+ }
+
+ return ret;
+}
+
+static struct cmd_tbl cmd_extension[] = {
+ U_BOOT_CMD_MKENT(scan, 1, 1, do_extension_scan, "", ""),
+ U_BOOT_CMD_MKENT(list, 1, 0, do_extension_list, "", ""),
+ U_BOOT_CMD_MKENT(apply, 2, 0, do_extension_apply, "", ""),
+};
+
+static int do_extensionops(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ /* Drop the extension command */
+ argc--;
+ argv++;
+
+ cp = find_cmd_tbl(argv[0], cmd_extension, ARRAY_SIZE(cmd_extension));
+ if (cp)
+ return cp->cmd(cmdtp, flag, argc, argv);
+
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(extension, 3, 1, do_extensionops,
+ "Extension board management sub system",
+ "scan - scan plugged extension(s) board(s)\n"
+ "extension list - lists available extension(s) board(s)\n"
+ "extension apply <extension number|all> - applies DT overlays corresponding to extension boards\n"
+);
diff --git a/roms/u-boot/cmd/fastboot.c b/roms/u-boot/cmd/fastboot.c
new file mode 100644
index 000000000..ad5c06491
--- /dev/null
+++ b/roms/u-boot/cmd/fastboot.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2008 - 2009 Windriver, <www.windriver.com>
+ * Author: Tom Rix <Tom.Rix@windriver.com>
+ *
+ * (C) Copyright 2014 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ */
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <g_dnl.h>
+#include <fastboot.h>
+#include <net.h>
+#include <usb.h>
+#include <watchdog.h>
+#include <linux/stringify.h>
+
+static int do_fastboot_udp(int argc, char *const argv[],
+ uintptr_t buf_addr, size_t buf_size)
+{
+#if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT)
+ int err = net_loop(FASTBOOT);
+
+ if (err < 0) {
+ printf("fastboot udp error: %d\n", err);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+#else
+ pr_err("Fastboot UDP not enabled\n");
+ return CMD_RET_FAILURE;
+#endif
+}
+
+static int do_fastboot_usb(int argc, char *const argv[],
+ uintptr_t buf_addr, size_t buf_size)
+{
+#if CONFIG_IS_ENABLED(USB_FUNCTION_FASTBOOT)
+ int controller_index;
+ char *usb_controller;
+ char *endp;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ usb_controller = argv[1];
+ controller_index = simple_strtoul(usb_controller, &endp, 0);
+ if (*endp != '\0') {
+ pr_err("Error: Wrong USB controller index format\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = usb_gadget_initialize(controller_index);
+ if (ret) {
+ pr_err("USB init failed: %d\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ g_dnl_clear_detach();
+ ret = g_dnl_register("usb_dnl_fastboot");
+ if (ret)
+ return ret;
+
+ if (!g_dnl_board_usb_cable_connected()) {
+ puts("\rUSB cable not detected.\n" \
+ "Command exit.\n");
+ ret = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ while (1) {
+ if (g_dnl_detach())
+ break;
+ if (ctrlc())
+ break;
+ WATCHDOG_RESET();
+ usb_gadget_handle_interrupts(controller_index);
+ }
+
+ ret = CMD_RET_SUCCESS;
+
+exit:
+ g_dnl_unregister();
+ g_dnl_clear_detach();
+ usb_gadget_release(controller_index);
+
+ return ret;
+#else
+ pr_err("Fastboot USB not enabled\n");
+ return CMD_RET_FAILURE;
+#endif
+}
+
+static int do_fastboot(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uintptr_t buf_addr = (uintptr_t)NULL;
+ size_t buf_size = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ while (argc > 1 && **(argv + 1) == '-') {
+ char *arg = *++argv;
+
+ --argc;
+ while (*++arg) {
+ switch (*arg) {
+ case 'l':
+ if (--argc <= 0)
+ return CMD_RET_USAGE;
+ buf_addr = simple_strtoul(*++argv, NULL, 16);
+ goto NXTARG;
+
+ case 's':
+ if (--argc <= 0)
+ return CMD_RET_USAGE;
+ buf_size = simple_strtoul(*++argv, NULL, 16);
+ goto NXTARG;
+
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+NXTARG:
+ ;
+ }
+
+ /* Handle case when USB controller param is just '-' */
+ if (argc == 1) {
+ pr_err("Error: Incorrect USB controller index\n");
+ return CMD_RET_USAGE;
+ }
+
+ fastboot_init((void *)buf_addr, buf_size);
+
+ if (!strcmp(argv[1], "udp"))
+ return do_fastboot_udp(argc, argv, buf_addr, buf_size);
+
+ if (!strcmp(argv[1], "usb")) {
+ argv++;
+ argc--;
+ }
+
+ return do_fastboot_usb(argc, argv, buf_addr, buf_size);
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char fastboot_help_text[] =
+ "[-l addr] [-s size] usb <controller> | udp\n"
+ "\taddr - address of buffer used during data transfers ("
+ __stringify(CONFIG_FASTBOOT_BUF_ADDR) ")\n"
+ "\tsize - size of buffer used during data transfers ("
+ __stringify(CONFIG_FASTBOOT_BUF_SIZE) ")"
+ ;
+#endif
+
+U_BOOT_CMD(
+ fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,
+ "run as a fastboot usb or udp device", fastboot_help_text
+);
diff --git a/roms/u-boot/cmd/fat.c b/roms/u-boot/cmd/fat.c
new file mode 100644
index 000000000..69ce1fa53
--- /dev/null
+++ b/roms/u-boot/cmd/fat.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Richard Jones, rjones@nexus-tech.net
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <mapmem.h>
+#include <fat.h>
+#include <fs.h>
+#include <part.h>
+#include <asm/cache.h>
+
+int do_fat_size(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return do_size(cmdtp, flag, argc, argv, FS_TYPE_FAT);
+}
+
+U_BOOT_CMD(
+ fatsize, 4, 0, do_fat_size,
+ "determine a file's size",
+ "<interface> <dev[:part]> <filename>\n"
+ " - Find file 'filename' from 'dev' on 'interface'\n"
+ " and determine its size."
+);
+
+int do_fat_fsload(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return do_load(cmdtp, flag, argc, argv, FS_TYPE_FAT);
+}
+
+
+U_BOOT_CMD(
+ fatload, 7, 0, do_fat_fsload,
+ "load binary file from a dos filesystem",
+ "<interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]\n"
+ " - Load binary file 'filename' from 'dev' on 'interface'\n"
+ " to address 'addr' from dos filesystem.\n"
+ " 'pos' gives the file position to start loading from.\n"
+ " If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n"
+ " 'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n"
+ " the load stops on end of file.\n"
+ " If either 'pos' or 'bytes' are not aligned to\n"
+ " ARCH_DMA_MINALIGN then a misaligned buffer warning will\n"
+ " be printed and performance will suffer for the load."
+);
+
+static int do_fat_ls(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_ls(cmdtp, flag, argc, argv, FS_TYPE_FAT);
+}
+
+U_BOOT_CMD(
+ fatls, 4, 1, do_fat_ls,
+ "list files in a directory (default /)",
+ "<interface> [<dev[:part]>] [directory]\n"
+ " - list files from 'dev' on 'interface' in a 'directory'"
+);
+
+static int do_fat_fsinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int dev, part;
+ struct blk_desc *dev_desc;
+ struct disk_partition info;
+
+ if (argc < 2) {
+ printf("usage: fatinfo <interface> [<dev[:part]>]\n");
+ return 0;
+ }
+
+ part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
+ if (part < 0)
+ return 1;
+
+ dev = dev_desc->devnum;
+ if (fat_set_blk_dev(dev_desc, &info) != 0) {
+ printf("\n** Unable to use %s %d:%d for fatinfo **\n",
+ argv[1], dev, part);
+ return 1;
+ }
+ return file_fat_detectfs();
+}
+
+U_BOOT_CMD(
+ fatinfo, 3, 1, do_fat_fsinfo,
+ "print information about filesystem",
+ "<interface> [<dev[:part]>]\n"
+ " - print information about filesystem from 'dev' on 'interface'"
+);
+
+#ifdef CONFIG_FAT_WRITE
+static int do_fat_fswrite(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_save(cmdtp, flag, argc, argv, FS_TYPE_FAT);
+}
+
+U_BOOT_CMD(
+ fatwrite, 7, 0, do_fat_fswrite,
+ "write file into a dos filesystem",
+ "<interface> <dev[:part]> <addr> <filename> [<bytes> [<offset>]]\n"
+ " - write file 'filename' from the address 'addr' in RAM\n"
+ " to 'dev' on 'interface'"
+);
+
+static int do_fat_rm(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_rm(cmdtp, flag, argc, argv, FS_TYPE_FAT);
+}
+
+U_BOOT_CMD(
+ fatrm, 4, 1, do_fat_rm,
+ "delete a file",
+ "<interface> [<dev[:part]>] <filename>\n"
+ " - delete a file from 'dev' on 'interface'"
+);
+
+static int do_fat_mkdir(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_mkdir(cmdtp, flag, argc, argv, FS_TYPE_FAT);
+}
+
+U_BOOT_CMD(
+ fatmkdir, 4, 1, do_fat_mkdir,
+ "create a directory",
+ "<interface> [<dev[:part]>] <directory>\n"
+ " - create a directory in 'dev' on 'interface'"
+);
+#endif
diff --git a/roms/u-boot/cmd/fdt.c b/roms/u-boot/cmd/fdt.c
new file mode 100644
index 000000000..f1e2fc2fd
--- /dev/null
+++ b/roms/u-boot/cmd/fdt.c
@@ -0,0 +1,1109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ * Based on code written by:
+ * Pantelis Antoniou <pantelis.antoniou@gmail.com> and
+ * Matthew McClintock <msm@freescale.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <asm/global_data.h>
+#include <linux/libfdt.h>
+#include <fdt_support.h>
+#include <mapmem.h>
+#include <asm/io.h>
+
+#define MAX_LEVEL 32 /* how deeply nested we will go */
+#define SCRATCHPAD 1024 /* bytes of scratchpad memory */
+
+/*
+ * Global data (for the gd->bd)
+ */
+DECLARE_GLOBAL_DATA_PTR;
+
+static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
+static int fdt_print(const char *pathp, char *prop, int depth);
+static int is_printable_string(const void *data, int len);
+
+/*
+ * The working_fdt points to our working flattened device tree.
+ */
+struct fdt_header *working_fdt;
+
+void set_working_fdt_addr(ulong addr)
+{
+ void *buf;
+
+ buf = map_sysmem(addr, 0);
+ working_fdt = buf;
+ env_set_hex("fdtaddr", addr);
+}
+
+/*
+ * Get a value from the fdt and format it to be set in the environment
+ */
+static int fdt_value_env_set(const void *nodep, int len, const char *var)
+{
+ if (is_printable_string(nodep, len))
+ env_set(var, (void *)nodep);
+ else if (len == 4) {
+ char buf[11];
+
+ sprintf(buf, "0x%08X", fdt32_to_cpu(*(fdt32_t *)nodep));
+ env_set(var, buf);
+ } else if (len%4 == 0 && len <= 20) {
+ /* Needed to print things like sha1 hashes. */
+ char buf[41];
+ int i;
+
+ for (i = 0; i < len; i += sizeof(unsigned int))
+ sprintf(buf + (i * 2), "%08x",
+ *(unsigned int *)(nodep + i));
+ env_set(var, buf);
+ } else {
+ printf("error: unprintable value\n");
+ return 1;
+ }
+ return 0;
+}
+
+static const char * const fdt_member_table[] = {
+ "magic",
+ "totalsize",
+ "off_dt_struct",
+ "off_dt_strings",
+ "off_mem_rsvmap",
+ "version",
+ "last_comp_version",
+ "boot_cpuid_phys",
+ "size_dt_strings",
+ "size_dt_struct",
+};
+
+static int fdt_get_header_value(int argc, char *const argv[])
+{
+ fdt32_t *fdtp = (fdt32_t *)working_fdt;
+ ulong val;
+ int i;
+
+ if (argv[2][0] != 'g')
+ return CMD_RET_FAILURE;
+
+ for (i = 0; i < ARRAY_SIZE(fdt_member_table); i++) {
+ if (strcmp(fdt_member_table[i], argv[4]))
+ continue;
+
+ val = fdt32_to_cpu(fdtp[i]);
+ env_set_hex(argv[3], val);
+ return CMD_RET_SUCCESS;
+ }
+
+ return CMD_RET_FAILURE;
+}
+
+/*
+ * Flattened Device Tree command, see the help for parameter definitions.
+ */
+static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /*
+ * Set the address of the fdt
+ */
+ if (strncmp(argv[1], "ad", 2) == 0) {
+ unsigned long addr;
+ int control = 0;
+ struct fdt_header *blob;
+ /*
+ * Set the address [and length] of the fdt.
+ */
+ argc -= 2;
+ argv += 2;
+/* Temporary #ifdef - some archs don't have fdt_blob yet */
+#ifdef CONFIG_OF_CONTROL
+ if (argc && !strcmp(*argv, "-c")) {
+ control = 1;
+ argc--;
+ argv++;
+ }
+#endif
+ if (argc == 0) {
+ if (control)
+ blob = (struct fdt_header *)gd->fdt_blob;
+ else
+ blob = working_fdt;
+ if (!blob || !fdt_valid(&blob))
+ return 1;
+ printf("The address of the fdt is %#08lx\n",
+ control ? (ulong)map_to_sysmem(blob) :
+ env_get_hex("fdtaddr", 0));
+ return 0;
+ }
+
+ addr = simple_strtoul(argv[0], NULL, 16);
+ blob = map_sysmem(addr, 0);
+ if (!fdt_valid(&blob))
+ return 1;
+ if (control)
+ gd->fdt_blob = blob;
+ else
+ set_working_fdt_addr(addr);
+
+ if (argc >= 2) {
+ int len;
+ int err;
+ /*
+ * Optional new length
+ */
+ len = simple_strtoul(argv[1], NULL, 16);
+ if (len < fdt_totalsize(blob)) {
+ printf ("New length %d < existing length %d, "
+ "ignoring.\n",
+ len, fdt_totalsize(blob));
+ } else {
+ /*
+ * Open in place with a new length.
+ */
+ err = fdt_open_into(blob, blob, len);
+ if (err != 0) {
+ printf ("libfdt fdt_open_into(): %s\n",
+ fdt_strerror(err));
+ }
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+ }
+
+ if (!working_fdt) {
+ puts(
+ "No FDT memory address configured. Please configure\n"
+ "the FDT address via \"fdt addr <address>\" command.\n"
+ "Aborting!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ /*
+ * Move the working_fdt
+ */
+ if (strncmp(argv[1], "mo", 2) == 0) {
+ struct fdt_header *newaddr;
+ int len;
+ int err;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ /*
+ * Set the address and length of the fdt.
+ */
+ working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
+ if (!fdt_valid(&working_fdt))
+ return 1;
+
+ newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
+
+ /*
+ * If the user specifies a length, use that. Otherwise use the
+ * current length.
+ */
+ if (argc <= 4) {
+ len = fdt_totalsize(working_fdt);
+ } else {
+ len = simple_strtoul(argv[4], NULL, 16);
+ if (len < fdt_totalsize(working_fdt)) {
+ printf ("New length 0x%X < existing length "
+ "0x%X, aborting.\n",
+ len, fdt_totalsize(working_fdt));
+ return 1;
+ }
+ }
+
+ /*
+ * Copy to the new location.
+ */
+ err = fdt_open_into(working_fdt, newaddr, len);
+ if (err != 0) {
+ printf ("libfdt fdt_open_into(): %s\n",
+ fdt_strerror(err));
+ return 1;
+ }
+ set_working_fdt_addr((ulong)newaddr);
+#ifdef CONFIG_OF_SYSTEM_SETUP
+ /* Call the board-specific fixup routine */
+ } else if (strncmp(argv[1], "sys", 3) == 0) {
+ int err = ft_system_setup(working_fdt, gd->bd);
+
+ if (err) {
+ printf("Failed to add system information to FDT: %s\n",
+ fdt_strerror(err));
+ return CMD_RET_FAILURE;
+ }
+#endif
+ /*
+ * Make a new node
+ */
+ } else if (strncmp(argv[1], "mk", 2) == 0) {
+ char *pathp; /* path */
+ char *nodep; /* new node to add */
+ int nodeoffset; /* node offset from libfdt */
+ int err;
+
+ /*
+ * Parameters: Node path, new node to be appended to the path.
+ */
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ pathp = argv[2];
+ nodep = argv[3];
+
+ nodeoffset = fdt_path_offset (working_fdt, pathp);
+ if (nodeoffset < 0) {
+ /*
+ * Not found or something else bad happened.
+ */
+ printf ("libfdt fdt_path_offset() returned %s\n",
+ fdt_strerror(nodeoffset));
+ return 1;
+ }
+ err = fdt_add_subnode(working_fdt, nodeoffset, nodep);
+ if (err < 0) {
+ printf ("libfdt fdt_add_subnode(): %s\n",
+ fdt_strerror(err));
+ return 1;
+ }
+
+ /*
+ * Set the value of a property in the working_fdt.
+ */
+ } else if (strncmp(argv[1], "se", 2) == 0) {
+ char *pathp; /* path */
+ char *prop; /* property */
+ int nodeoffset; /* node offset from libfdt */
+ static char data[SCRATCHPAD] __aligned(4);/* property storage */
+ const void *ptmp;
+ int len; /* new length of the property */
+ int ret; /* return value */
+
+ /*
+ * Parameters: Node path, property, optional value.
+ */
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ pathp = argv[2];
+ prop = argv[3];
+
+ nodeoffset = fdt_path_offset (working_fdt, pathp);
+ if (nodeoffset < 0) {
+ /*
+ * Not found or something else bad happened.
+ */
+ printf ("libfdt fdt_path_offset() returned %s\n",
+ fdt_strerror(nodeoffset));
+ return 1;
+ }
+
+ if (argc == 4) {
+ len = 0;
+ } else {
+ ptmp = fdt_getprop(working_fdt, nodeoffset, prop, &len);
+ if (len > SCRATCHPAD) {
+ printf("prop (%d) doesn't fit in scratchpad!\n",
+ len);
+ return 1;
+ }
+ if (ptmp != NULL)
+ memcpy(data, ptmp, len);
+
+ ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
+ if (ret != 0)
+ return ret;
+ }
+
+ ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len);
+ if (ret < 0) {
+ printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret));
+ return 1;
+ }
+
+ /********************************************************************
+ * Get the value of a property in the working_fdt.
+ ********************************************************************/
+ } else if (argv[1][0] == 'g') {
+ char *subcmd; /* sub-command */
+ char *pathp; /* path */
+ char *prop; /* property */
+ char *var; /* variable to store result */
+ int nodeoffset; /* node offset from libfdt */
+ const void *nodep; /* property node pointer */
+ int len = 0; /* new length of the property */
+
+ /*
+ * Parameters: Node path, property, optional value.
+ */
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ subcmd = argv[2];
+
+ if (argc < 6 && subcmd[0] != 's')
+ return CMD_RET_USAGE;
+
+ var = argv[3];
+ pathp = argv[4];
+ prop = argv[5];
+
+ nodeoffset = fdt_path_offset(working_fdt, pathp);
+ if (nodeoffset < 0) {
+ /*
+ * Not found or something else bad happened.
+ */
+ printf("libfdt fdt_path_offset() returned %s\n",
+ fdt_strerror(nodeoffset));
+ return 1;
+ }
+
+ if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) {
+ int reqIndex = -1;
+ int startDepth = fdt_node_depth(
+ working_fdt, nodeoffset);
+ int curDepth = startDepth;
+ int curIndex = -1;
+ int nextNodeOffset = fdt_next_node(
+ working_fdt, nodeoffset, &curDepth);
+
+ if (subcmd[0] == 'n')
+ reqIndex = simple_strtoul(argv[5], NULL, 16);
+
+ while (curDepth > startDepth) {
+ if (curDepth == startDepth + 1)
+ curIndex++;
+ if (subcmd[0] == 'n' && curIndex == reqIndex) {
+ const char *node_name;
+
+ node_name = fdt_get_name(working_fdt,
+ nextNodeOffset,
+ NULL);
+ env_set(var, node_name);
+ return 0;
+ }
+ nextNodeOffset = fdt_next_node(
+ working_fdt, nextNodeOffset, &curDepth);
+ if (nextNodeOffset < 0)
+ break;
+ }
+ if (subcmd[0] == 's') {
+ /* get the num nodes at this level */
+ env_set_ulong(var, curIndex + 1);
+ } else {
+ /* node index not found */
+ printf("libfdt node not found\n");
+ return 1;
+ }
+ } else {
+ nodep = fdt_getprop(
+ working_fdt, nodeoffset, prop, &len);
+ if (len == 0) {
+ /* no property value */
+ env_set(var, "");
+ return 0;
+ } else if (nodep && len > 0) {
+ if (subcmd[0] == 'v') {
+ int ret;
+
+ ret = fdt_value_env_set(nodep, len,
+ var);
+ if (ret != 0)
+ return ret;
+ } else if (subcmd[0] == 'a') {
+ /* Get address */
+ char buf[11];
+
+ sprintf(buf, "0x%p", nodep);
+ env_set(var, buf);
+ } else if (subcmd[0] == 's') {
+ /* Get size */
+ char buf[11];
+
+ sprintf(buf, "0x%08X", len);
+ env_set(var, buf);
+ } else
+ return CMD_RET_USAGE;
+ return 0;
+ } else {
+ printf("libfdt fdt_getprop(): %s\n",
+ fdt_strerror(len));
+ return 1;
+ }
+ }
+
+ /*
+ * Print (recursive) / List (single level)
+ */
+ } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {
+ int depth = MAX_LEVEL; /* how deep to print */
+ char *pathp; /* path */
+ char *prop; /* property */
+ int ret; /* return value */
+ static char root[2] = "/";
+
+ /*
+ * list is an alias for print, but limited to 1 level
+ */
+ if (argv[1][0] == 'l') {
+ depth = 1;
+ }
+
+ /*
+ * Get the starting path. The root node is an oddball,
+ * the offset is zero and has no name.
+ */
+ if (argc == 2)
+ pathp = root;
+ else
+ pathp = argv[2];
+ if (argc > 3)
+ prop = argv[3];
+ else
+ prop = NULL;
+
+ ret = fdt_print(pathp, prop, depth);
+ if (ret != 0)
+ return ret;
+
+ /*
+ * Remove a property/node
+ */
+ } else if (strncmp(argv[1], "rm", 2) == 0) {
+ int nodeoffset; /* node offset from libfdt */
+ int err;
+
+ /*
+ * Get the path. The root node is an oddball, the offset
+ * is zero and has no name.
+ */
+ nodeoffset = fdt_path_offset (working_fdt, argv[2]);
+ if (nodeoffset < 0) {
+ /*
+ * Not found or something else bad happened.
+ */
+ printf ("libfdt fdt_path_offset() returned %s\n",
+ fdt_strerror(nodeoffset));
+ return 1;
+ }
+ /*
+ * Do the delete. A fourth parameter means delete a property,
+ * otherwise delete the node.
+ */
+ if (argc > 3) {
+ err = fdt_delprop(working_fdt, nodeoffset, argv[3]);
+ if (err < 0) {
+ printf("libfdt fdt_delprop(): %s\n",
+ fdt_strerror(err));
+ return err;
+ }
+ } else {
+ err = fdt_del_node(working_fdt, nodeoffset);
+ if (err < 0) {
+ printf("libfdt fdt_del_node(): %s\n",
+ fdt_strerror(err));
+ return err;
+ }
+ }
+
+ /*
+ * Display header info
+ */
+ } else if (argv[1][0] == 'h') {
+ if (argc == 5)
+ return fdt_get_header_value(argc, argv);
+
+ u32 version = fdt_version(working_fdt);
+ printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt));
+ printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt),
+ fdt_totalsize(working_fdt));
+ printf("off_dt_struct:\t\t0x%x\n",
+ fdt_off_dt_struct(working_fdt));
+ printf("off_dt_strings:\t\t0x%x\n",
+ fdt_off_dt_strings(working_fdt));
+ printf("off_mem_rsvmap:\t\t0x%x\n",
+ fdt_off_mem_rsvmap(working_fdt));
+ printf("version:\t\t%d\n", version);
+ printf("last_comp_version:\t%d\n",
+ fdt_last_comp_version(working_fdt));
+ if (version >= 2)
+ printf("boot_cpuid_phys:\t0x%x\n",
+ fdt_boot_cpuid_phys(working_fdt));
+ if (version >= 3)
+ printf("size_dt_strings:\t0x%x\n",
+ fdt_size_dt_strings(working_fdt));
+ if (version >= 17)
+ printf("size_dt_struct:\t\t0x%x\n",
+ fdt_size_dt_struct(working_fdt));
+ printf("number mem_rsv:\t\t0x%x\n",
+ fdt_num_mem_rsv(working_fdt));
+ printf("\n");
+
+ /*
+ * Set boot cpu id
+ */
+ } else if (strncmp(argv[1], "boo", 3) == 0) {
+ unsigned long tmp = simple_strtoul(argv[2], NULL, 16);
+ fdt_set_boot_cpuid_phys(working_fdt, tmp);
+
+ /*
+ * memory command
+ */
+ } else if (strncmp(argv[1], "me", 2) == 0) {
+ uint64_t addr, size;
+ int err;
+ addr = simple_strtoull(argv[2], NULL, 16);
+ size = simple_strtoull(argv[3], NULL, 16);
+ err = fdt_fixup_memory(working_fdt, addr, size);
+ if (err < 0)
+ return err;
+
+ /*
+ * mem reserve commands
+ */
+ } else if (strncmp(argv[1], "rs", 2) == 0) {
+ if (argv[2][0] == 'p') {
+ uint64_t addr, size;
+ int total = fdt_num_mem_rsv(working_fdt);
+ int j, err;
+ printf("index\t\t start\t\t size\n");
+ printf("-------------------------------"
+ "-----------------\n");
+ for (j = 0; j < total; j++) {
+ err = fdt_get_mem_rsv(working_fdt, j, &addr, &size);
+ if (err < 0) {
+ printf("libfdt fdt_get_mem_rsv(): %s\n",
+ fdt_strerror(err));
+ return err;
+ }
+ printf(" %x\t%08x%08x\t%08x%08x\n", j,
+ (u32)(addr >> 32),
+ (u32)(addr & 0xffffffff),
+ (u32)(size >> 32),
+ (u32)(size & 0xffffffff));
+ }
+ } else if (argv[2][0] == 'a') {
+ uint64_t addr, size;
+ int err;
+ addr = simple_strtoull(argv[3], NULL, 16);
+ size = simple_strtoull(argv[4], NULL, 16);
+ err = fdt_add_mem_rsv(working_fdt, addr, size);
+
+ if (err < 0) {
+ printf("libfdt fdt_add_mem_rsv(): %s\n",
+ fdt_strerror(err));
+ return err;
+ }
+ } else if (argv[2][0] == 'd') {
+ unsigned long idx = simple_strtoul(argv[3], NULL, 16);
+ int err = fdt_del_mem_rsv(working_fdt, idx);
+
+ if (err < 0) {
+ printf("libfdt fdt_del_mem_rsv(): %s\n",
+ fdt_strerror(err));
+ return err;
+ }
+ } else {
+ /* Unrecognized command */
+ return CMD_RET_USAGE;
+ }
+ }
+#ifdef CONFIG_OF_BOARD_SETUP
+ /* Call the board-specific fixup routine */
+ else if (strncmp(argv[1], "boa", 3) == 0) {
+ int err = ft_board_setup(working_fdt, gd->bd);
+
+ if (err) {
+ printf("Failed to update board information in FDT: %s\n",
+ fdt_strerror(err));
+ return CMD_RET_FAILURE;
+ }
+#ifdef CONFIG_SOC_KEYSTONE
+ ft_board_setup_ex(working_fdt, gd->bd);
+#endif
+ }
+#endif
+ /* Create a chosen node */
+ else if (strncmp(argv[1], "cho", 3) == 0) {
+ unsigned long initrd_start = 0, initrd_end = 0;
+
+ if ((argc != 2) && (argc != 4))
+ return CMD_RET_USAGE;
+
+ if (argc == 4) {
+ initrd_start = simple_strtoul(argv[2], NULL, 16);
+ initrd_end = simple_strtoul(argv[3], NULL, 16);
+ }
+
+ fdt_chosen(working_fdt);
+ fdt_initrd(working_fdt, initrd_start, initrd_end);
+
+#if defined(CONFIG_FIT_SIGNATURE)
+ } else if (strncmp(argv[1], "che", 3) == 0) {
+ int cfg_noffset;
+ int ret;
+ unsigned long addr;
+ struct fdt_header *blob;
+
+ if (!working_fdt)
+ return CMD_RET_FAILURE;
+
+ if (argc > 2) {
+ addr = simple_strtoul(argv[2], NULL, 16);
+ blob = map_sysmem(addr, 0);
+ } else {
+ blob = (struct fdt_header *)gd->fdt_blob;
+ }
+ if (!fdt_valid(&blob))
+ return 1;
+
+ gd->fdt_blob = blob;
+ cfg_noffset = fit_conf_get_node(working_fdt, NULL);
+ if (!cfg_noffset) {
+ printf("Could not find configuration node: %s\n",
+ fdt_strerror(cfg_noffset));
+ return CMD_RET_FAILURE;
+ }
+
+ ret = fit_config_verify(working_fdt, cfg_noffset);
+ if (ret == 0)
+ return CMD_RET_SUCCESS;
+ else
+ return CMD_RET_FAILURE;
+#endif
+
+ }
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+ /* apply an overlay */
+ else if (strncmp(argv[1], "ap", 2) == 0) {
+ unsigned long addr;
+ struct fdt_header *blob;
+ int ret;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ if (!working_fdt)
+ return CMD_RET_FAILURE;
+
+ addr = simple_strtoul(argv[2], NULL, 16);
+ blob = map_sysmem(addr, 0);
+ if (!fdt_valid(&blob))
+ return CMD_RET_FAILURE;
+
+ /* apply method prints messages on error */
+ ret = fdt_overlay_apply_verbose(working_fdt, blob);
+ if (ret)
+ return CMD_RET_FAILURE;
+ }
+#endif
+ /* resize the fdt */
+ else if (strncmp(argv[1], "re", 2) == 0) {
+ uint extrasize;
+ if (argc > 2)
+ extrasize = simple_strtoul(argv[2], NULL, 16);
+ else
+ extrasize = 0;
+ fdt_shrink_to_minimum(working_fdt, extrasize);
+ }
+ else {
+ /* Unrecognized command */
+ return CMD_RET_USAGE;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+
+/*
+ * Parse the user's input, partially heuristic. Valid formats:
+ * <0x00112233 4 05> - an array of cells. Numbers follow standard
+ * C conventions.
+ * [00 11 22 .. nn] - byte stream
+ * "string" - If the the value doesn't start with "<" or "[", it is
+ * treated as a string. Note that the quotes are
+ * stripped by the parser before we get the string.
+ * newval: An array of strings containing the new property as specified
+ * on the command line
+ * count: The number of strings in the array
+ * data: A bytestream to be placed in the property
+ * len: The length of the resulting bytestream
+ */
+static int fdt_parse_prop(char * const *newval, int count, char *data, int *len)
+{
+ char *cp; /* temporary char pointer */
+ char *newp; /* temporary newval char pointer */
+ unsigned long tmp; /* holds converted values */
+ int stridx = 0;
+
+ *len = 0;
+ newp = newval[0];
+
+ /* An array of cells */
+ if (*newp == '<') {
+ newp++;
+ while ((*newp != '>') && (stridx < count)) {
+ /*
+ * Keep searching until we find that last ">"
+ * That way users don't have to escape the spaces
+ */
+ if (*newp == '\0') {
+ newp = newval[++stridx];
+ continue;
+ }
+
+ cp = newp;
+ tmp = simple_strtoul(cp, &newp, 0);
+ if (*cp != '?')
+ *(fdt32_t *)data = cpu_to_fdt32(tmp);
+ else
+ newp++;
+
+ data += 4;
+ *len += 4;
+
+ /* If the ptr didn't advance, something went wrong */
+ if ((newp - cp) <= 0) {
+ printf("Sorry, I could not convert \"%s\"\n",
+ cp);
+ return 1;
+ }
+
+ while (*newp == ' ')
+ newp++;
+ }
+
+ if (*newp != '>') {
+ printf("Unexpected character '%c'\n", *newp);
+ return 1;
+ }
+ } else if (*newp == '[') {
+ /*
+ * Byte stream. Convert the values.
+ */
+ newp++;
+ while ((stridx < count) && (*newp != ']')) {
+ while (*newp == ' ')
+ newp++;
+ if (*newp == '\0') {
+ newp = newval[++stridx];
+ continue;
+ }
+ if (!isxdigit(*newp))
+ break;
+ tmp = simple_strtoul(newp, &newp, 16);
+ *data++ = tmp & 0xFF;
+ *len = *len + 1;
+ }
+ if (*newp != ']') {
+ printf("Unexpected character '%c'\n", *newp);
+ return 1;
+ }
+ } else {
+ /*
+ * Assume it is one or more strings. Copy it into our
+ * data area for convenience (including the
+ * terminating '\0's).
+ */
+ while (stridx < count) {
+ size_t length = strlen(newp) + 1;
+ strcpy(data, newp);
+ data += length;
+ *len += length;
+ newp = newval[++stridx];
+ }
+ }
+ return 0;
+}
+
+/****************************************************************************/
+
+/*
+ * Heuristic to guess if this is a string or concatenated strings.
+ */
+
+static int is_printable_string(const void *data, int len)
+{
+ const char *s = data;
+
+ /* zero length is not */
+ if (len == 0)
+ return 0;
+
+ /* must terminate with zero or '\n' */
+ if (s[len - 1] != '\0' && s[len - 1] != '\n')
+ return 0;
+
+ /* printable or a null byte (concatenated strings) */
+ while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) {
+ /*
+ * If we see a null, there are three possibilities:
+ * 1) If len == 1, it is the end of the string, printable
+ * 2) Next character also a null, not printable.
+ * 3) Next character not a null, continue to check.
+ */
+ if (s[0] == '\0') {
+ if (len == 1)
+ return 1;
+ if (s[1] == '\0')
+ return 0;
+ }
+ s++;
+ len--;
+ }
+
+ /* Not the null termination, or not done yet: not printable */
+ if (*s != '\0' || (len != 0))
+ return 0;
+
+ return 1;
+}
+
+
+/*
+ * Print the property in the best format, a heuristic guess. Print as
+ * a string, concatenated strings, a byte, word, double word, or (if all
+ * else fails) it is printed as a stream of bytes.
+ */
+static void print_data(const void *data, int len)
+{
+ int j;
+ const char *env_max_dump;
+ ulong max_dump = ULONG_MAX;
+
+ /* no data, don't print */
+ if (len == 0)
+ return;
+
+ env_max_dump = env_get("fdt_max_dump");
+ if (env_max_dump)
+ max_dump = simple_strtoul(env_max_dump, NULL, 16);
+
+ /*
+ * It is a string, but it may have multiple strings (embedded '\0's).
+ */
+ if (is_printable_string(data, len)) {
+ puts("\"");
+ j = 0;
+ while (j < len) {
+ if (j > 0)
+ puts("\", \"");
+ puts(data);
+ j += strlen(data) + 1;
+ data += strlen(data) + 1;
+ }
+ puts("\"");
+ return;
+ }
+
+ if ((len %4) == 0) {
+ if (len > max_dump)
+ printf("* 0x%p [0x%08x]", data, len);
+ else {
+ const __be32 *p;
+
+ printf("<");
+ for (j = 0, p = data; j < len/4; j++)
+ printf("0x%08x%s", fdt32_to_cpu(p[j]),
+ j < (len/4 - 1) ? " " : "");
+ printf(">");
+ }
+ } else { /* anything else... hexdump */
+ if (len > max_dump)
+ printf("* 0x%p [0x%08x]", data, len);
+ else {
+ const u8 *s;
+
+ printf("[");
+ for (j = 0, s = data; j < len; j++)
+ printf("%02x%s", s[j], j < len - 1 ? " " : "");
+ printf("]");
+ }
+ }
+}
+
+/****************************************************************************/
+
+/*
+ * Recursively print (a portion of) the working_fdt. The depth parameter
+ * determines how deeply nested the fdt is printed.
+ */
+static int fdt_print(const char *pathp, char *prop, int depth)
+{
+ static char tabs[MAX_LEVEL+1] =
+ "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
+ "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+ const void *nodep; /* property node pointer */
+ int nodeoffset; /* node offset from libfdt */
+ int nextoffset; /* next node offset from libfdt */
+ uint32_t tag; /* tag */
+ int len; /* length of the property */
+ int level = 0; /* keep track of nesting level */
+ const struct fdt_property *fdt_prop;
+
+ nodeoffset = fdt_path_offset (working_fdt, pathp);
+ if (nodeoffset < 0) {
+ /*
+ * Not found or something else bad happened.
+ */
+ printf ("libfdt fdt_path_offset() returned %s\n",
+ fdt_strerror(nodeoffset));
+ return 1;
+ }
+ /*
+ * The user passed in a property as well as node path.
+ * Print only the given property and then return.
+ */
+ if (prop) {
+ nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len);
+ if (len == 0) {
+ /* no property value */
+ printf("%s %s\n", pathp, prop);
+ return 0;
+ } else if (nodep && len > 0) {
+ printf("%s = ", prop);
+ print_data (nodep, len);
+ printf("\n");
+ return 0;
+ } else {
+ printf ("libfdt fdt_getprop(): %s\n",
+ fdt_strerror(len));
+ return 1;
+ }
+ }
+
+ /*
+ * The user passed in a node path and no property,
+ * print the node and all subnodes.
+ */
+ while(level >= 0) {
+ tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
+ switch(tag) {
+ case FDT_BEGIN_NODE:
+ pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
+ if (level <= depth) {
+ if (pathp == NULL)
+ pathp = "/* NULL pointer error */";
+ if (*pathp == '\0')
+ pathp = "/"; /* root is nameless */
+ printf("%s%s {\n",
+ &tabs[MAX_LEVEL - level], pathp);
+ }
+ level++;
+ if (level >= MAX_LEVEL) {
+ printf("Nested too deep, aborting.\n");
+ return 1;
+ }
+ break;
+ case FDT_END_NODE:
+ level--;
+ if (level <= depth)
+ printf("%s};\n", &tabs[MAX_LEVEL - level]);
+ if (level == 0) {
+ level = -1; /* exit the loop */
+ }
+ break;
+ case FDT_PROP:
+ fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
+ sizeof(*fdt_prop));
+ pathp = fdt_string(working_fdt,
+ fdt32_to_cpu(fdt_prop->nameoff));
+ len = fdt32_to_cpu(fdt_prop->len);
+ nodep = fdt_prop->data;
+ if (len < 0) {
+ printf ("libfdt fdt_getprop(): %s\n",
+ fdt_strerror(len));
+ return 1;
+ } else if (len == 0) {
+ /* the property has no value */
+ if (level <= depth)
+ printf("%s%s;\n",
+ &tabs[MAX_LEVEL - level],
+ pathp);
+ } else {
+ if (level <= depth) {
+ printf("%s%s = ",
+ &tabs[MAX_LEVEL - level],
+ pathp);
+ print_data (nodep, len);
+ printf(";\n");
+ }
+ }
+ break;
+ case FDT_NOP:
+ printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
+ break;
+ case FDT_END:
+ return 1;
+ default:
+ if (level <= depth)
+ printf("Unknown tag 0x%08X\n", tag);
+ return 1;
+ }
+ nodeoffset = nextoffset;
+ }
+ return 0;
+}
+
+/********************************************************************/
+#ifdef CONFIG_SYS_LONGHELP
+static char fdt_help_text[] =
+ "addr [-c] <addr> [<length>] - Set the [control] fdt location to <addr>\n"
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+ "fdt apply <addr> - Apply overlay to the DT\n"
+#endif
+#ifdef CONFIG_OF_BOARD_SETUP
+ "fdt boardsetup - Do board-specific set up\n"
+#endif
+#ifdef CONFIG_OF_SYSTEM_SETUP
+ "fdt systemsetup - Do system-specific set up\n"
+#endif
+ "fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n"
+ "fdt resize [<extrasize>] - Resize fdt to size + padding to 4k addr + some optional <extrasize> if needed\n"
+ "fdt print <path> [<prop>] - Recursive print starting at <path>\n"
+ "fdt list <path> [<prop>] - Print one level starting at <path>\n"
+ "fdt get value <var> <path> <prop> - Get <property> and store in <var>\n"
+ "fdt get name <var> <path> <index> - Get name of node <index> and store in <var>\n"
+ "fdt get addr <var> <path> <prop> - Get start address of <property> and store in <var>\n"
+ "fdt get size <var> <path> [<prop>] - Get size of [<property>] or num nodes and store in <var>\n"
+ "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n"
+ "fdt mknode <path> <node> - Create a new node after <path>\n"
+ "fdt rm <path> [<prop>] - Delete the node or <property>\n"
+ "fdt header [get <var> <member>] - Display header info\n"
+ " get - get header member <member> and store it in <var>\n"
+ "fdt bootcpu <id> - Set boot cpuid\n"
+ "fdt memory <addr> <size> - Add/Update memory node\n"
+ "fdt rsvmem print - Show current mem reserves\n"
+ "fdt rsvmem add <addr> <size> - Add a mem reserve\n"
+ "fdt rsvmem delete <index> - Delete a mem reserves\n"
+ "fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n"
+ " <start>/<end> - initrd start/end addr\n"
+#if defined(CONFIG_FIT_SIGNATURE)
+ "fdt checksign [<addr>] - check FIT signature\n"
+ " <start> - addr of key blob\n"
+ " default gd->fdt_blob\n"
+#endif
+ "NOTE: Dereference aliases by omitting the leading '/', "
+ "e.g. fdt print ethernet0.";
+#endif
+
+U_BOOT_CMD(
+ fdt, 255, 0, do_fdt,
+ "flattened device tree utility commands", fdt_help_text
+);
diff --git a/roms/u-boot/cmd/flash.c b/roms/u-boot/cmd/flash.c
new file mode 100644
index 000000000..240871e80
--- /dev/null
+++ b/roms/u-boot/cmd/flash.c
@@ -0,0 +1,705 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * FLASH support
+ */
+#include <common.h>
+#include <command.h>
+#include <log.h>
+#include <uuid.h>
+
+#if defined(CONFIG_CMD_MTDPARTS)
+#include <jffs2/jffs2.h>
+
+/* partition handling routines */
+int mtdparts_init(void);
+int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
+int find_dev_and_part(const char *id, struct mtd_device **dev,
+ u8 *part_num, struct part_info **part);
+#endif
+
+#ifdef CONFIG_MTD_NOR_FLASH
+#include <flash.h>
+#include <mtd/cfi_flash.h>
+extern flash_info_t flash_info[]; /* info for FLASH chips */
+
+/*
+ * The user interface starts numbering for Flash banks with 1
+ * for historical reasons.
+ */
+
+/*
+ * this routine looks for an abbreviated flash range specification.
+ * the syntax is B:SF[-SL], where B is the bank number, SF is the first
+ * sector to erase, and SL is the last sector to erase (defaults to SF).
+ * bank numbers start at 1 to be consistent with other specs, sector numbers
+ * start at zero.
+ *
+ * returns: 1 - correct spec; *pinfo, *psf and *psl are
+ * set appropriately
+ * 0 - doesn't look like an abbreviated spec
+ * -1 - looks like an abbreviated spec, but got
+ * a parsing error, a number out of range,
+ * or an invalid flash bank.
+ */
+static int
+abbrev_spec (char *str, flash_info_t ** pinfo, int *psf, int *psl)
+{
+ flash_info_t *fp;
+ int bank, first, last;
+ char *p, *ep;
+
+ if ((p = strchr (str, ':')) == NULL)
+ return 0;
+ *p++ = '\0';
+
+ bank = simple_strtoul (str, &ep, 10);
+ if (ep == str || *ep != '\0' ||
+ bank < 1 || bank > CONFIG_SYS_MAX_FLASH_BANKS ||
+ (fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
+ return -1;
+
+ str = p;
+ if ((p = strchr (str, '-')) != NULL)
+ *p++ = '\0';
+
+ first = simple_strtoul (str, &ep, 10);
+ if (ep == str || *ep != '\0' || first >= fp->sector_count)
+ return -1;
+
+ if (p != NULL) {
+ last = simple_strtoul (p, &ep, 10);
+ if (ep == p || *ep != '\0' ||
+ last < first || last >= fp->sector_count)
+ return -1;
+ } else {
+ last = first;
+ }
+
+ *pinfo = fp;
+ *psf = first;
+ *psl = last;
+
+ return 1;
+}
+
+/*
+ * Take *addr in Flash and adjust it to fall on the end of its sector
+ */
+int flash_sect_roundb(ulong *addr)
+{
+ flash_info_t *info;
+ ulong bank, sector_end_addr;
+ char found;
+ int i;
+
+ /* find the end addr of the sector where the *addr is */
+ found = 0;
+ for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS && !found; ++bank) {
+ info = &flash_info[bank];
+ for (i = 0; i < info->sector_count && !found; ++i) {
+ /* get the end address of the sector */
+ if (i == info->sector_count - 1) {
+ sector_end_addr = info->start[0] +
+ info->size - 1;
+ } else {
+ sector_end_addr = info->start[i+1] - 1;
+ }
+
+ if (*addr <= sector_end_addr &&
+ *addr >= info->start[i]) {
+ found = 1;
+ /* adjust *addr if necessary */
+ if (*addr < sector_end_addr)
+ *addr = sector_end_addr;
+ } /* sector */
+ } /* bank */
+ }
+ if (!found) {
+ /* error, address not in flash */
+ printf("Error: end address (0x%08lx) not in flash!\n", *addr);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * This function computes the start and end addresses for both
+ * erase and protect commands. The range of the addresses on which
+ * either of the commands is to operate can be given in two forms:
+ * 1. <cmd> start end - operate on <'start', 'end')
+ * 2. <cmd> start +length - operate on <'start', start + length)
+ * If the second form is used and the end address doesn't fall on the
+ * sector boundary, than it will be adjusted to the next sector boundary.
+ * If it isn't in the flash, the function will fail (return -1).
+ * Input:
+ * arg1, arg2: address specification (i.e. both command arguments)
+ * Output:
+ * addr_first, addr_last: computed address range
+ * Return:
+ * 1: success
+ * -1: failure (bad format, bad address).
+*/
+static int
+addr_spec(char *arg1, char *arg2, ulong *addr_first, ulong *addr_last)
+{
+ char *ep;
+ char len_used; /* indicates if the "start +length" form used */
+
+ *addr_first = simple_strtoul(arg1, &ep, 16);
+ if (ep == arg1 || *ep != '\0')
+ return -1;
+
+ len_used = 0;
+ if (arg2 && *arg2 == '+'){
+ len_used = 1;
+ ++arg2;
+ }
+
+ *addr_last = simple_strtoul(arg2, &ep, 16);
+ if (ep == arg2 || *ep != '\0')
+ return -1;
+
+ if (len_used){
+ /*
+ * *addr_last has the length, compute correct *addr_last
+ * XXX watch out for the integer overflow! Right now it is
+ * checked for in both the callers.
+ */
+ *addr_last = *addr_first + *addr_last - 1;
+
+ /*
+ * It may happen that *addr_last doesn't fall on the sector
+ * boundary. We want to round such an address to the next
+ * sector boundary, so that the commands don't fail later on.
+ */
+
+ if (flash_sect_roundb(addr_last) > 0)
+ return -1;
+ } /* "start +length" from used */
+
+ return 1;
+}
+
+static int
+flash_fill_sect_ranges (ulong addr_first, ulong addr_last,
+ int *s_first, int *s_last,
+ int *s_count )
+{
+ flash_info_t *info;
+ ulong bank;
+ int rcode = 0;
+
+ *s_count = 0;
+
+ for (bank=0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
+ s_first[bank] = -1; /* first sector to erase */
+ s_last [bank] = -1; /* last sector to erase */
+ }
+
+ for (bank=0,info = &flash_info[0];
+ (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (addr_first <= addr_last);
+ ++bank, ++info) {
+ ulong b_end;
+ int sect;
+ short s_end;
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ continue;
+ }
+
+ b_end = info->start[0] + info->size - 1; /* bank end addr */
+ s_end = info->sector_count - 1; /* last sector */
+
+
+ for (sect=0; sect < info->sector_count; ++sect) {
+ ulong end; /* last address in current sect */
+
+ end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
+
+ if (addr_first > end)
+ continue;
+ if (addr_last < info->start[sect])
+ continue;
+
+ if (addr_first == info->start[sect]) {
+ s_first[bank] = sect;
+ }
+ if (addr_last == end) {
+ s_last[bank] = sect;
+ }
+ }
+ if (s_first[bank] >= 0) {
+ if (s_last[bank] < 0) {
+ if (addr_last > b_end) {
+ s_last[bank] = s_end;
+ } else {
+ puts ("Error: end address"
+ " not on sector boundary\n");
+ rcode = 1;
+ break;
+ }
+ }
+ if (s_last[bank] < s_first[bank]) {
+ puts ("Error: end sector"
+ " precedes start sector\n");
+ rcode = 1;
+ break;
+ }
+ sect = s_last[bank];
+ addr_first = (sect == s_end) ? b_end + 1: info->start[sect + 1];
+ (*s_count) += s_last[bank] - s_first[bank] + 1;
+ } else if (addr_first >= info->start[0] && addr_first < b_end) {
+ puts ("Error: start address not on sector boundary\n");
+ rcode = 1;
+ break;
+ } else if (s_last[bank] >= 0) {
+ puts ("Error: cannot span across banks when they are"
+ " mapped in reverse order\n");
+ rcode = 1;
+ break;
+ }
+ }
+
+ return rcode;
+}
+#endif /* CONFIG_MTD_NOR_FLASH */
+
+static int do_flinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+#ifdef CONFIG_MTD_NOR_FLASH
+ ulong bank;
+#endif
+
+#ifdef CONFIG_MTD_NOR_FLASH
+ if (argc == 1) { /* print info for all FLASH banks */
+ for (bank=0; bank <CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
+ printf ("\nBank # %ld: ", bank+1);
+
+ flash_print_info(&flash_info[bank]);
+ }
+ return 0;
+ }
+
+ bank = simple_strtoul(argv[1], NULL, 16);
+ if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
+ printf ("Only FLASH Banks # 1 ... # %d supported\n",
+ CONFIG_SYS_MAX_FLASH_BANKS);
+ return 1;
+ }
+ printf ("\nBank # %ld: ", bank);
+ flash_print_info(&flash_info[bank - 1]);
+#endif /* CONFIG_MTD_NOR_FLASH */
+ return 0;
+}
+
+static int do_flerase(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+#ifdef CONFIG_MTD_NOR_FLASH
+ flash_info_t *info = NULL;
+ ulong bank, addr_first, addr_last;
+ int n, sect_first = 0, sect_last = 0;
+#if defined(CONFIG_CMD_MTDPARTS)
+ struct mtd_device *dev;
+ struct part_info *part;
+ u8 dev_type, dev_num, pnum;
+#endif
+ int rcode = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "all") == 0) {
+ for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
+ printf ("Erase Flash Bank # %ld ", bank);
+ info = &flash_info[bank-1];
+ rcode = flash_erase(info, 0, info->sector_count - 1);
+ }
+ return rcode;
+ }
+
+ if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
+ if (n < 0) {
+ puts ("Bad sector specification\n");
+ return 1;
+ }
+ printf ("Erase Flash Sectors %d-%d in Bank # %zu ",
+ sect_first, sect_last, (info-flash_info)+1);
+ rcode = flash_erase(info, sect_first, sect_last);
+ return rcode;
+ }
+
+#if defined(CONFIG_CMD_MTDPARTS)
+ /* erase <part-id> - erase partition */
+ if ((argc == 2) && (mtd_id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
+ mtdparts_init();
+ if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) {
+ if (dev->id->type == MTD_DEV_TYPE_NOR) {
+ bank = dev->id->num;
+ info = &flash_info[bank];
+ addr_first = part->offset + info->start[0];
+ addr_last = addr_first + part->size - 1;
+
+ printf ("Erase Flash Partition %s, "
+ "bank %ld, 0x%08lx - 0x%08lx ",
+ argv[1], bank, addr_first,
+ addr_last);
+
+ rcode = flash_sect_erase(addr_first, addr_last);
+ return rcode;
+ }
+
+ printf("cannot erase, not a NOR device\n");
+ return 1;
+ }
+ }
+#endif
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "bank") == 0) {
+ bank = simple_strtoul(argv[2], NULL, 16);
+ if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
+ printf ("Only FLASH Banks # 1 ... # %d supported\n",
+ CONFIG_SYS_MAX_FLASH_BANKS);
+ return 1;
+ }
+ printf ("Erase Flash Bank # %ld ", bank);
+ info = &flash_info[bank-1];
+ rcode = flash_erase(info, 0, info->sector_count - 1);
+ return rcode;
+ }
+
+ if (addr_spec(argv[1], argv[2], &addr_first, &addr_last) < 0){
+ printf ("Bad address format\n");
+ return 1;
+ }
+
+ if (addr_first >= addr_last)
+ return CMD_RET_USAGE;
+
+ rcode = flash_sect_erase(addr_first, addr_last);
+ return rcode;
+#else
+ return 0;
+#endif /* CONFIG_MTD_NOR_FLASH */
+}
+
+#ifdef CONFIG_MTD_NOR_FLASH
+int flash_sect_erase(ulong addr_first, ulong addr_last)
+{
+ flash_info_t *info;
+ ulong bank;
+ int s_first[CONFIG_SYS_MAX_FLASH_BANKS], s_last[CONFIG_SYS_MAX_FLASH_BANKS];
+ int erased = 0;
+ int planned;
+ int rcode = 0;
+
+ rcode = flash_fill_sect_ranges (addr_first, addr_last,
+ s_first, s_last, &planned );
+
+ if (planned && (rcode == 0)) {
+ for (bank=0,info = &flash_info[0];
+ (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (rcode == 0);
+ ++bank, ++info) {
+ if (s_first[bank]>=0) {
+ erased += s_last[bank] - s_first[bank] + 1;
+ debug("Erase Flash from 0x%08lx to 0x%08lx in Bank # %ld ",
+ info->start[s_first[bank]],
+ (s_last[bank] == info->sector_count) ?
+ info->start[0] + info->size - 1 :
+ info->start[s_last[bank] + 1] - 1,
+ bank + 1);
+ rcode = flash_erase(info, s_first[bank],
+ s_last[bank]);
+ }
+ }
+ if (rcode == 0)
+ printf("Erased %d sectors\n", erased);
+ } else if (rcode == 0) {
+ puts ("Error: start and/or end address"
+ " not on sector boundary\n");
+ rcode = 1;
+ }
+ return rcode;
+}
+#endif /* CONFIG_MTD_NOR_FLASH */
+
+static int do_protect(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int rcode = 0;
+#ifdef CONFIG_MTD_NOR_FLASH
+ flash_info_t *info = NULL;
+ ulong bank;
+ int i, n, sect_first = 0, sect_last = 0;
+#if defined(CONFIG_CMD_MTDPARTS)
+ struct mtd_device *dev;
+ struct part_info *part;
+ u8 dev_type, dev_num, pnum;
+#endif
+#endif /* CONFIG_MTD_NOR_FLASH */
+#if defined(CONFIG_MTD_NOR_FLASH)
+ int p;
+ ulong addr_first, addr_last;
+#endif
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+#if defined(CONFIG_MTD_NOR_FLASH)
+ if (strcmp(argv[1], "off") == 0)
+ p = 0;
+ else if (strcmp(argv[1], "on") == 0)
+ p = 1;
+ else
+ return CMD_RET_USAGE;
+#endif
+
+#ifdef CONFIG_MTD_NOR_FLASH
+ if (strcmp(argv[2], "all") == 0) {
+ for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
+ info = &flash_info[bank-1];
+ if (info->flash_id == FLASH_UNKNOWN) {
+ continue;
+ }
+ printf ("%sProtect Flash Bank # %ld\n",
+ p ? "" : "Un-", bank);
+
+ for (i=0; i<info->sector_count; ++i) {
+#if defined(CONFIG_SYS_FLASH_PROTECTION)
+ if (flash_real_protect(info, i, p))
+ rcode = 1;
+ putc ('.');
+#else
+ info->protect[i] = p;
+#endif /* CONFIG_SYS_FLASH_PROTECTION */
+ }
+#if defined(CONFIG_SYS_FLASH_PROTECTION)
+ if (!rcode) puts (" done\n");
+#endif /* CONFIG_SYS_FLASH_PROTECTION */
+ }
+ return rcode;
+ }
+
+ if ((n = abbrev_spec(argv[2], &info, &sect_first, &sect_last)) != 0) {
+ if (n < 0) {
+ puts ("Bad sector specification\n");
+ return 1;
+ }
+ printf("%sProtect Flash Sectors %d-%d in Bank # %zu\n",
+ p ? "" : "Un-", sect_first, sect_last,
+ (info-flash_info)+1);
+ for (i = sect_first; i <= sect_last; i++) {
+#if defined(CONFIG_SYS_FLASH_PROTECTION)
+ if (flash_real_protect(info, i, p))
+ rcode = 1;
+ putc ('.');
+#else
+ info->protect[i] = p;
+#endif /* CONFIG_SYS_FLASH_PROTECTION */
+ }
+
+#if defined(CONFIG_SYS_FLASH_PROTECTION)
+ if (!rcode) puts (" done\n");
+#endif /* CONFIG_SYS_FLASH_PROTECTION */
+
+ return rcode;
+ }
+
+#if defined(CONFIG_CMD_MTDPARTS)
+ /* protect on/off <part-id> */
+ if ((argc == 3) && (mtd_id_parse(argv[2], NULL, &dev_type, &dev_num) == 0)) {
+ mtdparts_init();
+ if (find_dev_and_part(argv[2], &dev, &pnum, &part) == 0) {
+ if (dev->id->type == MTD_DEV_TYPE_NOR) {
+ bank = dev->id->num;
+ info = &flash_info[bank];
+ addr_first = part->offset + info->start[0];
+ addr_last = addr_first + part->size - 1;
+
+ printf ("%sProtect Flash Partition %s, "
+ "bank %ld, 0x%08lx - 0x%08lx\n",
+ p ? "" : "Un", argv[1],
+ bank, addr_first, addr_last);
+
+ rcode = flash_sect_protect(p, addr_first,
+ addr_last);
+ return rcode;
+ }
+
+ printf("cannot %sprotect, not a NOR device\n",
+ p ? "" : "un");
+ return 1;
+ }
+ }
+#endif
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[2], "bank") == 0) {
+ bank = simple_strtoul(argv[3], NULL, 16);
+ if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
+ printf ("Only FLASH Banks # 1 ... # %d supported\n",
+ CONFIG_SYS_MAX_FLASH_BANKS);
+ return 1;
+ }
+ printf ("%sProtect Flash Bank # %ld\n",
+ p ? "" : "Un-", bank);
+ info = &flash_info[bank-1];
+
+ if (info->flash_id == FLASH_UNKNOWN) {
+ puts ("missing or unknown FLASH type\n");
+ return 1;
+ }
+ for (i=0; i<info->sector_count; ++i) {
+#if defined(CONFIG_SYS_FLASH_PROTECTION)
+ if (flash_real_protect(info, i, p))
+ rcode = 1;
+ putc ('.');
+#else
+ info->protect[i] = p;
+#endif /* CONFIG_SYS_FLASH_PROTECTION */
+ }
+
+#if defined(CONFIG_SYS_FLASH_PROTECTION)
+ if (!rcode) puts (" done\n");
+#endif /* CONFIG_SYS_FLASH_PROTECTION */
+
+ return rcode;
+ }
+
+ if (addr_spec(argv[2], argv[3], &addr_first, &addr_last) < 0){
+ printf("Bad address format\n");
+ return 1;
+ }
+
+ if (addr_first >= addr_last)
+ return CMD_RET_USAGE;
+
+ rcode = flash_sect_protect(p, addr_first, addr_last);
+#endif /* CONFIG_MTD_NOR_FLASH */
+ return rcode;
+}
+
+#ifdef CONFIG_MTD_NOR_FLASH
+int flash_sect_protect(int p, ulong addr_first, ulong addr_last)
+{
+ flash_info_t *info;
+ ulong bank;
+ int s_first[CONFIG_SYS_MAX_FLASH_BANKS], s_last[CONFIG_SYS_MAX_FLASH_BANKS];
+ int protected, i;
+ int planned;
+ int rcode;
+
+ rcode = flash_fill_sect_ranges( addr_first, addr_last, s_first, s_last, &planned );
+
+ protected = 0;
+
+ if (planned && (rcode == 0)) {
+ for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
+ if (info->flash_id == FLASH_UNKNOWN) {
+ continue;
+ }
+
+ if (s_first[bank]>=0 && s_first[bank]<=s_last[bank]) {
+ debug("%sProtecting sectors %d..%d in bank %ld\n",
+ p ? "" : "Un-", s_first[bank],
+ s_last[bank], bank + 1);
+ protected += s_last[bank] - s_first[bank] + 1;
+ for (i=s_first[bank]; i<=s_last[bank]; ++i) {
+#if defined(CONFIG_SYS_FLASH_PROTECTION)
+ if (flash_real_protect(info, i, p))
+ rcode = 1;
+ putc ('.');
+#else
+ info->protect[i] = p;
+#endif /* CONFIG_SYS_FLASH_PROTECTION */
+ }
+ }
+ }
+#if defined(CONFIG_SYS_FLASH_PROTECTION)
+ puts (" done\n");
+#endif /* CONFIG_SYS_FLASH_PROTECTION */
+
+ printf ("%sProtected %d sectors\n",
+ p ? "" : "Un-", protected);
+ } else if (rcode == 0) {
+ puts ("Error: start and/or end address"
+ " not on sector boundary\n");
+ rcode = 1;
+ }
+ return rcode;
+}
+#endif /* CONFIG_MTD_NOR_FLASH */
+
+
+/**************************************************/
+#if defined(CONFIG_CMD_MTDPARTS)
+# define TMP_ERASE "erase <part-id>\n - erase partition\n"
+# define TMP_PROT_ON "protect on <part-id>\n - protect partition\n"
+# define TMP_PROT_OFF "protect off <part-id>\n - make partition writable\n"
+#else
+# define TMP_ERASE /* empty */
+# define TMP_PROT_ON /* empty */
+# define TMP_PROT_OFF /* empty */
+#endif
+
+U_BOOT_CMD(
+ flinfo, 2, 1, do_flinfo,
+ "print FLASH memory information",
+ "\n - print information for all FLASH memory banks\n"
+ "flinfo N\n - print information for FLASH memory bank # N"
+);
+
+U_BOOT_CMD(
+ erase, 3, 0, do_flerase,
+ "erase FLASH memory",
+ "start end\n"
+ " - erase FLASH from addr 'start' to addr 'end'\n"
+ "erase start +len\n"
+ " - erase FLASH from addr 'start' to the end of sect "
+ "w/addr 'start'+'len'-1\n"
+ "erase N:SF[-SL]\n - erase sectors SF-SL in FLASH bank # N\n"
+ "erase bank N\n - erase FLASH bank # N\n"
+ TMP_ERASE
+ "erase all\n - erase all FLASH banks"
+);
+
+U_BOOT_CMD(
+ protect, 4, 0, do_protect,
+ "enable or disable FLASH write protection",
+ "on start end\n"
+ " - protect FLASH from addr 'start' to addr 'end'\n"
+ "protect on start +len\n"
+ " - protect FLASH from addr 'start' to end of sect "
+ "w/addr 'start'+'len'-1\n"
+ "protect on N:SF[-SL]\n"
+ " - protect sectors SF-SL in FLASH bank # N\n"
+ "protect on bank N\n - protect FLASH bank # N\n"
+ TMP_PROT_ON
+ "protect on all\n - protect all FLASH banks\n"
+ "protect off start end\n"
+ " - make FLASH from addr 'start' to addr 'end' writable\n"
+ "protect off start +len\n"
+ " - make FLASH from addr 'start' to end of sect "
+ "w/addr 'start'+'len'-1 wrtable\n"
+ "protect off N:SF[-SL]\n"
+ " - make sectors SF-SL writable in FLASH bank # N\n"
+ "protect off bank N\n - make FLASH bank # N writable\n"
+ TMP_PROT_OFF
+ "protect off all\n - make all FLASH banks writable"
+);
+
+#undef TMP_ERASE
+#undef TMP_PROT_ON
+#undef TMP_PROT_OFF
diff --git a/roms/u-boot/cmd/fpga.c b/roms/u-boot/cmd/fpga.c
new file mode 100644
index 000000000..51410a8e4
--- /dev/null
+++ b/roms/u-boot/cmd/fpga.c
@@ -0,0 +1,469 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000, 2001
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ */
+
+/*
+ * FPGA support
+ */
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <fpga.h>
+#include <fs.h>
+#include <gzip.h>
+#include <image.h>
+#include <log.h>
+#include <malloc.h>
+
+static long do_fpga_get_device(char *arg)
+{
+ long dev = FPGA_INVALID_DEVICE;
+ char *devstr = env_get("fpga");
+
+ if (devstr)
+ /* Should be strtol to handle -1 cases */
+ dev = simple_strtol(devstr, NULL, 16);
+
+ if (dev == FPGA_INVALID_DEVICE && arg)
+ dev = simple_strtol(arg, NULL, 16);
+
+ debug("%s: device = %ld\n", __func__, dev);
+
+ return dev;
+}
+
+static int do_fpga_check_params(long *dev, long *fpga_data, size_t *data_size,
+ struct cmd_tbl *cmdtp, int argc,
+ char *const argv[])
+{
+ size_t local_data_size;
+ long local_fpga_data;
+
+ debug("%s %d, %d\n", __func__, argc, cmdtp->maxargs);
+
+ if (argc != cmdtp->maxargs) {
+ debug("fpga: incorrect parameters passed\n");
+ return CMD_RET_USAGE;
+ }
+
+ *dev = do_fpga_get_device(argv[0]);
+
+ local_fpga_data = simple_strtol(argv[1], NULL, 16);
+ if (!local_fpga_data) {
+ debug("fpga: zero fpga_data address\n");
+ return CMD_RET_USAGE;
+ }
+ *fpga_data = local_fpga_data;
+
+ local_data_size = simple_strtoul(argv[2], NULL, 16);
+ if (!local_data_size) {
+ debug("fpga: zero size\n");
+ return CMD_RET_USAGE;
+ }
+ *data_size = local_data_size;
+
+ return 0;
+}
+
+#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
+int do_fpga_loads(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ size_t data_size = 0;
+ long fpga_data, dev;
+ int ret;
+ struct fpga_secure_info fpga_sec_info;
+
+ memset(&fpga_sec_info, 0, sizeof(fpga_sec_info));
+
+ if (argc < 5) {
+ debug("fpga: incorrect parameters passed\n");
+ return CMD_RET_USAGE;
+ }
+
+ if (argc == 6)
+ fpga_sec_info.userkey_addr = (u8 *)(uintptr_t)
+ simple_strtoull(argv[5],
+ NULL, 16);
+ else
+ /*
+ * If 6th parameter is not passed then do_fpga_check_params
+ * will get 5 instead of expected 6 which means that function
+ * return CMD_RET_USAGE. Increase number of params +1 to pass
+ * this.
+ */
+ argc++;
+
+ fpga_sec_info.encflag = (u8)simple_strtoul(argv[4], NULL, 16);
+ fpga_sec_info.authflag = (u8)simple_strtoul(argv[3], NULL, 16);
+
+ if (fpga_sec_info.authflag >= FPGA_NO_ENC_OR_NO_AUTH &&
+ fpga_sec_info.encflag >= FPGA_NO_ENC_OR_NO_AUTH) {
+ debug("fpga: Use <fpga load> for NonSecure bitstream\n");
+ return CMD_RET_USAGE;
+ }
+
+ if (fpga_sec_info.encflag == FPGA_ENC_USR_KEY &&
+ !fpga_sec_info.userkey_addr) {
+ debug("fpga: User key not provided\n");
+ return CMD_RET_USAGE;
+ }
+
+ ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
+ cmdtp, argc, argv);
+ if (ret)
+ return ret;
+
+ return fpga_loads(dev, (void *)fpga_data, data_size, &fpga_sec_info);
+}
+#endif
+
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+static int do_fpga_loadfs(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ size_t data_size = 0;
+ long fpga_data, dev;
+ int ret;
+ fpga_fs_info fpga_fsinfo;
+
+ ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
+ cmdtp, argc, argv);
+ if (ret)
+ return ret;
+
+ fpga_fsinfo.fstype = FS_TYPE_ANY;
+ fpga_fsinfo.blocksize = (unsigned int)simple_strtoul(argv[3], NULL, 16);
+ fpga_fsinfo.interface = argv[4];
+ fpga_fsinfo.dev_part = argv[5];
+ fpga_fsinfo.filename = argv[6];
+
+ return fpga_fsload(dev, (void *)fpga_data, data_size, &fpga_fsinfo);
+}
+#endif
+
+static int do_fpga_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ long dev = do_fpga_get_device(argv[0]);
+
+ return fpga_info(dev);
+}
+
+static int do_fpga_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ size_t data_size = 0;
+ long fpga_data, dev;
+ int ret;
+
+ ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
+ cmdtp, argc, argv);
+ if (ret)
+ return ret;
+
+ return fpga_dump(dev, (void *)fpga_data, data_size);
+}
+
+static int do_fpga_load(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ size_t data_size = 0;
+ long fpga_data, dev;
+ int ret;
+
+ ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
+ cmdtp, argc, argv);
+ if (ret)
+ return ret;
+
+ return fpga_load(dev, (void *)fpga_data, data_size, BIT_FULL);
+}
+
+static int do_fpga_loadb(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ size_t data_size = 0;
+ long fpga_data, dev;
+ int ret;
+
+ ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
+ cmdtp, argc, argv);
+ if (ret)
+ return ret;
+
+ return fpga_loadbitstream(dev, (void *)fpga_data, data_size, BIT_FULL);
+}
+
+#if defined(CONFIG_CMD_FPGA_LOADP)
+static int do_fpga_loadp(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ size_t data_size = 0;
+ long fpga_data, dev;
+ int ret;
+
+ ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
+ cmdtp, argc, argv);
+ if (ret)
+ return ret;
+
+ return fpga_load(dev, (void *)fpga_data, data_size, BIT_PARTIAL);
+}
+#endif
+
+#if defined(CONFIG_CMD_FPGA_LOADBP)
+static int do_fpga_loadbp(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ size_t data_size = 0;
+ long fpga_data, dev;
+ int ret;
+
+ ret = do_fpga_check_params(&dev, &fpga_data, &data_size,
+ cmdtp, argc, argv);
+ if (ret)
+ return ret;
+
+ return fpga_loadbitstream(dev, (void *)fpga_data, data_size,
+ BIT_PARTIAL);
+}
+#endif
+
+#if defined(CONFIG_CMD_FPGA_LOADMK)
+static int do_fpga_loadmk(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ size_t data_size = 0;
+ void *fpga_data = NULL;
+#if defined(CONFIG_FIT)
+ const char *fit_uname = NULL;
+ ulong fit_addr;
+#endif
+ ulong dev = do_fpga_get_device(argv[0]);
+ char *datastr = env_get("fpgadata");
+
+ debug("fpga: argc %x, dev %lx, datastr %s\n", argc, dev, datastr);
+
+ if (dev == FPGA_INVALID_DEVICE) {
+ debug("fpga: Invalid fpga device\n");
+ return CMD_RET_USAGE;
+ }
+
+ if (argc == 0 && !datastr) {
+ debug("fpga: No datastr passed\n");
+ return CMD_RET_USAGE;
+ }
+
+ if (argc == 2) {
+ datastr = argv[1];
+ debug("fpga: Full command with two args\n");
+ } else if (argc == 1 && !datastr) {
+ debug("fpga: Dev is setup - fpgadata passed\n");
+ datastr = argv[0];
+ }
+
+#if defined(CONFIG_FIT)
+ if (fit_parse_subimage(datastr, (ulong)fpga_data,
+ &fit_addr, &fit_uname)) {
+ fpga_data = (void *)fit_addr;
+ debug("* fpga: subimage '%s' from FIT image ",
+ fit_uname);
+ debug("at 0x%08lx\n", fit_addr);
+ } else
+#endif
+ {
+ fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
+ debug("* fpga: cmdline image address = 0x%08lx\n",
+ (ulong)fpga_data);
+ }
+ debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data);
+ if (!fpga_data) {
+ puts("Zero fpga_data address\n");
+ return CMD_RET_USAGE;
+ }
+
+ switch (genimg_get_format(fpga_data)) {
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ case IMAGE_FORMAT_LEGACY:
+ {
+ image_header_t *hdr = (image_header_t *)fpga_data;
+ ulong data;
+ u8 comp;
+
+ comp = image_get_comp(hdr);
+ if (comp == IH_COMP_GZIP) {
+#if defined(CONFIG_GZIP)
+ ulong image_buf = image_get_data(hdr);
+ ulong image_size = ~0UL;
+
+ data = image_get_load(hdr);
+
+ if (gunzip((void *)data, ~0UL, (void *)image_buf,
+ &image_size) != 0) {
+ puts("GUNZIP: error\n");
+ return CMD_RET_FAILURE;
+ }
+ data_size = image_size;
+#else
+ puts("Gunzip image is not supported\n");
+ return 1;
+#endif
+ } else {
+ data = (ulong)image_get_data(hdr);
+ data_size = image_get_data_size(hdr);
+ }
+ return fpga_load(dev, (void *)data, data_size,
+ BIT_FULL);
+ }
+#endif
+#if defined(CONFIG_FIT)
+ case IMAGE_FORMAT_FIT:
+ {
+ const void *fit_hdr = (const void *)fpga_data;
+ int noffset;
+ const void *fit_data;
+
+ if (!fit_uname) {
+ puts("No FIT subimage unit name\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
+ puts("Bad FIT image format\n");
+ return CMD_RET_FAILURE;
+ }
+
+ /* get fpga component image node offset */
+ noffset = fit_image_get_node(fit_hdr, fit_uname);
+ if (noffset < 0) {
+ printf("Can't find '%s' FIT subimage\n", fit_uname);
+ return CMD_RET_FAILURE;
+ }
+
+ /* verify integrity */
+ if (!fit_image_verify(fit_hdr, noffset)) {
+ puts("Bad Data Hash\n");
+ return CMD_RET_FAILURE;
+ }
+
+ /* get fpga subimage/external data address and length */
+ if (fit_image_get_data_and_size(fit_hdr, noffset,
+ &fit_data, &data_size)) {
+ puts("Fpga subimage data not found\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return fpga_load(dev, fit_data, data_size, BIT_FULL);
+ }
+#endif
+ default:
+ puts("** Unknown image type\n");
+ return CMD_RET_FAILURE;
+ }
+}
+#endif
+
+static struct cmd_tbl fpga_commands[] = {
+ U_BOOT_CMD_MKENT(info, 1, 1, do_fpga_info, "", ""),
+ U_BOOT_CMD_MKENT(dump, 3, 1, do_fpga_dump, "", ""),
+ U_BOOT_CMD_MKENT(load, 3, 1, do_fpga_load, "", ""),
+ U_BOOT_CMD_MKENT(loadb, 3, 1, do_fpga_loadb, "", ""),
+#if defined(CONFIG_CMD_FPGA_LOADP)
+ U_BOOT_CMD_MKENT(loadp, 3, 1, do_fpga_loadp, "", ""),
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADBP)
+ U_BOOT_CMD_MKENT(loadbp, 3, 1, do_fpga_loadbp, "", ""),
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+ U_BOOT_CMD_MKENT(loadfs, 7, 1, do_fpga_loadfs, "", ""),
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADMK)
+ U_BOOT_CMD_MKENT(loadmk, 2, 1, do_fpga_loadmk, "", ""),
+#endif
+#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
+ U_BOOT_CMD_MKENT(loads, 6, 1, do_fpga_loads, "", ""),
+#endif
+};
+
+static int do_fpga_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *fpga_cmd;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ fpga_cmd = find_cmd_tbl(argv[1], fpga_commands,
+ ARRAY_SIZE(fpga_commands));
+ if (!fpga_cmd) {
+ debug("fpga: non existing command\n");
+ return CMD_RET_USAGE;
+ }
+
+ argc -= 2;
+ argv += 2;
+
+ if (argc > fpga_cmd->maxargs) {
+ debug("fpga: more parameters passed\n");
+ return CMD_RET_USAGE;
+ }
+
+ ret = fpga_cmd->cmd(fpga_cmd, flag, argc, argv);
+
+ return cmd_process_error(fpga_cmd, ret);
+}
+
+#if defined(CONFIG_CMD_FPGA_LOADFS) || defined(CONFIG_CMD_FPGA_LOAD_SECURE)
+U_BOOT_CMD(fpga, 9, 1, do_fpga_wrapper,
+#else
+U_BOOT_CMD(fpga, 6, 1, do_fpga_wrapper,
+#endif
+ "loadable FPGA image support",
+ "[operation type] [device number] [image address] [image size]\n"
+ "fpga operations:\n"
+ " dump\t[dev] [address] [size]\tLoad device to memory buffer\n"
+ " info\t[dev]\t\t\tlist known device information\n"
+ " load\t[dev] [address] [size]\tLoad device from memory buffer\n"
+#if defined(CONFIG_CMD_FPGA_LOADP)
+ " loadp\t[dev] [address] [size]\t"
+ "Load device from memory buffer with partial bitstream\n"
+#endif
+ " loadb\t[dev] [address] [size]\t"
+ "Load device from bitstream buffer (Xilinx only)\n"
+#if defined(CONFIG_CMD_FPGA_LOADBP)
+ " loadbp\t[dev] [address] [size]\t"
+ "Load device from bitstream buffer with partial bitstream"
+ "(Xilinx only)\n"
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADFS)
+ "Load device from filesystem (FAT by default) (Xilinx only)\n"
+ " loadfs [dev] [address] [image size] [blocksize] <interface>\n"
+ " [<dev[:part]>] <filename>\n"
+#endif
+#if defined(CONFIG_CMD_FPGA_LOADMK)
+ " loadmk [dev] [address]\tLoad device generated with mkimage"
+#if defined(CONFIG_FIT)
+ "\n"
+ "\tFor loadmk operating on FIT format uImage address must include\n"
+ "\tsubimage unit name in the form of addr:<subimg_uname>"
+#endif
+#endif
+#if defined(CONFIG_CMD_FPGA_LOAD_SECURE)
+ "Load encrypted bitstream (Xilinx only)\n"
+ " loads [dev] [address] [size] [auth-OCM-0/DDR-1/noauth-2]\n"
+ " [enc-devkey(0)/userkey(1)/nenc(2) [Userkey address]\n"
+ "Loads the secure bistreams(authenticated/encrypted/both\n"
+ "authenticated and encrypted) of [size] from [address].\n"
+ "The auth-OCM/DDR flag specifies to perform authentication\n"
+ "in OCM or in DDR. 0 for OCM, 1 for DDR, 2 for no authentication.\n"
+ "The enc flag specifies which key to be used for decryption\n"
+ "0-device key, 1-user key, 2-no encryption.\n"
+ "The optional Userkey address specifies from which address key\n"
+ "has to be used for decryption if user key is selected.\n"
+ "NOTE: the secure bitstream has to be created using Xilinx\n"
+ "bootgen tool only.\n"
+#endif
+);
diff --git a/roms/u-boot/cmd/fpgad.c b/roms/u-boot/cmd/fpgad.c
new file mode 100644
index 000000000..fb2fe63e7
--- /dev/null
+++ b/roms/u-boot/cmd/fpgad.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ *
+ * based on cmd_mem.c
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+
+#include <gdsys_fpga.h>
+
+static uint dp_last_fpga;
+static uint dp_last_addr;
+static uint dp_last_length = 0x40;
+
+/*
+ * FPGA Memory Display
+ *
+ * Syntax:
+ * fpgad {fpga} {addr} {len}
+ */
+#define DISP_LINE_LEN 16
+int do_fpga_md(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned int k;
+ unsigned int fpga;
+ ulong addr, length;
+ int rc = 0;
+ u16 linebuf[DISP_LINE_LEN/sizeof(u16)];
+ ulong nbytes;
+
+ /*
+ * We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ fpga = dp_last_fpga;
+ addr = dp_last_addr;
+ length = dp_last_length;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /*
+ * FPGA is specified since argc > 2
+ */
+ fpga = simple_strtoul(argv[1], NULL, 16);
+
+ /*
+ * Address is specified since argc > 2
+ */
+ addr = simple_strtoul(argv[2], NULL, 16);
+
+ /*
+ * If another parameter, it is the length to display.
+ * Length is the number of objects, not number of bytes.
+ */
+ if (argc > 3)
+ length = simple_strtoul(argv[3], NULL, 16);
+ }
+
+ nbytes = length * sizeof(u16);
+ do {
+ ulong linebytes = (nbytes > DISP_LINE_LEN) ?
+ DISP_LINE_LEN : nbytes;
+
+ for (k = 0; k < linebytes / sizeof(u16); ++k)
+ fpga_get_reg(fpga,
+ (u16 *)fpga_ptr[fpga] + addr
+ / sizeof(u16) + k,
+ addr + k * sizeof(u16),
+ &linebuf[k]);
+ print_buffer(addr, (void *)linebuf, sizeof(u16),
+ linebytes / sizeof(u16),
+ DISP_LINE_LEN / sizeof(u16));
+
+ nbytes -= linebytes;
+ addr += linebytes;
+ if (ctrlc()) {
+ rc = 1;
+ break;
+ }
+ } while (nbytes > 0);
+
+ dp_last_fpga = fpga;
+ dp_last_addr = addr;
+ dp_last_length = length;
+ return rc;
+}
+
+U_BOOT_CMD(
+ fpgad, 4, 1, do_fpga_md,
+ "fpga register display",
+ "fpga address [# of objects]"
+);
diff --git a/roms/u-boot/cmd/fs.c b/roms/u-boot/cmd/fs.c
new file mode 100644
index 000000000..5ad11647c
--- /dev/null
+++ b/roms/u-boot/cmd/fs.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Inspired by cmd_ext_common.c, cmd_fat.c.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+
+static int do_size_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_size(cmdtp, flag, argc, argv, FS_TYPE_ANY);
+}
+
+U_BOOT_CMD(
+ size, 4, 0, do_size_wrapper,
+ "determine a file's size",
+ "<interface> <dev[:part]> <filename>\n"
+ " - Find file 'filename' from 'dev' on 'interface'\n"
+ " and determine its size."
+);
+
+static int do_load_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_load(cmdtp, flag, argc, argv, FS_TYPE_ANY);
+}
+
+U_BOOT_CMD(
+ load, 7, 0, do_load_wrapper,
+ "load binary file from a filesystem",
+ "<interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]\n"
+ " - Load binary file 'filename' from partition 'part' on device\n"
+ " type 'interface' instance 'dev' to address 'addr' in memory.\n"
+ " 'bytes' gives the size to load in bytes.\n"
+ " If 'bytes' is 0 or omitted, the file is read until the end.\n"
+ " 'pos' gives the file byte position to start reading from.\n"
+ " If 'pos' is 0 or omitted, the file is read from the start."
+)
+
+static int do_save_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_save(cmdtp, flag, argc, argv, FS_TYPE_ANY);
+}
+
+U_BOOT_CMD(
+ save, 7, 0, do_save_wrapper,
+ "save file to a filesystem",
+ "<interface> <dev[:part]> <addr> <filename> bytes [pos]\n"
+ " - Save binary file 'filename' to partition 'part' on device\n"
+ " type 'interface' instance 'dev' from addr 'addr' in memory.\n"
+ " 'bytes' gives the size to save in bytes and is mandatory.\n"
+ " 'pos' gives the file byte position to start writing to.\n"
+ " If 'pos' is 0 or omitted, the file is written from the start."
+)
+
+static int do_ls_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_ls(cmdtp, flag, argc, argv, FS_TYPE_ANY);
+}
+
+U_BOOT_CMD(
+ ls, 4, 1, do_ls_wrapper,
+ "list files in a directory (default /)",
+ "<interface> [<dev[:part]> [directory]]\n"
+ " - List files in directory 'directory' of partition 'part' on\n"
+ " device type 'interface' instance 'dev'."
+)
+
+static int do_ln_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_ln(cmdtp, flag, argc, argv, FS_TYPE_ANY);
+}
+
+U_BOOT_CMD(
+ ln, 5, 1, do_ln_wrapper,
+ "Create a symbolic link",
+ "<interface> <dev[:part]> target linkname\n"
+ " - create a symbolic link to 'target' with the name 'linkname' on\n"
+ " device type 'interface' instance 'dev'."
+)
+
+static int do_fstype_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_fs_type(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ fstype, 4, 1, do_fstype_wrapper,
+ "Look up a filesystem type",
+ "<interface> <dev>:<part>\n"
+ "- print filesystem type\n"
+ "fstype <interface> <dev>:<part> <varname>\n"
+ "- set environment variable to filesystem type\n"
+);
+
+static int do_fstypes_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ return do_fs_types(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ fstypes, 1, 1, do_fstypes_wrapper,
+ "List supported filesystem types", ""
+);
diff --git a/roms/u-boot/cmd/fs_uuid.c b/roms/u-boot/cmd/fs_uuid.c
new file mode 100644
index 000000000..5dc94aa64
--- /dev/null
+++ b/roms/u-boot/cmd/fs_uuid.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * cmd_fs_uuid.c -- fsuuid command
+ *
+ * Copyright (C) 2014, Bachmann electronic GmbH
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+
+static int do_fs_uuid_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_fs_uuid(cmdtp, flag, argc, argv, FS_TYPE_ANY);
+}
+
+U_BOOT_CMD(
+ fsuuid, 4, 1, do_fs_uuid_wrapper,
+ "Look up a filesystem UUID",
+ "<interface> <dev>:<part>\n"
+ " - print filesystem UUID\n"
+ "fsuuid <interface> <dev>:<part> <varname>\n"
+ " - set environment variable to filesystem UUID\n"
+);
diff --git a/roms/u-boot/cmd/fuse.c b/roms/u-boot/cmd/fuse.c
new file mode 100644
index 000000000..e001619d1
--- /dev/null
+++ b/roms/u-boot/cmd/fuse.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009-2013 ADVANSEE
+ * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
+ *
+ * Based on the mpc512x iim code:
+ * Copyright 2008 Silicon Turnkey Express, Inc.
+ * Martha Marx <mmarx@silicontkx.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <fuse.h>
+#include <linux/errno.h>
+
+static int strtou32(const char *str, unsigned int base, u32 *result)
+{
+ char *ep;
+
+ *result = simple_strtoul(str, &ep, base);
+ if (ep == str || *ep != '\0')
+ return -EINVAL;
+
+ return 0;
+}
+
+static int confirm_prog(void)
+{
+ puts("Warning: Programming fuses is an irreversible operation!\n"
+ " This may brick your system.\n"
+ " Use this command only if you are sure of "
+ "what you are doing!\n"
+ "\nReally perform this fuse programming? <y/N>\n");
+
+ if (confirm_yesno())
+ return 1;
+
+ puts("Fuse programming aborted\n");
+ return 0;
+}
+
+static int do_fuse(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *op = argc >= 2 ? argv[1] : NULL;
+ int confirmed = argc >= 3 && !strcmp(argv[2], "-y");
+ u32 bank, word, cnt, val;
+ int ret, i;
+
+ argc -= 2 + confirmed;
+ argv += 2 + confirmed;
+
+ if (argc < 2 || strtou32(argv[0], 0, &bank) ||
+ strtou32(argv[1], 0, &word))
+ return CMD_RET_USAGE;
+
+ if (!strcmp(op, "read")) {
+ if (argc == 2)
+ cnt = 1;
+ else if (argc != 3 || strtou32(argv[2], 0, &cnt))
+ return CMD_RET_USAGE;
+
+ printf("Reading bank %u:\n", bank);
+ for (i = 0; i < cnt; i++, word++) {
+ if (!(i % 4))
+ printf("\nWord 0x%.8x:", word);
+
+ ret = fuse_read(bank, word, &val);
+ if (ret)
+ goto err;
+
+ printf(" %.8x", val);
+ }
+ putc('\n');
+ } else if (!strcmp(op, "sense")) {
+ if (argc == 2)
+ cnt = 1;
+ else if (argc != 3 || strtou32(argv[2], 0, &cnt))
+ return CMD_RET_USAGE;
+
+ printf("Sensing bank %u:\n", bank);
+ for (i = 0; i < cnt; i++, word++) {
+ if (!(i % 4))
+ printf("\nWord 0x%.8x:", word);
+
+ ret = fuse_sense(bank, word, &val);
+ if (ret)
+ goto err;
+
+ printf(" %.8x", val);
+ }
+ putc('\n');
+ } else if (!strcmp(op, "prog")) {
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ for (i = 2; i < argc; i++, word++) {
+ if (strtou32(argv[i], 16, &val))
+ return CMD_RET_USAGE;
+
+ printf("Programming bank %u word 0x%.8x to 0x%.8x...\n",
+ bank, word, val);
+ if (!confirmed && !confirm_prog())
+ return CMD_RET_FAILURE;
+ ret = fuse_prog(bank, word, val);
+ if (ret)
+ goto err;
+ }
+ } else if (!strcmp(op, "override")) {
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ for (i = 2; i < argc; i++, word++) {
+ if (strtou32(argv[i], 16, &val))
+ return CMD_RET_USAGE;
+
+ printf("Overriding bank %u word 0x%.8x with "
+ "0x%.8x...\n", bank, word, val);
+ ret = fuse_override(bank, word, val);
+ if (ret)
+ goto err;
+ }
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ return 0;
+
+err:
+ puts("ERROR\n");
+ return CMD_RET_FAILURE;
+}
+
+U_BOOT_CMD(
+ fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
+ "Fuse sub-system",
+ "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n"
+ " starting at 'word'\n"
+ "fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n"
+ " starting at 'word'\n"
+ "fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n"
+ " several fuse words, starting at 'word' (PERMANENT)\n"
+ "fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n"
+ " several fuse words, starting at 'word'"
+);
diff --git a/roms/u-boot/cmd/gettime.c b/roms/u-boot/cmd/gettime.c
new file mode 100644
index 000000000..2e74e02b4
--- /dev/null
+++ b/roms/u-boot/cmd/gettime.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Get Timer overflows after 2^32 / CONFIG_SYS_HZ (32Khz) = 131072 sec
+ */
+#include <common.h>
+#include <command.h>
+
+static int do_gettime(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long int val = get_timer(0);
+
+#ifdef CONFIG_SYS_HZ
+ printf("Timer val: %lu\n", val);
+ printf("Seconds : %lu\n", val / CONFIG_SYS_HZ);
+ printf("Remainder : %lu\n", val % CONFIG_SYS_HZ);
+ printf("sys_hz = %lu\n", (unsigned long int)CONFIG_SYS_HZ);
+#else
+ printf("CONFIG_SYS_HZ not defined");
+ printf("Timer Val %lu", val);
+#endif
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ gettime, 1, 1, do_gettime,
+ "get timer val elapsed",
+ "get time elapsed from uboot start"
+);
diff --git a/roms/u-boot/cmd/gpio.c b/roms/u-boot/cmd/gpio.c
new file mode 100644
index 000000000..4fdb3135f
--- /dev/null
+++ b/roms/u-boot/cmd/gpio.c
@@ -0,0 +1,270 @@
+/*
+ * Control GPIO pins on the fly
+ *
+ * Copyright (c) 2008-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/gpio.h>
+#include <linux/err.h>
+
+__weak int name_to_gpio(const char *name)
+{
+ return simple_strtoul(name, NULL, 10);
+}
+
+enum gpio_cmd {
+ GPIOC_INPUT,
+ GPIOC_SET,
+ GPIOC_CLEAR,
+ GPIOC_TOGGLE,
+};
+
+#if defined(CONFIG_DM_GPIO) && !defined(gpio_status)
+
+/* A few flags used by show_gpio() */
+enum {
+ FLAG_SHOW_ALL = 1 << 0,
+ FLAG_SHOW_BANK = 1 << 1,
+ FLAG_SHOW_NEWLINE = 1 << 2,
+};
+
+static void gpio_get_description(struct udevice *dev, const char *bank_name,
+ int offset, int *flagsp, bool show_all)
+{
+ char buf[80];
+ int ret;
+
+ ret = gpio_get_function(dev, offset, NULL);
+ if (ret < 0)
+ goto err;
+ if (!show_all && !(*flagsp & FLAG_SHOW_ALL) && ret == GPIOF_UNUSED)
+ return;
+ if ((*flagsp & FLAG_SHOW_BANK) && bank_name) {
+ if (*flagsp & FLAG_SHOW_NEWLINE) {
+ putc('\n');
+ *flagsp &= ~FLAG_SHOW_NEWLINE;
+ }
+ printf("Bank %s:\n", bank_name);
+ *flagsp &= ~FLAG_SHOW_BANK;
+ }
+
+ ret = gpio_get_status(dev, offset, buf, sizeof(buf));
+ if (ret)
+ goto err;
+
+ printf("%s\n", buf);
+ return;
+err:
+ printf("Error %d\n", ret);
+}
+
+static int do_gpio_status(bool all, const char *gpio_name)
+{
+ struct udevice *dev;
+ int banklen;
+ int flags;
+ int ret;
+
+ flags = 0;
+ if (gpio_name && !*gpio_name)
+ gpio_name = NULL;
+ for (ret = uclass_first_device(UCLASS_GPIO, &dev);
+ dev;
+ ret = uclass_next_device(&dev)) {
+ const char *bank_name;
+ int num_bits;
+
+ flags |= FLAG_SHOW_BANK;
+ if (all)
+ flags |= FLAG_SHOW_ALL;
+ bank_name = gpio_get_bank_info(dev, &num_bits);
+ if (!num_bits) {
+ debug("GPIO device %s has no bits\n", dev->name);
+ continue;
+ }
+ banklen = bank_name ? strlen(bank_name) : 0;
+
+ if (!gpio_name || !bank_name ||
+ !strncasecmp(gpio_name, bank_name, banklen)) {
+ const char *p;
+ int offset;
+
+ p = gpio_name + banklen;
+ if (gpio_name && *p) {
+ offset = simple_strtoul(p, NULL, 10);
+ gpio_get_description(dev, bank_name, offset,
+ &flags, true);
+ } else {
+ for (offset = 0; offset < num_bits; offset++) {
+ gpio_get_description(dev, bank_name,
+ offset, &flags, false);
+ }
+ }
+ }
+ /* Add a newline between bank names */
+ if (!(flags & FLAG_SHOW_BANK))
+ flags |= FLAG_SHOW_NEWLINE;
+ }
+
+ return ret;
+}
+#endif
+
+static int do_gpio(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned int gpio;
+ enum gpio_cmd sub_cmd;
+ int value;
+ const char *str_cmd, *str_gpio = NULL;
+ int ret;
+#ifdef CONFIG_DM_GPIO
+ bool all = false;
+#endif
+
+ if (argc < 2)
+ show_usage:
+ return CMD_RET_USAGE;
+ str_cmd = argv[1];
+ argc -= 2;
+ argv += 2;
+#ifdef CONFIG_DM_GPIO
+ if (argc > 0 && !strcmp(*argv, "-a")) {
+ all = true;
+ argc--;
+ argv++;
+ }
+#endif
+ if (argc > 0)
+ str_gpio = *argv;
+ if (!strncmp(str_cmd, "status", 2)) {
+ /* Support deprecated gpio_status() */
+#ifdef gpio_status
+ gpio_status();
+ return 0;
+#elif defined(CONFIG_DM_GPIO)
+ return cmd_process_error(cmdtp, do_gpio_status(all, str_gpio));
+#else
+ goto show_usage;
+#endif
+ }
+
+ if (!str_gpio)
+ goto show_usage;
+
+ /* parse the behavior */
+ switch (*str_cmd) {
+ case 'i':
+ sub_cmd = GPIOC_INPUT;
+ break;
+ case 's':
+ sub_cmd = GPIOC_SET;
+ break;
+ case 'c':
+ sub_cmd = GPIOC_CLEAR;
+ break;
+ case 't':
+ sub_cmd = GPIOC_TOGGLE;
+ break;
+ default:
+ goto show_usage;
+ }
+
+#if defined(CONFIG_DM_GPIO)
+ /*
+ * TODO(sjg@chromium.org): For now we must fit into the existing GPIO
+ * framework, so we look up the name here and convert it to a GPIO number.
+ * Once all GPIO drivers are converted to driver model, we can change the
+ * code here to use the GPIO uclass interface instead of the numbered
+ * GPIO compatibility layer.
+ */
+ ret = gpio_lookup_name(str_gpio, NULL, NULL, &gpio);
+ if (ret) {
+ printf("GPIO: '%s' not found\n", str_gpio);
+ return cmd_process_error(cmdtp, ret);
+ }
+#else
+ /* turn the gpio name into a gpio number */
+ gpio = name_to_gpio(str_gpio);
+ if (gpio < 0)
+ goto show_usage;
+#endif
+ /* grab the pin before we tweak it */
+ ret = gpio_request(gpio, "cmd_gpio");
+ if (ret && ret != -EBUSY) {
+ printf("gpio: requesting pin %u failed\n", gpio);
+ return -1;
+ }
+
+ /* finally, let's do it: set direction and exec command */
+ if (sub_cmd == GPIOC_INPUT) {
+ gpio_direction_input(gpio);
+ value = gpio_get_value(gpio);
+ } else {
+ switch (sub_cmd) {
+ case GPIOC_SET:
+ value = 1;
+ break;
+ case GPIOC_CLEAR:
+ value = 0;
+ break;
+ case GPIOC_TOGGLE:
+ value = gpio_get_value(gpio);
+ if (!IS_ERR_VALUE(value))
+ value = !value;
+ break;
+ default:
+ goto show_usage;
+ }
+ gpio_direction_output(gpio, value);
+ }
+ printf("gpio: pin %s (gpio %u) value is ", str_gpio, gpio);
+
+ if (IS_ERR_VALUE(value)) {
+ printf("unknown (ret=%d)\n", value);
+ goto err;
+ } else {
+ printf("%d\n", value);
+ }
+
+ if (sub_cmd != GPIOC_INPUT && !IS_ERR_VALUE(value)) {
+ int nval = gpio_get_value(gpio);
+
+ if (IS_ERR_VALUE(nval)) {
+ printf(" Warning: no access to GPIO output value\n");
+ goto err;
+ } else if (nval != value) {
+ printf(" Warning: value of pin is still %d\n", nval);
+ goto err;
+ }
+ }
+
+ if (ret != -EBUSY)
+ gpio_free(gpio);
+
+ /*
+ * Whilst wrong, the legacy gpio input command returns the pin
+ * value, or CMD_RET_FAILURE (which is indistinguishable from a
+ * valid pin value).
+ */
+ return (sub_cmd == GPIOC_INPUT) ? value : CMD_RET_SUCCESS;
+
+err:
+ if (ret != -EBUSY)
+ gpio_free(gpio);
+ return CMD_RET_FAILURE;
+}
+
+U_BOOT_CMD(gpio, 4, 0, do_gpio,
+ "query and control gpio pins",
+ "<input|set|clear|toggle> <pin>\n"
+ " - input/set/clear/toggle the specified pin\n"
+ "gpio status [-a] [<bank> | <pin>] - show [all/claimed] GPIOs");
diff --git a/roms/u-boot/cmd/gpt.c b/roms/u-boot/cmd/gpt.c
new file mode 100644
index 000000000..17f2b839d
--- /dev/null
+++ b/roms/u-boot/cmd/gpt.c
@@ -0,0 +1,1072 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * cmd_gpt.c -- GPT (GUID Partition Table) handling command
+ *
+ * Copyright (C) 2015
+ * Lukasz Majewski <l.majewski@majess.pl>
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ * author: Piotr Wilczek <p.wilczek@samsung.com>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <env.h>
+#include <log.h>
+#include <malloc.h>
+#include <command.h>
+#include <part.h>
+#include <part_efi.h>
+#include <part.h>
+#include <exports.h>
+#include <uuid.h>
+#include <linux/ctype.h>
+#include <div64.h>
+#include <memalign.h>
+#include <linux/compat.h>
+#include <linux/err.h>
+#include <linux/sizes.h>
+#include <stdlib.h>
+
+static LIST_HEAD(disk_partitions);
+
+/**
+ * extract_env(): Expand env name from string format '&{env_name}'
+ * and return pointer to the env (if the env is set)
+ *
+ * @param str - pointer to string
+ * @param env - pointer to pointer to extracted env
+ *
+ * @return - zero on successful expand and env is set
+ */
+static int extract_env(const char *str, char **env)
+{
+ int ret = -1;
+ char *e, *s;
+#ifdef CONFIG_RANDOM_UUID
+ char uuid_str[UUID_STR_LEN + 1];
+#endif
+
+ if (!str || strlen(str) < 4)
+ return -1;
+
+ if (!((strncmp(str, "${", 2) == 0) && (str[strlen(str) - 1] == '}')))
+ return -1;
+
+ s = strdup(str);
+ if (s == NULL)
+ return -1;
+
+ memset(s + strlen(s) - 1, '\0', 1);
+ memmove(s, s + 2, strlen(s) - 1);
+
+ e = env_get(s);
+ if (e == NULL) {
+#ifdef CONFIG_RANDOM_UUID
+ debug("%s unset. ", str);
+ gen_rand_uuid_str(uuid_str, UUID_STR_FORMAT_GUID);
+ env_set(s, uuid_str);
+
+ e = env_get(s);
+ if (e) {
+ debug("Set to random.\n");
+ ret = 0;
+ } else {
+ debug("Can't get random UUID.\n");
+ }
+#else
+ debug("%s unset.\n", str);
+#endif
+ } else {
+ debug("%s get from environment.\n", str);
+ ret = 0;
+ }
+
+ *env = e;
+ free(s);
+
+ return ret;
+}
+
+/**
+ * extract_val(): Extract value from a key=value pair list (comma separated).
+ * Only value for the given key is returend.
+ * Function allocates memory for the value, remember to free!
+ *
+ * @param str - pointer to string with key=values pairs
+ * @param key - pointer to the key to search for
+ *
+ * @return - pointer to allocated string with the value
+ */
+static char *extract_val(const char *str, const char *key)
+{
+ char *v, *k;
+ char *s, *strcopy;
+ char *new = NULL;
+
+ strcopy = strdup(str);
+ if (strcopy == NULL)
+ return NULL;
+
+ s = strcopy;
+ while (s) {
+ v = strsep(&s, ",");
+ if (!v)
+ break;
+ k = strsep(&v, "=");
+ if (!k)
+ break;
+ if (strcmp(k, key) == 0) {
+ new = strdup(v);
+ break;
+ }
+ }
+
+ free(strcopy);
+
+ return new;
+}
+
+/**
+ * found_key(): Found key without value in parameter list (comma separated).
+ *
+ * @param str - pointer to string with key
+ * @param key - pointer to the key to search for
+ *
+ * @return - true on found key
+ */
+static bool found_key(const char *str, const char *key)
+{
+ char *k;
+ char *s, *strcopy;
+ bool result = false;
+
+ strcopy = strdup(str);
+ if (!strcopy)
+ return NULL;
+
+ s = strcopy;
+ while (s) {
+ k = strsep(&s, ",");
+ if (!k)
+ break;
+ if (strcmp(k, key) == 0) {
+ result = true;
+ break;
+ }
+ }
+
+ free(strcopy);
+
+ return result;
+}
+
+static int calc_parts_list_len(int numparts)
+{
+ int partlistlen = UUID_STR_LEN + 1 + strlen("uuid_disk=");
+ /* for the comma */
+ partlistlen++;
+
+ /* per-partition additions; numparts starts at 1, so this should be correct */
+ partlistlen += numparts * (strlen("name=,") + PART_NAME_LEN + 1);
+ /* see part.h for definition of struct disk_partition */
+ partlistlen += numparts * (strlen("start=MiB,") + sizeof(lbaint_t) + 1);
+ partlistlen += numparts * (strlen("size=MiB,") + sizeof(lbaint_t) + 1);
+ partlistlen += numparts * (strlen("uuid=;") + UUID_STR_LEN + 1);
+ /* for the terminating null */
+ partlistlen++;
+ debug("Length of partitions_list is %d for %d partitions\n", partlistlen,
+ numparts);
+ return partlistlen;
+}
+
+#ifdef CONFIG_CMD_GPT_RENAME
+static void del_gpt_info(void)
+{
+ struct list_head *pos = &disk_partitions;
+ struct disk_part *curr;
+ while (!list_empty(pos)) {
+ curr = list_entry(pos->next, struct disk_part, list);
+ list_del(pos->next);
+ free(curr);
+ }
+}
+
+static struct disk_part *allocate_disk_part(struct disk_partition *info,
+ int partnum)
+{
+ struct disk_part *newpart;
+ newpart = calloc(1, sizeof(struct disk_part));
+ if (!newpart)
+ return ERR_PTR(-ENOMEM);
+
+ newpart->gpt_part_info.start = info->start;
+ newpart->gpt_part_info.size = info->size;
+ newpart->gpt_part_info.blksz = info->blksz;
+ strncpy((char *)newpart->gpt_part_info.name, (const char *)info->name,
+ PART_NAME_LEN);
+ newpart->gpt_part_info.name[PART_NAME_LEN - 1] = '\0';
+ strncpy((char *)newpart->gpt_part_info.type, (const char *)info->type,
+ PART_TYPE_LEN);
+ newpart->gpt_part_info.type[PART_TYPE_LEN - 1] = '\0';
+ newpart->gpt_part_info.bootable = info->bootable;
+#ifdef CONFIG_PARTITION_UUIDS
+ strncpy(newpart->gpt_part_info.uuid, (const char *)info->uuid,
+ UUID_STR_LEN);
+ /* UUID_STR_LEN is correct, as uuid[]'s length is UUID_STR_LEN+1 chars */
+ newpart->gpt_part_info.uuid[UUID_STR_LEN] = '\0';
+#endif
+ newpart->partnum = partnum;
+
+ return newpart;
+}
+
+static void prettyprint_part_size(char *sizestr, lbaint_t partsize,
+ lbaint_t blksize)
+{
+ unsigned long long partbytes, partmegabytes;
+
+ partbytes = partsize * blksize;
+ partmegabytes = lldiv(partbytes, SZ_1M);
+ snprintf(sizestr, 16, "%lluMiB", partmegabytes);
+}
+
+static void print_gpt_info(void)
+{
+ struct list_head *pos;
+ struct disk_part *curr;
+ char partstartstr[16];
+ char partsizestr[16];
+
+ list_for_each(pos, &disk_partitions) {
+ curr = list_entry(pos, struct disk_part, list);
+ prettyprint_part_size(partstartstr, curr->gpt_part_info.start,
+ curr->gpt_part_info.blksz);
+ prettyprint_part_size(partsizestr, curr->gpt_part_info.size,
+ curr->gpt_part_info.blksz);
+
+ printf("Partition %d:\n", curr->partnum);
+ printf("Start %s, size %s\n", partstartstr, partsizestr);
+ printf("Block size %lu, name %s\n", curr->gpt_part_info.blksz,
+ curr->gpt_part_info.name);
+ printf("Type %s, bootable %d\n", curr->gpt_part_info.type,
+ curr->gpt_part_info.bootable & PART_BOOTABLE);
+#ifdef CONFIG_PARTITION_UUIDS
+ printf("UUID %s\n", curr->gpt_part_info.uuid);
+#endif
+ printf("\n");
+ }
+}
+
+/*
+ * create the string that upstream 'gpt write' command will accept as an
+ * argument
+ *
+ * From doc/README.gpt, Format of partitions layout:
+ * "uuid_disk=...;name=u-boot,size=60MiB,uuid=...;
+ * name=kernel,size=60MiB,uuid=...;"
+ * The fields 'name' and 'size' are mandatory for every partition.
+ * The field 'start' is optional. The fields 'uuid' and 'uuid_disk'
+ * are optional if CONFIG_RANDOM_UUID is enabled.
+ */
+static int create_gpt_partitions_list(int numparts, const char *guid,
+ char *partitions_list)
+{
+ struct list_head *pos;
+ struct disk_part *curr;
+ char partstr[PART_NAME_LEN + 1];
+
+ if (!partitions_list)
+ return -EINVAL;
+
+ strcpy(partitions_list, "uuid_disk=");
+ strncat(partitions_list, guid, UUID_STR_LEN + 1);
+ strcat(partitions_list, ";");
+
+ list_for_each(pos, &disk_partitions) {
+ curr = list_entry(pos, struct disk_part, list);
+ strcat(partitions_list, "name=");
+ strncat(partitions_list, (const char *)curr->gpt_part_info.name,
+ PART_NAME_LEN + 1);
+ sprintf(partstr, ",start=0x%llx",
+ (unsigned long long)curr->gpt_part_info.start *
+ curr->gpt_part_info.blksz);
+ /* one extra byte for NULL */
+ strncat(partitions_list, partstr, PART_NAME_LEN + 1);
+ sprintf(partstr, ",size=0x%llx",
+ (unsigned long long)curr->gpt_part_info.size *
+ curr->gpt_part_info.blksz);
+ strncat(partitions_list, partstr, PART_NAME_LEN + 1);
+
+ strcat(partitions_list, ",uuid=");
+ strncat(partitions_list, curr->gpt_part_info.uuid,
+ UUID_STR_LEN + 1);
+ strcat(partitions_list, ";");
+ }
+ return 0;
+}
+
+/*
+ * read partition info into disk_partitions list where
+ * it can be printed or modified
+ */
+static int get_gpt_info(struct blk_desc *dev_desc)
+{
+ /* start partition numbering at 1, as U-Boot does */
+ int valid_parts = 0, p, ret;
+ struct disk_partition info;
+ struct disk_part *new_disk_part;
+
+ /*
+ * Always re-read partition info from device, in case
+ * it has changed
+ */
+ INIT_LIST_HEAD(&disk_partitions);
+
+ for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
+ ret = part_get_info(dev_desc, p, &info);
+ if (ret)
+ continue;
+
+ /* Add 1 here because counter is zero-based but p1 is
+ the first partition */
+ new_disk_part = allocate_disk_part(&info, valid_parts+1);
+ if (IS_ERR(new_disk_part))
+ goto out;
+
+ list_add_tail(&new_disk_part->list, &disk_partitions);
+ valid_parts++;
+ }
+ if (valid_parts == 0) {
+ printf("** No valid partitions found **\n");
+ goto out;
+ }
+ return valid_parts;
+ out:
+ if (valid_parts >= 1)
+ del_gpt_info();
+ return -ENODEV;
+}
+
+/* a wrapper to test get_gpt_info */
+static int do_get_gpt_info(struct blk_desc *dev_desc, char * const namestr)
+{
+ int numparts;
+
+ numparts = get_gpt_info(dev_desc);
+
+ if (numparts > 0) {
+ if (namestr) {
+ char disk_guid[UUID_STR_LEN + 1];
+ char *partitions_list;
+ int partlistlen;
+ int ret = -1;
+
+ ret = get_disk_guid(dev_desc, disk_guid);
+ if (ret < 0)
+ return ret;
+
+ partlistlen = calc_parts_list_len(numparts);
+ partitions_list = malloc(partlistlen);
+ if (!partitions_list) {
+ del_gpt_info();
+ return -ENOMEM;
+ }
+ memset(partitions_list, '\0', partlistlen);
+
+ ret = create_gpt_partitions_list(numparts, disk_guid,
+ partitions_list);
+ if (ret < 0)
+ printf("Error: Could not create partition list string!\n");
+ else
+ env_set(namestr, partitions_list);
+
+ free(partitions_list);
+ } else {
+ print_gpt_info();
+ }
+ del_gpt_info();
+ return 0;
+ }
+ return numparts;
+}
+#endif
+
+/**
+ * set_gpt_info(): Fill partition information from string
+ * function allocates memory, remember to free!
+ *
+ * @param dev_desc - pointer block device descriptor
+ * @param str_part - pointer to string with partition information
+ * @param str_disk_guid - pointer to pointer to allocated string with disk guid
+ * @param partitions - pointer to pointer to allocated partitions array
+ * @param parts_count - number of partitions
+ *
+ * @return - zero on success, otherwise error
+ *
+ */
+static int set_gpt_info(struct blk_desc *dev_desc,
+ const char *str_part,
+ char **str_disk_guid,
+ struct disk_partition **partitions,
+ u8 *parts_count)
+{
+ char *tok, *str, *s;
+ int i;
+ char *val, *p;
+ int p_count;
+ struct disk_partition *parts;
+ int errno = 0;
+ uint64_t size_ll, start_ll;
+ lbaint_t offset = 0;
+ int max_str_part = calc_parts_list_len(MAX_SEARCH_PARTITIONS);
+
+ debug("%s: lba num: 0x%x %d\n", __func__,
+ (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba);
+
+ if (str_part == NULL)
+ return -1;
+
+ str = strdup(str_part);
+ if (str == NULL)
+ return -ENOMEM;
+
+ /* extract disk guid */
+ s = str;
+ val = extract_val(str, "uuid_disk");
+ if (!val) {
+#ifdef CONFIG_RANDOM_UUID
+ *str_disk_guid = malloc(UUID_STR_LEN + 1);
+ if (*str_disk_guid == NULL)
+ return -ENOMEM;
+ gen_rand_uuid_str(*str_disk_guid, UUID_STR_FORMAT_STD);
+#else
+ free(str);
+ return -2;
+#endif
+ } else {
+ val = strsep(&val, ";");
+ if (extract_env(val, &p))
+ p = val;
+ *str_disk_guid = strdup(p);
+ free(val);
+ /* Move s to first partition */
+ strsep(&s, ";");
+ }
+ if (s == NULL) {
+ printf("Error: is the partitions string NULL-terminated?\n");
+ return -EINVAL;
+ }
+ if (strnlen(s, max_str_part) == 0)
+ return -3;
+
+ i = strnlen(s, max_str_part) - 1;
+ if (s[i] == ';')
+ s[i] = '\0';
+
+ /* calculate expected number of partitions */
+ p_count = 1;
+ p = s;
+ while (*p) {
+ if (*p++ == ';')
+ p_count++;
+ }
+
+ /* allocate memory for partitions */
+ parts = calloc(sizeof(struct disk_partition), p_count);
+ if (parts == NULL)
+ return -ENOMEM;
+
+ /* retrieve partitions data from string */
+ for (i = 0; i < p_count; i++) {
+ tok = strsep(&s, ";");
+
+ if (tok == NULL)
+ break;
+
+ /* uuid */
+ val = extract_val(tok, "uuid");
+ if (!val) {
+ /* 'uuid' is optional if random uuid's are enabled */
+#ifdef CONFIG_RANDOM_UUID
+ gen_rand_uuid_str(parts[i].uuid, UUID_STR_FORMAT_STD);
+#else
+ errno = -4;
+ goto err;
+#endif
+ } else {
+ if (extract_env(val, &p))
+ p = val;
+ if (strnlen(p, max_str_part) >= sizeof(parts[i].uuid)) {
+ printf("Wrong uuid format for partition %d\n", i);
+ errno = -4;
+ goto err;
+ }
+ strncpy((char *)parts[i].uuid, p, max_str_part);
+ free(val);
+ }
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ /* guid */
+ val = extract_val(tok, "type");
+ if (val) {
+ /* 'type' is optional */
+ if (extract_env(val, &p))
+ p = val;
+ if (strnlen(p, max_str_part) >= sizeof(parts[i].type_guid)) {
+ printf("Wrong type guid format for partition %d\n",
+ i);
+ errno = -4;
+ goto err;
+ }
+ strncpy((char *)parts[i].type_guid, p, max_str_part);
+ free(val);
+ }
+#endif
+ /* name */
+ val = extract_val(tok, "name");
+ if (!val) { /* name is mandatory */
+ errno = -4;
+ goto err;
+ }
+ if (extract_env(val, &p))
+ p = val;
+ if (strnlen(p, max_str_part) >= sizeof(parts[i].name)) {
+ errno = -4;
+ goto err;
+ }
+ strncpy((char *)parts[i].name, p, max_str_part);
+ free(val);
+
+ /* size */
+ val = extract_val(tok, "size");
+ if (!val) { /* 'size' is mandatory */
+ errno = -4;
+ goto err;
+ }
+ if (extract_env(val, &p))
+ p = val;
+ if ((strcmp(p, "-") == 0)) {
+ /* Let part efi module to auto extend the size */
+ parts[i].size = 0;
+ } else {
+ size_ll = ustrtoull(p, &p, 0);
+ parts[i].size = lldiv(size_ll, dev_desc->blksz);
+ }
+
+ free(val);
+
+ /* start address */
+ val = extract_val(tok, "start");
+ if (val) { /* start address is optional */
+ if (extract_env(val, &p))
+ p = val;
+ start_ll = ustrtoull(p, &p, 0);
+ parts[i].start = lldiv(start_ll, dev_desc->blksz);
+ free(val);
+ }
+
+ offset += parts[i].size + parts[i].start;
+
+ /* bootable */
+ if (found_key(tok, "bootable"))
+ parts[i].bootable = PART_BOOTABLE;
+ }
+
+ *parts_count = p_count;
+ *partitions = parts;
+ free(str);
+
+ return 0;
+err:
+ free(str);
+ free(*str_disk_guid);
+ free(parts);
+
+ return errno;
+}
+
+static int gpt_default(struct blk_desc *blk_dev_desc, const char *str_part)
+{
+ int ret;
+ char *str_disk_guid;
+ u8 part_count = 0;
+ struct disk_partition *partitions = NULL;
+
+ /* fill partitions */
+ ret = set_gpt_info(blk_dev_desc, str_part,
+ &str_disk_guid, &partitions, &part_count);
+ if (ret) {
+ if (ret == -1)
+ printf("No partition list provided\n");
+ if (ret == -2)
+ printf("Missing disk guid\n");
+ if ((ret == -3) || (ret == -4))
+ printf("Partition list incomplete\n");
+ return -1;
+ }
+
+ /* save partitions layout to disk */
+ ret = gpt_restore(blk_dev_desc, str_disk_guid, partitions, part_count);
+ free(str_disk_guid);
+ free(partitions);
+
+ return ret;
+}
+
+static int gpt_verify(struct blk_desc *blk_dev_desc, const char *str_part)
+{
+ ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1,
+ blk_dev_desc->blksz);
+ struct disk_partition *partitions = NULL;
+ gpt_entry *gpt_pte = NULL;
+ char *str_disk_guid;
+ u8 part_count = 0;
+ int ret = 0;
+
+ /* fill partitions */
+ ret = set_gpt_info(blk_dev_desc, str_part,
+ &str_disk_guid, &partitions, &part_count);
+ if (ret) {
+ if (ret == -1) {
+ printf("No partition list provided - only basic check\n");
+ ret = gpt_verify_headers(blk_dev_desc, gpt_head,
+ &gpt_pte);
+ goto out;
+ }
+ if (ret == -2)
+ printf("Missing disk guid\n");
+ if ((ret == -3) || (ret == -4))
+ printf("Partition list incomplete\n");
+ return -1;
+ }
+
+ /* Check partition layout with provided pattern */
+ ret = gpt_verify_partitions(blk_dev_desc, partitions, part_count,
+ gpt_head, &gpt_pte);
+ free(str_disk_guid);
+ free(partitions);
+ out:
+ free(gpt_pte);
+ return ret;
+}
+
+/**
+ * gpt_enumerate() - Enumerate partition names into environment variable.
+ *
+ * Enumerate partition names. Partition names are stored in gpt_partition_list
+ * environment variable. Each partition name is delimited by space.
+ *
+ * @desc: block device descriptor
+ *
+ * @Return: '0' on success and -ve error on failure
+ */
+static int gpt_enumerate(struct blk_desc *desc)
+{
+ struct part_driver *first_drv, *part_drv;
+ int str_len = 0, tmp_len;
+ char part_list[2048];
+ int n_drvs;
+ char *ptr;
+
+ part_list[0] = 0;
+ n_drvs = part_driver_get_count();
+ if (!n_drvs) {
+ printf("Failed to get partition driver count\n");
+ return -ENOENT;
+ }
+
+ first_drv = part_driver_get_first();
+ for (part_drv = first_drv; part_drv != first_drv + n_drvs; part_drv++) {
+ struct disk_partition pinfo;
+ int ret;
+ int i;
+
+ for (i = 1; i < part_drv->max_entries; i++) {
+ ret = part_drv->get_info(desc, i, &pinfo);
+ if (ret) {
+ /* no more entries in table */
+ break;
+ }
+
+ ptr = &part_list[str_len];
+ tmp_len = strlen((const char *)pinfo.name);
+ str_len += tmp_len;
+ /* +1 for space */
+ str_len++;
+ if (str_len > sizeof(part_list)) {
+ printf("Error insufficient memory\n");
+ return -ENOMEM;
+ }
+ strcpy(ptr, (const char *)pinfo.name);
+ /* One byte for space(" ") delimiter */
+ ptr[tmp_len] = ' ';
+ }
+ }
+ if (*part_list)
+ part_list[strlen(part_list) - 1] = 0;
+ debug("setenv gpt_partition_list %s\n", part_list);
+
+ return env_set("gpt_partition_list", part_list);
+}
+
+/**
+ * gpt_setenv_part_variables() - setup partition environmental variables
+ *
+ * Setup the gpt_partition_name, gpt_partition_entry, gpt_partition_addr
+ * and gpt_partition_size environment variables.
+ *
+ * @pinfo: pointer to disk partition
+ * @i: partition entry
+ *
+ * @Return: '0' on success and -ENOENT on failure
+ */
+static int gpt_setenv_part_variables(struct disk_partition *pinfo, int i)
+{
+ int ret;
+
+ ret = env_set_hex("gpt_partition_addr", pinfo->start);
+ if (ret)
+ goto fail;
+
+ ret = env_set_hex("gpt_partition_size", pinfo->size);
+ if (ret)
+ goto fail;
+
+ ret = env_set_ulong("gpt_partition_entry", i);
+ if (ret)
+ goto fail;
+
+ ret = env_set("gpt_partition_name", (const char *)pinfo->name);
+ if (ret)
+ goto fail;
+
+ return 0;
+
+fail:
+ return -ENOENT;
+}
+
+/**
+ * gpt_setenv() - Dynamically setup environment variables.
+ *
+ * Dynamically setup environment variables for name, index, offset and size
+ * for partition in GPT table after running "gpt setenv" for a partition name.
+ *
+ * @desc: block device descriptor
+ * @name: partition name
+ *
+ * @Return: '0' on success and -ve err on failure
+ */
+static int gpt_setenv(struct blk_desc *desc, const char *name)
+{
+ struct part_driver *first_drv, *part_drv;
+ int n_drvs;
+ int ret = -1;
+
+ n_drvs = part_driver_get_count();
+ if (!n_drvs) {
+ printf("Failed to get partition driver count\n");
+ goto fail;
+ }
+
+ first_drv = part_driver_get_first();
+ for (part_drv = first_drv; part_drv != first_drv + n_drvs; part_drv++) {
+ struct disk_partition pinfo;
+ int i;
+
+ for (i = 1; i < part_drv->max_entries; i++) {
+ ret = part_drv->get_info(desc, i, &pinfo);
+ if (ret) {
+ /* no more entries in table */
+ break;
+ }
+
+ if (!strcmp(name, (const char *)pinfo.name)) {
+ /* match found, setup environment variables */
+ ret = gpt_setenv_part_variables(&pinfo, i);
+ if (ret)
+ goto fail;
+
+ return 0;
+ }
+ }
+ }
+
+fail:
+ return ret;
+}
+
+static int do_disk_guid(struct blk_desc *dev_desc, char * const namestr)
+{
+ int ret;
+ char disk_guid[UUID_STR_LEN + 1];
+
+ ret = get_disk_guid(dev_desc, disk_guid);
+ if (ret < 0)
+ return CMD_RET_FAILURE;
+
+ if (namestr)
+ env_set(namestr, disk_guid);
+ else
+ printf("%s\n", disk_guid);
+
+ return ret;
+}
+
+#ifdef CONFIG_CMD_GPT_RENAME
+static int do_rename_gpt_parts(struct blk_desc *dev_desc, char *subcomm,
+ char *name1, char *name2)
+{
+ struct list_head *pos;
+ struct disk_part *curr;
+ struct disk_partition *new_partitions = NULL;
+ char disk_guid[UUID_STR_LEN + 1];
+ char *partitions_list, *str_disk_guid = NULL;
+ u8 part_count = 0;
+ int partlistlen, ret, numparts = 0, partnum, i = 1, ctr1 = 0, ctr2 = 0;
+
+ if ((subcomm == NULL) || (name1 == NULL) || (name2 == NULL) ||
+ (strcmp(subcomm, "swap") && (strcmp(subcomm, "rename"))))
+ return -EINVAL;
+
+ ret = get_disk_guid(dev_desc, disk_guid);
+ if (ret < 0)
+ return ret;
+ /*
+ * Allocates disk_partitions, requiring matching call to del_gpt_info()
+ * if successful.
+ */
+ numparts = get_gpt_info(dev_desc);
+ if (numparts <= 0)
+ return numparts ? numparts : -ENODEV;
+
+ partlistlen = calc_parts_list_len(numparts);
+ partitions_list = malloc(partlistlen);
+ if (!partitions_list) {
+ del_gpt_info();
+ return -ENOMEM;
+ }
+ memset(partitions_list, '\0', partlistlen);
+
+ ret = create_gpt_partitions_list(numparts, disk_guid, partitions_list);
+ if (ret < 0) {
+ free(partitions_list);
+ return ret;
+ }
+ /*
+ * Uncomment the following line to print a string that 'gpt write'
+ * or 'gpt verify' will accept as input.
+ */
+ debug("OLD partitions_list is %s with %u chars\n", partitions_list,
+ (unsigned)strlen(partitions_list));
+
+ /* set_gpt_info allocates new_partitions and str_disk_guid */
+ ret = set_gpt_info(dev_desc, partitions_list, &str_disk_guid,
+ &new_partitions, &part_count);
+ if (ret < 0)
+ goto out;
+
+ if (!strcmp(subcomm, "swap")) {
+ if ((strlen(name1) > PART_NAME_LEN) || (strlen(name2) > PART_NAME_LEN)) {
+ printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
+ ret = -EINVAL;
+ goto out;
+ }
+ list_for_each(pos, &disk_partitions) {
+ curr = list_entry(pos, struct disk_part, list);
+ if (!strcmp((char *)curr->gpt_part_info.name, name1)) {
+ strcpy((char *)curr->gpt_part_info.name, name2);
+ ctr1++;
+ } else if (!strcmp((char *)curr->gpt_part_info.name, name2)) {
+ strcpy((char *)curr->gpt_part_info.name, name1);
+ ctr2++;
+ }
+ }
+ if ((ctr1 + ctr2 < 2) || (ctr1 != ctr2)) {
+ printf("Cannot swap partition names except in pairs.\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ } else { /* rename */
+ if (strlen(name2) > PART_NAME_LEN) {
+ printf("Names longer than %d characters are truncated.\n", PART_NAME_LEN);
+ ret = -EINVAL;
+ goto out;
+ }
+ partnum = (int)simple_strtol(name1, NULL, 10);
+ if ((partnum < 0) || (partnum > numparts)) {
+ printf("Illegal partition number %s\n", name1);
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = part_get_info(dev_desc, partnum, new_partitions);
+ if (ret < 0)
+ goto out;
+
+ /* U-Boot partition numbering starts at 1 */
+ list_for_each(pos, &disk_partitions) {
+ curr = list_entry(pos, struct disk_part, list);
+ if (i == partnum) {
+ strcpy((char *)curr->gpt_part_info.name, name2);
+ break;
+ }
+ i++;
+ }
+ }
+
+ ret = create_gpt_partitions_list(numparts, disk_guid, partitions_list);
+ if (ret < 0)
+ goto out;
+ debug("NEW partitions_list is %s with %u chars\n", partitions_list,
+ (unsigned)strlen(partitions_list));
+
+ ret = set_gpt_info(dev_desc, partitions_list, &str_disk_guid,
+ &new_partitions, &part_count);
+ /*
+ * Even though valid pointers are here passed into set_gpt_info(),
+ * it mallocs again, and there's no way to tell which failed.
+ */
+ if (ret < 0)
+ goto out;
+
+ debug("Writing new partition table\n");
+ ret = gpt_restore(dev_desc, disk_guid, new_partitions, numparts);
+ if (ret < 0) {
+ printf("Writing new partition table failed\n");
+ goto out;
+ }
+
+ debug("Reading back new partition table\n");
+ /*
+ * Empty the existing disk_partitions list, as otherwise the memory in
+ * the original list is unreachable.
+ */
+ del_gpt_info();
+ numparts = get_gpt_info(dev_desc);
+ if (numparts <= 0) {
+ ret = numparts ? numparts : -ENODEV;
+ goto out;
+ }
+ printf("new partition table with %d partitions is:\n", numparts);
+ print_gpt_info();
+ out:
+ del_gpt_info();
+#ifdef CONFIG_RANDOM_UUID
+ free(str_disk_guid);
+#endif
+ free(new_partitions);
+ free(partitions_list);
+ return ret;
+}
+#endif
+
+/**
+ * do_gpt(): Perform GPT operations
+ *
+ * @param cmdtp - command name
+ * @param flag
+ * @param argc
+ * @param argv
+ *
+ * @return zero on success; otherwise error
+ */
+static int do_gpt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int ret = CMD_RET_SUCCESS;
+ int dev = 0;
+ char *ep;
+ struct blk_desc *blk_dev_desc = NULL;
+
+#ifndef CONFIG_CMD_GPT_RENAME
+ if (argc < 4 || argc > 5)
+#else
+ if (argc < 4 || argc > 6)
+#endif
+ return CMD_RET_USAGE;
+
+ dev = (int)simple_strtoul(argv[3], &ep, 10);
+ if (!ep || ep[0] != '\0') {
+ printf("'%s' is not a number\n", argv[3]);
+ return CMD_RET_USAGE;
+ }
+ blk_dev_desc = blk_get_dev(argv[2], dev);
+ if (!blk_dev_desc) {
+ printf("%s: %s dev %d NOT available\n",
+ __func__, argv[2], dev);
+ return CMD_RET_FAILURE;
+ }
+
+ if ((strcmp(argv[1], "write") == 0) && (argc == 5)) {
+ printf("Writing GPT: ");
+ ret = gpt_default(blk_dev_desc, argv[4]);
+ } else if ((strcmp(argv[1], "verify") == 0)) {
+ ret = gpt_verify(blk_dev_desc, argv[4]);
+ printf("Verify GPT: ");
+ } else if ((strcmp(argv[1], "setenv") == 0)) {
+ ret = gpt_setenv(blk_dev_desc, argv[4]);
+ } else if ((strcmp(argv[1], "enumerate") == 0)) {
+ ret = gpt_enumerate(blk_dev_desc);
+ } else if (strcmp(argv[1], "guid") == 0) {
+ ret = do_disk_guid(blk_dev_desc, argv[4]);
+#ifdef CONFIG_CMD_GPT_RENAME
+ } else if (strcmp(argv[1], "read") == 0) {
+ ret = do_get_gpt_info(blk_dev_desc, (argc == 5) ? argv[4] : NULL);
+ } else if ((strcmp(argv[1], "swap") == 0) ||
+ (strcmp(argv[1], "rename") == 0)) {
+ ret = do_rename_gpt_parts(blk_dev_desc, argv[1], argv[4], argv[5]);
+#endif
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ if (ret) {
+ printf("error!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ printf("success!\n");
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
+ "GUID Partition Table",
+ "<command> <interface> <dev> <partitions_list>\n"
+ " - GUID partition table restoration and validity check\n"
+ " Restore or verify GPT information on a device connected\n"
+ " to interface\n"
+ " Example usage:\n"
+ " gpt write mmc 0 $partitions\n"
+ " - write the GPT to device\n"
+ " gpt verify mmc 0 $partitions\n"
+ " - verify the GPT on device against $partitions\n"
+ " gpt setenv mmc 0 $name\n"
+ " - setup environment variables for partition $name:\n"
+ " gpt_partition_addr, gpt_partition_size,\n"
+ " gpt_partition_name, gpt_partition_entry\n"
+ " gpt enumerate mmc 0\n"
+ " - store list of partitions to gpt_partition_list environment variable\n"
+ " read <interface> <dev>\n"
+ " - read GPT into a data structure for manipulation\n"
+ " gpt guid <interface> <dev>\n"
+ " - print disk GUID\n"
+ " gpt guid <interface> <dev> <varname>\n"
+ " - set environment variable to disk GUID\n"
+ " Example usage:\n"
+ " gpt guid mmc 0\n"
+ " gpt guid mmc 0 varname\n"
+#ifdef CONFIG_CMD_GPT_RENAME
+ "gpt partition renaming commands:\n"
+ " gpt read <interface> <dev> [<varname>]\n"
+ " - read GPT into a data structure for manipulation\n"
+ " - read GPT partitions into environment variable\n"
+ " gpt swap <interface> <dev> <name1> <name2>\n"
+ " - change all partitions named name1 to name2\n"
+ " and vice-versa\n"
+ " gpt rename <interface> <dev> <part> <name>\n"
+ " - rename the specified partition\n"
+ " Example usage:\n"
+ " gpt swap mmc 0 foo bar\n"
+ " gpt rename mmc 0 3 foo\n"
+#endif
+);
diff --git a/roms/u-boot/cmd/hash.c b/roms/u-boot/cmd/hash.c
new file mode 100644
index 000000000..e163cd677
--- /dev/null
+++ b/roms/u-boot/cmd/hash.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * (C) Copyright 2011
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.com
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <hash.h>
+#include <linux/ctype.h>
+
+static int do_hash(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *s;
+ int flags = HASH_FLAG_ENV;
+
+#ifdef CONFIG_HASH_VERIFY
+ if (argc < 4)
+ return CMD_RET_USAGE;
+ if (!strcmp(argv[1], "-v")) {
+ flags |= HASH_FLAG_VERIFY;
+ argc--;
+ argv++;
+ }
+#endif
+ /* Move forward to 'algorithm' parameter */
+ argc--;
+ argv++;
+ for (s = *argv; *s; s++)
+ *s = tolower(*s);
+ return hash_command(*argv, flags, cmdtp, flag, argc - 1, argv + 1);
+}
+
+#ifdef CONFIG_HASH_VERIFY
+#define HARGS 6
+#else
+#define HARGS 5
+#endif
+
+U_BOOT_CMD(
+ hash, HARGS, 1, do_hash,
+ "compute hash message digest",
+ "algorithm address count [[*]hash_dest]\n"
+ " - compute message digest [save to env var / *address]"
+#ifdef CONFIG_HASH_VERIFY
+ "\nhash -v algorithm address count [*]hash\n"
+ " - verify message digest of memory area to immediate value, \n"
+ " env var or *address"
+#endif
+);
diff --git a/roms/u-boot/cmd/help.c b/roms/u-boot/cmd/help.c
new file mode 100644
index 000000000..8d67d977b
--- /dev/null
+++ b/roms/u-boot/cmd/help.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_help(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+#ifdef CONFIG_CMDLINE
+ struct cmd_tbl *start = ll_entry_start(struct cmd_tbl, cmd);
+ const int len = ll_entry_count(struct cmd_tbl, cmd);
+ return _do_help(start, len, cmdtp, flag, argc, argv);
+#else
+ return 0;
+#endif
+}
+
+U_BOOT_CMD(
+ help, CONFIG_SYS_MAXARGS, 1, do_help,
+ "print command description/usage",
+ "\n"
+ " - print brief description of all commands\n"
+ "help command ...\n"
+ " - print detailed usage of 'command'"
+);
+
+#ifdef CONFIG_CMDLINE
+/* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */
+ll_entry_declare(struct cmd_tbl, question_mark, cmd) = {
+ "?", CONFIG_SYS_MAXARGS, cmd_always_repeatable, do_help,
+ "alias for 'help'",
+#ifdef CONFIG_SYS_LONGHELP
+ ""
+#endif /* CONFIG_SYS_LONGHELP */
+};
+#endif
diff --git a/roms/u-boot/cmd/host.c b/roms/u-boot/cmd/host.c
new file mode 100644
index 000000000..6aa3d9167
--- /dev/null
+++ b/roms/u-boot/cmd/host.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2012, Google Inc.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <fs.h>
+#include <part.h>
+#include <sandboxblockdev.h>
+#include <dm/device_compat.h>
+#include <linux/errno.h>
+
+static int host_curr_device = -1;
+
+static int do_host_load(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_load(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX);
+}
+
+static int do_host_ls(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX);
+}
+
+static int do_host_size(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_size(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX);
+}
+
+static int do_host_save(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX);
+}
+
+static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bool removable = false;
+ const char *dev_str;
+ char *file;
+ char *ep;
+ int dev;
+
+ /* Skip 'bind' */
+ argc--;
+ argv++;
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(argv[0], "-r")) {
+ removable = true;
+ argc--;
+ argv++;
+ }
+
+ if (argc > 2)
+ return CMD_RET_USAGE;
+ dev_str = argv[0];
+ dev = simple_strtoul(dev_str, &ep, 16);
+ if (*ep) {
+ printf("** Bad device specification %s **\n", dev_str);
+ return CMD_RET_USAGE;
+ }
+ file = argc > 1 ? argv[1] : NULL;
+
+ return !!host_dev_bind(dev, file, removable);
+}
+
+static int do_host_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc < 1 || argc > 2)
+ return CMD_RET_USAGE;
+ int min_dev = 0;
+ int max_dev = CONFIG_HOST_MAX_DEVICES - 1;
+ if (argc >= 2) {
+ char *ep;
+ char *dev_str = argv[1];
+ int dev = simple_strtoul(dev_str, &ep, 16);
+ if (*ep) {
+ printf("** Bad device specification %s **\n", dev_str);
+ return CMD_RET_USAGE;
+ }
+ min_dev = dev;
+ max_dev = dev;
+ }
+ int dev;
+ printf("%3s %12s %s\n", "dev", "blocks", "path");
+ for (dev = min_dev; dev <= max_dev; dev++) {
+ struct blk_desc *blk_dev;
+ int ret;
+
+ printf("%3d ", dev);
+ ret = host_get_dev_err(dev, &blk_dev);
+ if (ret) {
+ if (ret == -ENOENT)
+ puts("Not bound to a backing file\n");
+ else if (ret == -ENODEV)
+ puts("Invalid host device number\n");
+
+ continue;
+ }
+ struct host_block_dev *host_dev;
+
+#ifdef CONFIG_BLK
+ host_dev = dev_get_plat(blk_dev->bdev);
+#else
+ host_dev = blk_dev->priv;
+#endif
+ printf("%12lu %s\n", (unsigned long)blk_dev->lba,
+ host_dev->filename);
+ }
+ return 0;
+}
+
+static int do_host_dev(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int dev;
+ char *ep;
+ struct blk_desc *blk_dev;
+ int ret;
+
+ if (argc < 1 || argc > 3)
+ return CMD_RET_USAGE;
+
+ if (argc == 1) {
+ if (host_curr_device < 0) {
+ printf("No current host device\n");
+ return 1;
+ }
+ printf("Current host device %d\n", host_curr_device);
+ return 0;
+ }
+
+ dev = simple_strtoul(argv[1], &ep, 16);
+ if (*ep) {
+ printf("** Bad device specification %s **\n", argv[2]);
+ return CMD_RET_USAGE;
+ }
+
+ ret = host_get_dev_err(dev, &blk_dev);
+ if (ret) {
+ if (ret == -ENOENT)
+ puts("Not bound to a backing file\n");
+ else if (ret == -ENODEV)
+ puts("Invalid host device number\n");
+
+ return 1;
+ }
+
+ host_curr_device = dev;
+ return 0;
+}
+
+static struct cmd_tbl cmd_host_sub[] = {
+ U_BOOT_CMD_MKENT(load, 7, 0, do_host_load, "", ""),
+ U_BOOT_CMD_MKENT(ls, 3, 0, do_host_ls, "", ""),
+ U_BOOT_CMD_MKENT(save, 6, 0, do_host_save, "", ""),
+ U_BOOT_CMD_MKENT(size, 3, 0, do_host_size, "", ""),
+ U_BOOT_CMD_MKENT(bind, 4, 0, do_host_bind, "", ""),
+ U_BOOT_CMD_MKENT(info, 3, 0, do_host_info, "", ""),
+ U_BOOT_CMD_MKENT(dev, 0, 1, do_host_dev, "", ""),
+};
+
+static int do_host(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ /* Skip past 'host' */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], cmd_host_sub,
+ ARRAY_SIZE(cmd_host_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+ host, 8, 1, do_host,
+ "Miscellaneous host commands",
+ "load hostfs - <addr> <filename> [<bytes> <offset>] - "
+ "load a file from host\n"
+ "host ls hostfs - <filename> - list files on host\n"
+ "host save hostfs - <addr> <filename> <bytes> [<offset>] - "
+ "save a file to host\n"
+ "host size hostfs - <filename> - determine size of file on host\n"
+ "host bind [-r] <dev> [<filename>] - bind \"host\" device to file\n"
+ " -r = mark as removable\n"
+ "host info [<dev>] - show device binding & info\n"
+ "host dev [<dev>] - Set or retrieve the current host device\n"
+ "host commands use the \"hostfs\" device. The \"host\" device is used\n"
+ "with standard IO commands such as fatls or ext2load"
+);
diff --git a/roms/u-boot/cmd/i2c.c b/roms/u-boot/cmd/i2c.c
new file mode 100644
index 000000000..5d0e20787
--- /dev/null
+++ b/roms/u-boot/cmd/i2c.c
@@ -0,0 +1,2075 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009
+ * Sergey Kubushyn, himself, ksi@koi8.net
+ *
+ * Changes for unified multibus/multiadapter I2C support.
+ *
+ * (C) Copyright 2001
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
+ */
+
+/*
+ * I2C Functions similar to the standard memory functions.
+ *
+ * There are several parameters in many of the commands that bear further
+ * explanations:
+ *
+ * {i2c_chip} is the I2C chip address (the first byte sent on the bus).
+ * Each I2C chip on the bus has a unique address. On the I2C data bus,
+ * the address is the upper seven bits and the LSB is the "read/write"
+ * bit. Note that the {i2c_chip} address specified on the command
+ * line is not shifted up: e.g. a typical EEPROM memory chip may have
+ * an I2C address of 0x50, but the data put on the bus will be 0xA0
+ * for write and 0xA1 for read. This "non shifted" address notation
+ * matches at least half of the data sheets :-/.
+ *
+ * {addr} is the address (or offset) within the chip. Small memory
+ * chips have 8 bit addresses. Large memory chips have 16 bit
+ * addresses. Other memory chips have 9, 10, or 11 bit addresses.
+ * Many non-memory chips have multiple registers and {addr} is used
+ * as the register index. Some non-memory chips have only one register
+ * and therefore don't need any {addr} parameter.
+ *
+ * The default {addr} parameter is one byte (.1) which works well for
+ * memories and registers with 8 bits of address space.
+ *
+ * You can specify the length of the {addr} field with the optional .0,
+ * .1, or .2 modifier (similar to the .b, .w, .l modifier). If you are
+ * manipulating a single register device which doesn't use an address
+ * field, use "0.0" for the address and the ".0" length field will
+ * suppress the address in the I2C data stream. This also works for
+ * successive reads using the I2C auto-incrementing memory pointer.
+ *
+ * If you are manipulating a large memory with 2-byte addresses, use
+ * the .2 address modifier, e.g. 210.2 addresses location 528 (decimal).
+ *
+ * Then there are the unfortunate memory chips that spill the most
+ * significant 1, 2, or 3 bits of address into the chip address byte.
+ * This effectively makes one chip (logically) look like 2, 4, or
+ * 8 chips. This is handled (awkwardly) by #defining
+ * CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW and using the .1 modifier on the
+ * {addr} field (since .1 is the default, it doesn't actually have to
+ * be specified). Examples: given a memory chip at I2C chip address
+ * 0x50, the following would happen...
+ * i2c md 50 0 10 display 16 bytes starting at 0x000
+ * On the bus: <S> A0 00 <E> <S> A1 <rd> ... <rd>
+ * i2c md 50 100 10 display 16 bytes starting at 0x100
+ * On the bus: <S> A2 00 <E> <S> A3 <rd> ... <rd>
+ * i2c md 50 210 10 display 16 bytes starting at 0x210
+ * On the bus: <S> A4 10 <E> <S> A5 <rd> ... <rd>
+ * This is awfully ugly. It would be nice if someone would think up
+ * a better way of handling this.
+ *
+ * Adapted from cmd_mem.c which is copyright Wolfgang Denk (wd@denx.de).
+ */
+
+#include <common.h>
+#include <bootretry.h>
+#include <cli.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <edid.h>
+#include <errno.h>
+#include <i2c.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <u-boot/crc.h>
+
+/* Display values from last command.
+ * Memory modify remembered values are different from display memory.
+ */
+static uint i2c_dp_last_chip;
+static uint i2c_dp_last_addr;
+static uint i2c_dp_last_alen;
+static uint i2c_dp_last_length = 0x10;
+
+static uint i2c_mm_last_chip;
+static uint i2c_mm_last_addr;
+static uint i2c_mm_last_alen;
+
+/* If only one I2C bus is present, the list of devices to ignore when
+ * the probe command is issued is represented by a 1D array of addresses.
+ * When multiple buses are present, the list is an array of bus-address
+ * pairs. The following macros take care of this */
+
+#if defined(CONFIG_SYS_I2C_NOPROBES)
+#if defined(CONFIG_SYS_I2C) || defined(CONFIG_I2C_MULTI_BUS)
+static struct
+{
+ uchar bus;
+ uchar addr;
+} i2c_no_probes[] = CONFIG_SYS_I2C_NOPROBES;
+#define GET_BUS_NUM i2c_get_bus_num()
+#define COMPARE_BUS(b,i) (i2c_no_probes[(i)].bus == (b))
+#define COMPARE_ADDR(a,i) (i2c_no_probes[(i)].addr == (a))
+#define NO_PROBE_ADDR(i) i2c_no_probes[(i)].addr
+#else /* single bus */
+static uchar i2c_no_probes[] = CONFIG_SYS_I2C_NOPROBES;
+#define GET_BUS_NUM 0
+#define COMPARE_BUS(b,i) ((b) == 0) /* Make compiler happy */
+#define COMPARE_ADDR(a,i) (i2c_no_probes[(i)] == (a))
+#define NO_PROBE_ADDR(i) i2c_no_probes[(i)]
+#endif /* defined(CONFIG_SYS_I2C) */
+#endif
+
+#define DISP_LINE_LEN 16
+
+/*
+ * Default for driver model is to use the chip's existing address length.
+ * For legacy code, this is not stored, so we need to use a suitable
+ * default.
+ */
+#if CONFIG_IS_ENABLED(DM_I2C)
+#define DEFAULT_ADDR_LEN (-1)
+#else
+#define DEFAULT_ADDR_LEN 1
+#endif
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+static struct udevice *i2c_cur_bus;
+
+static int cmd_i2c_set_bus_num(unsigned int busnum)
+{
+ struct udevice *bus;
+ int ret;
+
+ ret = uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus);
+ if (ret) {
+ debug("%s: No bus %d\n", __func__, busnum);
+ return ret;
+ }
+ i2c_cur_bus = bus;
+
+ return 0;
+}
+
+static int i2c_get_cur_bus(struct udevice **busp)
+{
+#ifdef CONFIG_I2C_SET_DEFAULT_BUS_NUM
+ if (!i2c_cur_bus) {
+ if (cmd_i2c_set_bus_num(CONFIG_I2C_DEFAULT_BUS_NUMBER)) {
+ printf("Default I2C bus %d not found\n",
+ CONFIG_I2C_DEFAULT_BUS_NUMBER);
+ return -ENODEV;
+ }
+ }
+#endif
+
+ if (!i2c_cur_bus) {
+ puts("No I2C bus selected\n");
+ return -ENODEV;
+ }
+ *busp = i2c_cur_bus;
+
+ return 0;
+}
+
+static int i2c_get_cur_bus_chip(uint chip_addr, struct udevice **devp)
+{
+ struct udevice *bus;
+ int ret;
+
+ ret = i2c_get_cur_bus(&bus);
+ if (ret)
+ return ret;
+
+ return i2c_get_chip(bus, chip_addr, 1, devp);
+}
+
+#endif
+
+/**
+ * i2c_init_board() - Board-specific I2C bus init
+ *
+ * This function is the default no-op implementation of I2C bus
+ * initialization. This function can be overridden by board-specific
+ * implementation if needed.
+ */
+__weak
+void i2c_init_board(void)
+{
+}
+
+/* TODO: Implement architecture-specific get/set functions */
+
+/**
+ * i2c_get_bus_speed() - Return I2C bus speed
+ *
+ * This function is the default implementation of function for retrieveing
+ * the current I2C bus speed in Hz.
+ *
+ * A driver implementing runtime switching of I2C bus speed must override
+ * this function to report the speed correctly. Simple or legacy drivers
+ * can use this fallback.
+ *
+ * Returns I2C bus speed in Hz.
+ */
+#if !defined(CONFIG_SYS_I2C) && !CONFIG_IS_ENABLED(DM_I2C)
+/*
+ * TODO: Implement architecture-specific get/set functions
+ * Should go away, if we switched completely to new multibus support
+ */
+__weak
+unsigned int i2c_get_bus_speed(void)
+{
+ return CONFIG_SYS_I2C_SPEED;
+}
+
+/**
+ * i2c_set_bus_speed() - Configure I2C bus speed
+ * @speed: Newly set speed of the I2C bus in Hz
+ *
+ * This function is the default implementation of function for setting
+ * the I2C bus speed in Hz.
+ *
+ * A driver implementing runtime switching of I2C bus speed must override
+ * this function to report the speed correctly. Simple or legacy drivers
+ * can use this fallback.
+ *
+ * Returns zero on success, negative value on error.
+ */
+__weak
+int i2c_set_bus_speed(unsigned int speed)
+{
+ if (speed != CONFIG_SYS_I2C_SPEED)
+ return -1;
+
+ return 0;
+}
+#endif
+
+/**
+ * get_alen() - Small parser helper function to get address length
+ *
+ * Returns the address length.
+ */
+static uint get_alen(char *arg, int default_len)
+{
+ int j;
+ int alen;
+
+ alen = default_len;
+ for (j = 0; j < 8; j++) {
+ if (arg[j] == '.') {
+ alen = arg[j+1] - '0';
+ break;
+ } else if (arg[j] == '\0')
+ break;
+ }
+ return alen;
+}
+
+enum i2c_err_op {
+ I2C_ERR_READ,
+ I2C_ERR_WRITE,
+};
+
+static int i2c_report_err(int ret, enum i2c_err_op op)
+{
+ printf("Error %s the chip: %d\n",
+ op == I2C_ERR_READ ? "reading" : "writing", ret);
+
+ return CMD_RET_FAILURE;
+}
+
+/**
+ * do_i2c_read() - Handle the "i2c read" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
+ * Syntax:
+ * i2c read {i2c_chip} {devaddr}{.0, .1, .2} {len} {memaddr}
+ */
+static int do_i2c_read(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint chip;
+ uint devaddr, length;
+ int alen;
+ u_char *memaddr;
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+#endif
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ /*
+ * I2C chip address
+ */
+ chip = simple_strtoul(argv[1], NULL, 16);
+
+ /*
+ * I2C data address within the chip. This can be 1 or
+ * 2 bytes long. Some day it might be 3 bytes long :-).
+ */
+ devaddr = simple_strtoul(argv[2], NULL, 16);
+ alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
+ if (alen > 3)
+ return CMD_RET_USAGE;
+
+ /*
+ * Length is the number of objects, not number of bytes.
+ */
+ length = simple_strtoul(argv[3], NULL, 16);
+
+ /*
+ * memaddr is the address where to store things in memory
+ */
+ memaddr = (u_char *)simple_strtoul(argv[4], NULL, 16);
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret && alen != -1)
+ ret = i2c_set_chip_offset_len(dev, alen);
+ if (!ret)
+ ret = dm_i2c_read(dev, devaddr, memaddr, length);
+#else
+ ret = i2c_read(chip, devaddr, alen, memaddr, length);
+#endif
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+
+ return 0;
+}
+
+static int do_i2c_write(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint chip;
+ uint devaddr, length;
+ int alen;
+ u_char *memaddr;
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+ struct dm_i2c_chip *i2c_chip;
+#endif
+
+ if ((argc < 5) || (argc > 6))
+ return cmd_usage(cmdtp);
+
+ /*
+ * memaddr is the address where to store things in memory
+ */
+ memaddr = (u_char *)simple_strtoul(argv[1], NULL, 16);
+
+ /*
+ * I2C chip address
+ */
+ chip = simple_strtoul(argv[2], NULL, 16);
+
+ /*
+ * I2C data address within the chip. This can be 1 or
+ * 2 bytes long. Some day it might be 3 bytes long :-).
+ */
+ devaddr = simple_strtoul(argv[3], NULL, 16);
+ alen = get_alen(argv[3], DEFAULT_ADDR_LEN);
+ if (alen > 3)
+ return cmd_usage(cmdtp);
+
+ /*
+ * Length is the number of bytes.
+ */
+ length = simple_strtoul(argv[4], NULL, 16);
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret && alen != -1)
+ ret = i2c_set_chip_offset_len(dev, alen);
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_WRITE);
+ i2c_chip = dev_get_parent_plat(dev);
+ if (!i2c_chip)
+ return i2c_report_err(ret, I2C_ERR_WRITE);
+#endif
+
+ if (argc == 6 && !strcmp(argv[5], "-s")) {
+ /*
+ * Write all bytes in a single I2C transaction. If the target
+ * device is an EEPROM, it is your responsibility to not cross
+ * a page boundary. No write delay upon completion, take this
+ * into account if linking commands.
+ */
+#if CONFIG_IS_ENABLED(DM_I2C)
+ i2c_chip->flags &= ~DM_I2C_CHIP_WR_ADDRESS;
+ ret = dm_i2c_write(dev, devaddr, memaddr, length);
+#else
+ ret = i2c_write(chip, devaddr, alen, memaddr, length);
+#endif
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_WRITE);
+ } else {
+ /*
+ * Repeated addressing - perform <length> separate
+ * write transactions of one byte each
+ */
+ while (length-- > 0) {
+#if CONFIG_IS_ENABLED(DM_I2C)
+ i2c_chip->flags |= DM_I2C_CHIP_WR_ADDRESS;
+ ret = dm_i2c_write(dev, devaddr++, memaddr++, 1);
+#else
+ ret = i2c_write(chip, devaddr++, alen, memaddr++, 1);
+#endif
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_WRITE);
+/*
+ * No write delay with FRAM devices.
+ */
+#if !defined(CONFIG_SYS_I2C_FRAM)
+ udelay(11000);
+#endif
+ }
+ }
+ return 0;
+}
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+static int do_i2c_flags(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ uint flags;
+ int chip;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ chip = simple_strtoul(argv[1], NULL, 16);
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+
+ if (argc > 2) {
+ flags = simple_strtoul(argv[2], NULL, 16);
+ ret = i2c_set_chip_flags(dev, flags);
+ } else {
+ ret = i2c_get_chip_flags(dev, &flags);
+ if (!ret)
+ printf("%x\n", flags);
+ }
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+
+ return 0;
+}
+
+static int do_i2c_olen(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ uint olen;
+ int chip;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ chip = simple_strtoul(argv[1], NULL, 16);
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+
+ if (argc > 2) {
+ olen = simple_strtoul(argv[2], NULL, 16);
+ ret = i2c_set_chip_offset_len(dev, olen);
+ } else {
+ ret = i2c_get_chip_offset_len(dev);
+ if (ret >= 0) {
+ printf("%x\n", ret);
+ ret = 0;
+ }
+ }
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+
+ return 0;
+}
+#endif
+
+/**
+ * do_i2c_md() - Handle the "i2c md" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
+ * Syntax:
+ * i2c md {i2c_chip} {addr}{.0, .1, .2} {len}
+ */
+static int do_i2c_md(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint chip;
+ uint addr, length;
+ int alen;
+ int j, nbytes, linebytes;
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+#endif
+
+ /* We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ chip = i2c_dp_last_chip;
+ addr = i2c_dp_last_addr;
+ alen = i2c_dp_last_alen;
+ length = i2c_dp_last_length;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /*
+ * New command specified.
+ */
+
+ /*
+ * I2C chip address
+ */
+ chip = simple_strtoul(argv[1], NULL, 16);
+
+ /*
+ * I2C data address within the chip. This can be 1 or
+ * 2 bytes long. Some day it might be 3 bytes long :-).
+ */
+ addr = simple_strtoul(argv[2], NULL, 16);
+ alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
+ if (alen > 3)
+ return CMD_RET_USAGE;
+
+ /*
+ * If another parameter, it is the length to display.
+ * Length is the number of objects, not number of bytes.
+ */
+ if (argc > 3)
+ length = simple_strtoul(argv[3], NULL, 16);
+ }
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret && alen != -1)
+ ret = i2c_set_chip_offset_len(dev, alen);
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+#endif
+
+ /*
+ * Print the lines.
+ *
+ * We buffer all read data, so we can make sure data is read only
+ * once.
+ */
+ nbytes = length;
+ do {
+ unsigned char linebuf[DISP_LINE_LEN];
+ unsigned char *cp;
+
+ linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_read(dev, addr, linebuf, linebytes);
+#else
+ ret = i2c_read(chip, addr, alen, linebuf, linebytes);
+#endif
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+ else {
+ printf("%04x:", addr);
+ cp = linebuf;
+ for (j=0; j<linebytes; j++) {
+ printf(" %02x", *cp++);
+ addr++;
+ }
+ puts (" ");
+ cp = linebuf;
+ for (j=0; j<linebytes; j++) {
+ if ((*cp < 0x20) || (*cp > 0x7e))
+ puts (".");
+ else
+ printf("%c", *cp);
+ cp++;
+ }
+ putc ('\n');
+ }
+ nbytes -= linebytes;
+ } while (nbytes > 0);
+
+ i2c_dp_last_chip = chip;
+ i2c_dp_last_addr = addr;
+ i2c_dp_last_alen = alen;
+ i2c_dp_last_length = length;
+
+ return 0;
+}
+
+/**
+ * do_i2c_mw() - Handle the "i2c mw" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
+ * Syntax:
+ * i2c mw {i2c_chip} {addr}{.0, .1, .2} {data} [{count}]
+ */
+static int do_i2c_mw(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint chip;
+ ulong addr;
+ int alen;
+ uchar byte;
+ int count;
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+#endif
+
+ if ((argc < 4) || (argc > 5))
+ return CMD_RET_USAGE;
+
+ /*
+ * Chip is always specified.
+ */
+ chip = simple_strtoul(argv[1], NULL, 16);
+
+ /*
+ * Address is always specified.
+ */
+ addr = simple_strtoul(argv[2], NULL, 16);
+ alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
+ if (alen > 3)
+ return CMD_RET_USAGE;
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret && alen != -1)
+ ret = i2c_set_chip_offset_len(dev, alen);
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_WRITE);
+#endif
+ /*
+ * Value to write is always specified.
+ */
+ byte = simple_strtoul(argv[3], NULL, 16);
+
+ /*
+ * Optional count
+ */
+ if (argc == 5)
+ count = simple_strtoul(argv[4], NULL, 16);
+ else
+ count = 1;
+
+ while (count-- > 0) {
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_write(dev, addr++, &byte, 1);
+#else
+ ret = i2c_write(chip, addr++, alen, &byte, 1);
+#endif
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_WRITE);
+ /*
+ * Wait for the write to complete. The write can take
+ * up to 10mSec (we allow a little more time).
+ */
+/*
+ * No write delay with FRAM devices.
+ */
+#if !defined(CONFIG_SYS_I2C_FRAM)
+ udelay(11000);
+#endif
+ }
+
+ return 0;
+}
+
+/**
+ * do_i2c_crc() - Handle the "i2c crc32" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Calculate a CRC on memory
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
+ * Syntax:
+ * i2c crc32 {i2c_chip} {addr}{.0, .1, .2} {count}
+ */
+static int do_i2c_crc(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint chip;
+ ulong addr;
+ int alen;
+ int count;
+ uchar byte;
+ ulong crc;
+ ulong err;
+ int ret = 0;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+#endif
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ /*
+ * Chip is always specified.
+ */
+ chip = simple_strtoul(argv[1], NULL, 16);
+
+ /*
+ * Address is always specified.
+ */
+ addr = simple_strtoul(argv[2], NULL, 16);
+ alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
+ if (alen > 3)
+ return CMD_RET_USAGE;
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret && alen != -1)
+ ret = i2c_set_chip_offset_len(dev, alen);
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+#endif
+ /*
+ * Count is always specified
+ */
+ count = simple_strtoul(argv[3], NULL, 16);
+
+ printf ("CRC32 for %08lx ... %08lx ==> ", addr, addr + count - 1);
+ /*
+ * CRC a byte at a time. This is going to be slooow, but hey, the
+ * memories are small and slow too so hopefully nobody notices.
+ */
+ crc = 0;
+ err = 0;
+ while (count-- > 0) {
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_read(dev, addr, &byte, 1);
+#else
+ ret = i2c_read(chip, addr, alen, &byte, 1);
+#endif
+ if (ret)
+ err++;
+ crc = crc32(crc, &byte, 1);
+ addr++;
+ }
+ if (err > 0)
+ i2c_report_err(ret, I2C_ERR_READ);
+ else
+ printf ("%08lx\n", crc);
+
+ return 0;
+}
+
+/**
+ * mod_i2c_mem() - Handle the "i2c mm" and "i2c nm" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Modify memory.
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
+ * Syntax:
+ * i2c mm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
+ * i2c nm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
+ */
+static int mod_i2c_mem(struct cmd_tbl *cmdtp, int incrflag, int flag, int argc,
+ char *const argv[])
+{
+ uint chip;
+ ulong addr;
+ int alen;
+ ulong data;
+ int size = 1;
+ int nbytes;
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+#endif
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ bootretry_reset_cmd_timeout(); /* got a good command to get here */
+ /*
+ * We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ chip = i2c_mm_last_chip;
+ addr = i2c_mm_last_addr;
+ alen = i2c_mm_last_alen;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /*
+ * New command specified. Check for a size specification.
+ * Defaults to byte if no or incorrect specification.
+ */
+ size = cmd_get_data_size(argv[0], 1);
+
+ /*
+ * Chip is always specified.
+ */
+ chip = simple_strtoul(argv[1], NULL, 16);
+
+ /*
+ * Address is always specified.
+ */
+ addr = simple_strtoul(argv[2], NULL, 16);
+ alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
+ if (alen > 3)
+ return CMD_RET_USAGE;
+ }
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret && alen != -1)
+ ret = i2c_set_chip_offset_len(dev, alen);
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_WRITE);
+#endif
+
+ /*
+ * Print the address, followed by value. Then accept input for
+ * the next value. A non-converted value exits.
+ */
+ do {
+ printf("%08lx:", addr);
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_read(dev, addr, (uchar *)&data, size);
+#else
+ ret = i2c_read(chip, addr, alen, (uchar *)&data, size);
+#endif
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+
+ data = cpu_to_be32(data);
+ if (size == 1)
+ printf(" %02lx", (data >> 24) & 0x000000FF);
+ else if (size == 2)
+ printf(" %04lx", (data >> 16) & 0x0000FFFF);
+ else
+ printf(" %08lx", data);
+
+ nbytes = cli_readline(" ? ");
+ if (nbytes == 0) {
+ /*
+ * <CR> pressed as only input, don't modify current
+ * location and move to next.
+ */
+ if (incrflag)
+ addr += size;
+ nbytes = size;
+ /* good enough to not time out */
+ bootretry_reset_cmd_timeout();
+ }
+#ifdef CONFIG_BOOT_RETRY_TIME
+ else if (nbytes == -2)
+ break; /* timed out, exit the command */
+#endif
+ else {
+ char *endp;
+
+ data = simple_strtoul(console_buffer, &endp, 16);
+ if (size == 1)
+ data = data << 24;
+ else if (size == 2)
+ data = data << 16;
+ data = be32_to_cpu(data);
+ nbytes = endp - console_buffer;
+ if (nbytes) {
+ /*
+ * good enough to not time out
+ */
+ bootretry_reset_cmd_timeout();
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_write(dev, addr, (uchar *)&data,
+ size);
+#else
+ ret = i2c_write(chip, addr, alen,
+ (uchar *)&data, size);
+#endif
+ if (ret)
+ return i2c_report_err(ret,
+ I2C_ERR_WRITE);
+#ifdef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
+ udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
+#endif
+ if (incrflag)
+ addr += size;
+ }
+ }
+ } while (nbytes);
+
+ i2c_mm_last_chip = chip;
+ i2c_mm_last_addr = addr;
+ i2c_mm_last_alen = alen;
+
+ return 0;
+}
+
+/**
+ * do_i2c_probe() - Handle the "i2c probe" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
+ * Syntax:
+ * i2c probe {addr}
+ *
+ * Returns zero (success) if one or more I2C devices was found
+ */
+static int do_i2c_probe(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int j;
+ int addr = -1;
+ int found = 0;
+#if defined(CONFIG_SYS_I2C_NOPROBES)
+ int k, skip;
+ unsigned int bus = GET_BUS_NUM;
+#endif /* NOPROBES */
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *bus, *dev;
+
+ if (i2c_get_cur_bus(&bus))
+ return CMD_RET_FAILURE;
+#endif
+
+ if (argc == 2)
+ addr = simple_strtol(argv[1], 0, 16);
+
+ puts ("Valid chip addresses:");
+ for (j = 0; j < 128; j++) {
+ if ((0 <= addr) && (j != addr))
+ continue;
+
+#if defined(CONFIG_SYS_I2C_NOPROBES)
+ skip = 0;
+ for (k = 0; k < ARRAY_SIZE(i2c_no_probes); k++) {
+ if (COMPARE_BUS(bus, k) && COMPARE_ADDR(j, k)) {
+ skip = 1;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+#endif
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_probe(bus, j, 0, &dev);
+#else
+ ret = i2c_probe(j);
+#endif
+ if (ret == 0) {
+ printf(" %02X", j);
+ found++;
+ }
+ }
+ putc ('\n');
+
+#if defined(CONFIG_SYS_I2C_NOPROBES)
+ puts ("Excluded chip addresses:");
+ for (k = 0; k < ARRAY_SIZE(i2c_no_probes); k++) {
+ if (COMPARE_BUS(bus,k))
+ printf(" %02X", NO_PROBE_ADDR(k));
+ }
+ putc ('\n');
+#endif
+
+ return (0 == found);
+}
+
+/**
+ * do_i2c_loop() - Handle the "i2c loop" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ *
+ * Syntax:
+ * i2c loop {i2c_chip} {addr}{.0, .1, .2} [{length}] [{delay}]
+ * {length} - Number of bytes to read
+ * {delay} - A DECIMAL number and defaults to 1000 uSec
+ */
+static int do_i2c_loop(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint chip;
+ int alen;
+ uint addr;
+ uint length;
+ u_char bytes[16];
+ int delay;
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+#endif
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ /*
+ * Chip is always specified.
+ */
+ chip = simple_strtoul(argv[1], NULL, 16);
+
+ /*
+ * Address is always specified.
+ */
+ addr = simple_strtoul(argv[2], NULL, 16);
+ alen = get_alen(argv[2], DEFAULT_ADDR_LEN);
+ if (alen > 3)
+ return CMD_RET_USAGE;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret && alen != -1)
+ ret = i2c_set_chip_offset_len(dev, alen);
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_WRITE);
+#endif
+
+ /*
+ * Length is the number of objects, not number of bytes.
+ */
+ length = 1;
+ length = simple_strtoul(argv[3], NULL, 16);
+ if (length > sizeof(bytes))
+ length = sizeof(bytes);
+
+ /*
+ * The delay time (uSec) is optional.
+ */
+ delay = 1000;
+ if (argc > 3)
+ delay = simple_strtoul(argv[4], NULL, 10);
+ /*
+ * Run the loop...
+ */
+ while (1) {
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_read(dev, addr, bytes, length);
+#else
+ ret = i2c_read(chip, addr, alen, bytes, length);
+#endif
+ if (ret)
+ i2c_report_err(ret, I2C_ERR_READ);
+ udelay(delay);
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+/*
+ * The SDRAM command is separately configured because many
+ * (most?) embedded boards don't use SDRAM DIMMs.
+ *
+ * FIXME: Document and probably move elsewhere!
+ */
+#if defined(CONFIG_CMD_SDRAM)
+static void print_ddr2_tcyc (u_char const b)
+{
+ printf ("%d.", (b >> 4) & 0x0F);
+ switch (b & 0x0F) {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ printf ("%d ns\n", b & 0x0F);
+ break;
+ case 0xA:
+ puts ("25 ns\n");
+ break;
+ case 0xB:
+ puts ("33 ns\n");
+ break;
+ case 0xC:
+ puts ("66 ns\n");
+ break;
+ case 0xD:
+ puts ("75 ns\n");
+ break;
+ default:
+ puts ("?? ns\n");
+ break;
+ }
+}
+
+static void decode_bits (u_char const b, char const *str[], int const do_once)
+{
+ u_char mask;
+
+ for (mask = 0x80; mask != 0x00; mask >>= 1, ++str) {
+ if (b & mask) {
+ puts (*str);
+ if (do_once)
+ return;
+ }
+ }
+}
+
+/*
+ * Syntax:
+ * i2c sdram {i2c_chip}
+ */
+static int do_sdram(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum { unknown, EDO, SDRAM, DDR, DDR2, DDR3, DDR4 } type;
+
+ uint chip;
+ u_char data[128];
+ u_char cksum;
+ int j, ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+#endif
+
+ static const char *decode_CAS_DDR2[] = {
+ " TBD", " 6", " 5", " 4", " 3", " 2", " TBD", " TBD"
+ };
+
+ static const char *decode_CAS_default[] = {
+ " TBD", " 7", " 6", " 5", " 4", " 3", " 2", " 1"
+ };
+
+ static const char *decode_CS_WE_default[] = {
+ " TBD", " 6", " 5", " 4", " 3", " 2", " 1", " 0"
+ };
+
+ static const char *decode_byte21_default[] = {
+ " TBD (bit 7)\n",
+ " Redundant row address\n",
+ " Differential clock input\n",
+ " Registerd DQMB inputs\n",
+ " Buffered DQMB inputs\n",
+ " On-card PLL\n",
+ " Registered address/control lines\n",
+ " Buffered address/control lines\n"
+ };
+
+ static const char *decode_byte22_DDR2[] = {
+ " TBD (bit 7)\n",
+ " TBD (bit 6)\n",
+ " TBD (bit 5)\n",
+ " TBD (bit 4)\n",
+ " TBD (bit 3)\n",
+ " Supports partial array self refresh\n",
+ " Supports 50 ohm ODT\n",
+ " Supports weak driver\n"
+ };
+
+ static const char *decode_row_density_DDR2[] = {
+ "512 MiB", "256 MiB", "128 MiB", "16 GiB",
+ "8 GiB", "4 GiB", "2 GiB", "1 GiB"
+ };
+
+ static const char *decode_row_density_default[] = {
+ "512 MiB", "256 MiB", "128 MiB", "64 MiB",
+ "32 MiB", "16 MiB", "8 MiB", "4 MiB"
+ };
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /*
+ * Chip is always specified.
+ */
+ chip = simple_strtoul (argv[1], NULL, 16);
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret)
+ ret = dm_i2c_read(dev, 0, data, sizeof(data));
+#else
+ ret = i2c_read(chip, 0, 1, data, sizeof(data));
+#endif
+ if (ret) {
+ puts ("No SDRAM Serial Presence Detect found.\n");
+ return 1;
+ }
+
+ cksum = 0;
+ for (j = 0; j < 63; j++) {
+ cksum += data[j];
+ }
+ if (cksum != data[63]) {
+ printf ("WARNING: Configuration data checksum failure:\n"
+ " is 0x%02x, calculated 0x%02x\n", data[63], cksum);
+ }
+ printf ("SPD data revision %d.%d\n",
+ (data[62] >> 4) & 0x0F, data[62] & 0x0F);
+ printf ("Bytes used 0x%02X\n", data[0]);
+ printf ("Serial memory size 0x%02X\n", 1 << data[1]);
+
+ puts ("Memory type ");
+ switch (data[2]) {
+ case 2:
+ type = EDO;
+ puts ("EDO\n");
+ break;
+ case 4:
+ type = SDRAM;
+ puts ("SDRAM\n");
+ break;
+ case 7:
+ type = DDR;
+ puts("DDR\n");
+ break;
+ case 8:
+ type = DDR2;
+ puts ("DDR2\n");
+ break;
+ case 11:
+ type = DDR3;
+ puts("DDR3\n");
+ break;
+ case 12:
+ type = DDR4;
+ puts("DDR4\n");
+ break;
+ default:
+ type = unknown;
+ puts ("unknown\n");
+ break;
+ }
+
+ puts ("Row address bits ");
+ if ((data[3] & 0x00F0) == 0)
+ printf ("%d\n", data[3] & 0x0F);
+ else
+ printf ("%d/%d\n", data[3] & 0x0F, (data[3] >> 4) & 0x0F);
+
+ puts ("Column address bits ");
+ if ((data[4] & 0x00F0) == 0)
+ printf ("%d\n", data[4] & 0x0F);
+ else
+ printf ("%d/%d\n", data[4] & 0x0F, (data[4] >> 4) & 0x0F);
+
+ switch (type) {
+ case DDR2:
+ printf ("Number of ranks %d\n",
+ (data[5] & 0x07) + 1);
+ break;
+ default:
+ printf ("Module rows %d\n", data[5]);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("Module data width %d bits\n", data[6]);
+ break;
+ default:
+ printf ("Module data width %d bits\n",
+ (data[7] << 8) | data[6]);
+ break;
+ }
+
+ puts ("Interface signal levels ");
+ switch(data[8]) {
+ case 0: puts ("TTL 5.0 V\n"); break;
+ case 1: puts ("LVTTL\n"); break;
+ case 2: puts ("HSTL 1.5 V\n"); break;
+ case 3: puts ("SSTL 3.3 V\n"); break;
+ case 4: puts ("SSTL 2.5 V\n"); break;
+ case 5: puts ("SSTL 1.8 V\n"); break;
+ default: puts ("unknown\n"); break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("SDRAM cycle time ");
+ print_ddr2_tcyc (data[9]);
+ break;
+ default:
+ printf ("SDRAM cycle time %d.%d ns\n",
+ (data[9] >> 4) & 0x0F, data[9] & 0x0F);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("SDRAM access time 0.%d%d ns\n",
+ (data[10] >> 4) & 0x0F, data[10] & 0x0F);
+ break;
+ default:
+ printf ("SDRAM access time %d.%d ns\n",
+ (data[10] >> 4) & 0x0F, data[10] & 0x0F);
+ break;
+ }
+
+ puts ("EDC configuration ");
+ switch (data[11]) {
+ case 0: puts ("None\n"); break;
+ case 1: puts ("Parity\n"); break;
+ case 2: puts ("ECC\n"); break;
+ default: puts ("unknown\n"); break;
+ }
+
+ if ((data[12] & 0x80) == 0)
+ puts ("No self refresh, rate ");
+ else
+ puts ("Self refresh, rate ");
+
+ switch(data[12] & 0x7F) {
+ case 0: puts ("15.625 us\n"); break;
+ case 1: puts ("3.9 us\n"); break;
+ case 2: puts ("7.8 us\n"); break;
+ case 3: puts ("31.3 us\n"); break;
+ case 4: puts ("62.5 us\n"); break;
+ case 5: puts ("125 us\n"); break;
+ default: puts ("unknown\n"); break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("SDRAM width (primary) %d\n", data[13]);
+ break;
+ default:
+ printf ("SDRAM width (primary) %d\n", data[13] & 0x7F);
+ if ((data[13] & 0x80) != 0) {
+ printf (" (second bank) %d\n",
+ 2 * (data[13] & 0x7F));
+ }
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ if (data[14] != 0)
+ printf ("EDC width %d\n", data[14]);
+ break;
+ default:
+ if (data[14] != 0) {
+ printf ("EDC width %d\n",
+ data[14] & 0x7F);
+
+ if ((data[14] & 0x80) != 0) {
+ printf (" (second bank) %d\n",
+ 2 * (data[14] & 0x7F));
+ }
+ }
+ break;
+ }
+
+ if (DDR2 != type) {
+ printf ("Min clock delay, back-to-back random column addresses "
+ "%d\n", data[15]);
+ }
+
+ puts ("Burst length(s) ");
+ if (data[16] & 0x80) puts (" Page");
+ if (data[16] & 0x08) puts (" 8");
+ if (data[16] & 0x04) puts (" 4");
+ if (data[16] & 0x02) puts (" 2");
+ if (data[16] & 0x01) puts (" 1");
+ putc ('\n');
+ printf ("Number of banks %d\n", data[17]);
+
+ switch (type) {
+ case DDR2:
+ puts ("CAS latency(s) ");
+ decode_bits (data[18], decode_CAS_DDR2, 0);
+ putc ('\n');
+ break;
+ default:
+ puts ("CAS latency(s) ");
+ decode_bits (data[18], decode_CAS_default, 0);
+ putc ('\n');
+ break;
+ }
+
+ if (DDR2 != type) {
+ puts ("CS latency(s) ");
+ decode_bits (data[19], decode_CS_WE_default, 0);
+ putc ('\n');
+ }
+
+ if (DDR2 != type) {
+ puts ("WE latency(s) ");
+ decode_bits (data[20], decode_CS_WE_default, 0);
+ putc ('\n');
+ }
+
+ switch (type) {
+ case DDR2:
+ puts ("Module attributes:\n");
+ if (data[21] & 0x80)
+ puts (" TBD (bit 7)\n");
+ if (data[21] & 0x40)
+ puts (" Analysis probe installed\n");
+ if (data[21] & 0x20)
+ puts (" TBD (bit 5)\n");
+ if (data[21] & 0x10)
+ puts (" FET switch external enable\n");
+ printf (" %d PLLs on DIMM\n", (data[21] >> 2) & 0x03);
+ if (data[20] & 0x11) {
+ printf (" %d active registers on DIMM\n",
+ (data[21] & 0x03) + 1);
+ }
+ break;
+ default:
+ puts ("Module attributes:\n");
+ if (!data[21])
+ puts (" (none)\n");
+ else
+ decode_bits (data[21], decode_byte21_default, 0);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ decode_bits (data[22], decode_byte22_DDR2, 0);
+ break;
+ default:
+ puts ("Device attributes:\n");
+ if (data[22] & 0x80) puts (" TBD (bit 7)\n");
+ if (data[22] & 0x40) puts (" TBD (bit 6)\n");
+ if (data[22] & 0x20) puts (" Upper Vcc tolerance 5%\n");
+ else puts (" Upper Vcc tolerance 10%\n");
+ if (data[22] & 0x10) puts (" Lower Vcc tolerance 5%\n");
+ else puts (" Lower Vcc tolerance 10%\n");
+ if (data[22] & 0x08) puts (" Supports write1/read burst\n");
+ if (data[22] & 0x04) puts (" Supports precharge all\n");
+ if (data[22] & 0x02) puts (" Supports auto precharge\n");
+ if (data[22] & 0x01) puts (" Supports early RAS# precharge\n");
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("SDRAM cycle time (2nd highest CAS latency) ");
+ print_ddr2_tcyc (data[23]);
+ break;
+ default:
+ printf ("SDRAM cycle time (2nd highest CAS latency) %d."
+ "%d ns\n", (data[23] >> 4) & 0x0F, data[23] & 0x0F);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("SDRAM access from clock (2nd highest CAS latency) 0."
+ "%d%d ns\n", (data[24] >> 4) & 0x0F, data[24] & 0x0F);
+ break;
+ default:
+ printf ("SDRAM access from clock (2nd highest CAS latency) %d."
+ "%d ns\n", (data[24] >> 4) & 0x0F, data[24] & 0x0F);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("SDRAM cycle time (3rd highest CAS latency) ");
+ print_ddr2_tcyc (data[25]);
+ break;
+ default:
+ printf ("SDRAM cycle time (3rd highest CAS latency) %d."
+ "%d ns\n", (data[25] >> 4) & 0x0F, data[25] & 0x0F);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("SDRAM access from clock (3rd highest CAS latency) 0."
+ "%d%d ns\n", (data[26] >> 4) & 0x0F, data[26] & 0x0F);
+ break;
+ default:
+ printf ("SDRAM access from clock (3rd highest CAS latency) %d."
+ "%d ns\n", (data[26] >> 4) & 0x0F, data[26] & 0x0F);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("Minimum row precharge %d.%02d ns\n",
+ (data[27] >> 2) & 0x3F, 25 * (data[27] & 0x03));
+ break;
+ default:
+ printf ("Minimum row precharge %d ns\n", data[27]);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("Row active to row active min %d.%02d ns\n",
+ (data[28] >> 2) & 0x3F, 25 * (data[28] & 0x03));
+ break;
+ default:
+ printf ("Row active to row active min %d ns\n", data[28]);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("RAS to CAS delay min %d.%02d ns\n",
+ (data[29] >> 2) & 0x3F, 25 * (data[29] & 0x03));
+ break;
+ default:
+ printf ("RAS to CAS delay min %d ns\n", data[29]);
+ break;
+ }
+
+ printf ("Minimum RAS pulse width %d ns\n", data[30]);
+
+ switch (type) {
+ case DDR2:
+ puts ("Density of each row ");
+ decode_bits (data[31], decode_row_density_DDR2, 1);
+ putc ('\n');
+ break;
+ default:
+ puts ("Density of each row ");
+ decode_bits (data[31], decode_row_density_default, 1);
+ putc ('\n');
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ puts ("Command and Address setup ");
+ if (data[32] >= 0xA0) {
+ printf ("1.%d%d ns\n",
+ ((data[32] >> 4) & 0x0F) - 10, data[32] & 0x0F);
+ } else {
+ printf ("0.%d%d ns\n",
+ ((data[32] >> 4) & 0x0F), data[32] & 0x0F);
+ }
+ break;
+ default:
+ printf ("Command and Address setup %c%d.%d ns\n",
+ (data[32] & 0x80) ? '-' : '+',
+ (data[32] >> 4) & 0x07, data[32] & 0x0F);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ puts ("Command and Address hold ");
+ if (data[33] >= 0xA0) {
+ printf ("1.%d%d ns\n",
+ ((data[33] >> 4) & 0x0F) - 10, data[33] & 0x0F);
+ } else {
+ printf ("0.%d%d ns\n",
+ ((data[33] >> 4) & 0x0F), data[33] & 0x0F);
+ }
+ break;
+ default:
+ printf ("Command and Address hold %c%d.%d ns\n",
+ (data[33] & 0x80) ? '-' : '+',
+ (data[33] >> 4) & 0x07, data[33] & 0x0F);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("Data signal input setup 0.%d%d ns\n",
+ (data[34] >> 4) & 0x0F, data[34] & 0x0F);
+ break;
+ default:
+ printf ("Data signal input setup %c%d.%d ns\n",
+ (data[34] & 0x80) ? '-' : '+',
+ (data[34] >> 4) & 0x07, data[34] & 0x0F);
+ break;
+ }
+
+ switch (type) {
+ case DDR2:
+ printf ("Data signal input hold 0.%d%d ns\n",
+ (data[35] >> 4) & 0x0F, data[35] & 0x0F);
+ break;
+ default:
+ printf ("Data signal input hold %c%d.%d ns\n",
+ (data[35] & 0x80) ? '-' : '+',
+ (data[35] >> 4) & 0x07, data[35] & 0x0F);
+ break;
+ }
+
+ puts ("Manufacturer's JEDEC ID ");
+ for (j = 64; j <= 71; j++)
+ printf ("%02X ", data[j]);
+ putc ('\n');
+ printf ("Manufacturing Location %02X\n", data[72]);
+ puts ("Manufacturer's Part Number ");
+ for (j = 73; j <= 90; j++)
+ printf ("%02X ", data[j]);
+ putc ('\n');
+ printf ("Revision Code %02X %02X\n", data[91], data[92]);
+ printf ("Manufacturing Date %02X %02X\n", data[93], data[94]);
+ puts ("Assembly Serial Number ");
+ for (j = 95; j <= 98; j++)
+ printf ("%02X ", data[j]);
+ putc ('\n');
+
+ if (DDR2 != type) {
+ printf ("Speed rating PC%d\n",
+ data[126] == 0x66 ? 66 : data[126]);
+ }
+ return 0;
+}
+#endif
+
+/*
+ * Syntax:
+ * i2c edid {i2c_chip}
+ */
+#if defined(CONFIG_I2C_EDID)
+int do_edid(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ uint chip;
+ struct edid1_info edid;
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+#endif
+
+ if (argc < 2) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ chip = simple_strtoul(argv[1], NULL, 16);
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret)
+ ret = dm_i2c_read(dev, 0, (uchar *)&edid, sizeof(edid));
+#else
+ ret = i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid));
+#endif
+ if (ret)
+ return i2c_report_err(ret, I2C_ERR_READ);
+
+ if (edid_check_info(&edid)) {
+ puts("Content isn't valid EDID.\n");
+ return 1;
+ }
+
+ edid_print_info(&edid);
+ return 0;
+
+}
+#endif /* CONFIG_I2C_EDID */
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+static void show_bus(struct udevice *bus)
+{
+ struct udevice *dev;
+
+ printf("Bus %d:\t%s", dev_seq(bus), bus->name);
+ if (device_active(bus))
+ printf(" (active %d)", dev_seq(bus));
+ printf("\n");
+ for (device_find_first_child(bus, &dev);
+ dev;
+ device_find_next_child(&dev)) {
+ struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
+
+ printf(" %02x: %s, offset len %x, flags %x\n",
+ chip->chip_addr, dev->name, chip->offset_len,
+ chip->flags);
+ }
+}
+#endif
+
+/**
+ * do_i2c_show_bus() - Handle the "i2c bus" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero always.
+ */
+#if defined(CONFIG_SYS_I2C) || CONFIG_IS_ENABLED(DM_I2C)
+static int do_i2c_show_bus(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc == 1) {
+ /* show all busses */
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *bus;
+ struct uclass *uc;
+ int ret;
+
+ ret = uclass_get(UCLASS_I2C, &uc);
+ if (ret)
+ return CMD_RET_FAILURE;
+ uclass_foreach_dev(bus, uc)
+ show_bus(bus);
+#else
+ int i;
+
+ for (i = 0; i < CONFIG_SYS_NUM_I2C_BUSES; i++) {
+ printf("Bus %d:\t%s", i, I2C_ADAP_NR(i)->name);
+#ifndef CONFIG_SYS_I2C_DIRECT_BUS
+ int j;
+
+ for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) {
+ if (i2c_bus[i].next_hop[j].chip == 0)
+ break;
+ printf("->%s@0x%2x:%d",
+ i2c_bus[i].next_hop[j].mux.name,
+ i2c_bus[i].next_hop[j].chip,
+ i2c_bus[i].next_hop[j].channel);
+ }
+#endif
+ printf("\n");
+ }
+#endif
+ } else {
+ int i;
+
+ /* show specific bus */
+ i = simple_strtoul(argv[1], NULL, 10);
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *bus;
+ int ret;
+
+ ret = uclass_get_device_by_seq(UCLASS_I2C, i, &bus);
+ if (ret) {
+ printf("Invalid bus %d: err=%d\n", i, ret);
+ return CMD_RET_FAILURE;
+ }
+ show_bus(bus);
+#else
+ if (i >= CONFIG_SYS_NUM_I2C_BUSES) {
+ printf("Invalid bus %d\n", i);
+ return -1;
+ }
+ printf("Bus %d:\t%s", i, I2C_ADAP_NR(i)->name);
+#ifndef CONFIG_SYS_I2C_DIRECT_BUS
+ int j;
+ for (j = 0; j < CONFIG_SYS_I2C_MAX_HOPS; j++) {
+ if (i2c_bus[i].next_hop[j].chip == 0)
+ break;
+ printf("->%s@0x%2x:%d",
+ i2c_bus[i].next_hop[j].mux.name,
+ i2c_bus[i].next_hop[j].chip,
+ i2c_bus[i].next_hop[j].channel);
+ }
+#endif
+ printf("\n");
+#endif
+ }
+
+ return 0;
+}
+#endif
+
+/**
+ * do_i2c_bus_num() - Handle the "i2c dev" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+#if defined(CONFIG_SYS_I2C) || defined(CONFIG_I2C_MULTI_BUS) || \
+ CONFIG_IS_ENABLED(DM_I2C)
+static int do_i2c_bus_num(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret = 0;
+ int bus_no;
+
+ if (argc == 1) {
+ /* querying current setting */
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *bus;
+
+ if (!i2c_get_cur_bus(&bus))
+ bus_no = dev_seq(bus);
+ else
+ bus_no = -1;
+#else
+ bus_no = i2c_get_bus_num();
+#endif
+ printf("Current bus is %d\n", bus_no);
+ } else {
+ bus_no = simple_strtoul(argv[1], NULL, 10);
+#if defined(CONFIG_SYS_I2C)
+ if (bus_no >= CONFIG_SYS_NUM_I2C_BUSES) {
+ printf("Invalid bus %d\n", bus_no);
+ return -1;
+ }
+#endif
+ printf("Setting bus to %d\n", bus_no);
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = cmd_i2c_set_bus_num(bus_no);
+#else
+ ret = i2c_set_bus_num(bus_no);
+#endif
+ if (ret)
+ printf("Failure changing bus number (%d)\n", ret);
+ }
+
+ return ret ? CMD_RET_FAILURE : 0;
+}
+#endif /* defined(CONFIG_SYS_I2C) */
+
+/**
+ * do_i2c_bus_speed() - Handle the "i2c speed" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_i2c_bus_speed(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int speed, ret=0;
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *bus;
+
+ if (i2c_get_cur_bus(&bus))
+ return 1;
+#endif
+ if (argc == 1) {
+#if CONFIG_IS_ENABLED(DM_I2C)
+ speed = dm_i2c_get_bus_speed(bus);
+#else
+ speed = i2c_get_bus_speed();
+#endif
+ /* querying current speed */
+ printf("Current bus speed=%d\n", speed);
+ } else {
+ speed = simple_strtoul(argv[1], NULL, 10);
+ printf("Setting bus speed to %d Hz\n", speed);
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_set_bus_speed(bus, speed);
+#else
+ ret = i2c_set_bus_speed(speed);
+#endif
+ if (ret)
+ printf("Failure changing bus speed (%d)\n", ret);
+ }
+
+ return ret ? CMD_RET_FAILURE : 0;
+}
+
+/**
+ * do_i2c_mm() - Handle the "i2c mm" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_i2c_mm(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return mod_i2c_mem (cmdtp, 1, flag, argc, argv);
+}
+
+/**
+ * do_i2c_nm() - Handle the "i2c nm" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_i2c_nm(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return mod_i2c_mem (cmdtp, 0, flag, argc, argv);
+}
+
+/**
+ * do_i2c_reset() - Handle the "i2c reset" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero always.
+ */
+static int do_i2c_reset(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *bus;
+
+ if (i2c_get_cur_bus(&bus))
+ return CMD_RET_FAILURE;
+ if (i2c_deblock(bus)) {
+ printf("Error: Not supported by the driver\n");
+ return CMD_RET_FAILURE;
+ }
+#elif defined(CONFIG_SYS_I2C)
+ i2c_init(I2C_ADAP->speed, I2C_ADAP->slaveaddr);
+#else
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+#endif
+ return 0;
+}
+
+static struct cmd_tbl cmd_i2c_sub[] = {
+#if defined(CONFIG_SYS_I2C) || CONFIG_IS_ENABLED(DM_I2C)
+ U_BOOT_CMD_MKENT(bus, 1, 1, do_i2c_show_bus, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(crc32, 3, 1, do_i2c_crc, "", ""),
+#if defined(CONFIG_SYS_I2C) || \
+ defined(CONFIG_I2C_MULTI_BUS) || CONFIG_IS_ENABLED(DM_I2C)
+ U_BOOT_CMD_MKENT(dev, 1, 1, do_i2c_bus_num, "", ""),
+#endif /* CONFIG_I2C_MULTI_BUS */
+#if defined(CONFIG_I2C_EDID)
+ U_BOOT_CMD_MKENT(edid, 1, 1, do_edid, "", ""),
+#endif /* CONFIG_I2C_EDID */
+ U_BOOT_CMD_MKENT(loop, 3, 1, do_i2c_loop, "", ""),
+ U_BOOT_CMD_MKENT(md, 3, 1, do_i2c_md, "", ""),
+ U_BOOT_CMD_MKENT(mm, 2, 1, do_i2c_mm, "", ""),
+ U_BOOT_CMD_MKENT(mw, 3, 1, do_i2c_mw, "", ""),
+ U_BOOT_CMD_MKENT(nm, 2, 1, do_i2c_nm, "", ""),
+ U_BOOT_CMD_MKENT(probe, 0, 1, do_i2c_probe, "", ""),
+ U_BOOT_CMD_MKENT(read, 5, 1, do_i2c_read, "", ""),
+ U_BOOT_CMD_MKENT(write, 6, 0, do_i2c_write, "", ""),
+#if CONFIG_IS_ENABLED(DM_I2C)
+ U_BOOT_CMD_MKENT(flags, 2, 1, do_i2c_flags, "", ""),
+ U_BOOT_CMD_MKENT(olen, 2, 1, do_i2c_olen, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(reset, 0, 1, do_i2c_reset, "", ""),
+#if defined(CONFIG_CMD_SDRAM)
+ U_BOOT_CMD_MKENT(sdram, 1, 1, do_sdram, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(speed, 1, 1, do_i2c_bus_speed, "", ""),
+};
+
+static __maybe_unused void i2c_reloc(void)
+{
+ static int relocated;
+
+ if (!relocated) {
+ fixup_cmdtable(cmd_i2c_sub, ARRAY_SIZE(cmd_i2c_sub));
+ relocated = 1;
+ };
+}
+
+/**
+ * do_i2c() - Handle the "i2c" command-line command
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Returns zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int do_i2c(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *c;
+
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+ i2c_reloc();
+#endif
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* Strip off leading 'i2c' command argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], &cmd_i2c_sub[0], ARRAY_SIZE(cmd_i2c_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+/***************************************************/
+#ifdef CONFIG_SYS_LONGHELP
+static char i2c_help_text[] =
+#if defined(CONFIG_SYS_I2C) || CONFIG_IS_ENABLED(DM_I2C)
+ "bus [muxtype:muxaddr:muxchannel] - show I2C bus info\n"
+ "i2c " /* That's the prefix for the crc32 command below. */
+#endif
+ "crc32 chip address[.0, .1, .2] count - compute CRC32 checksum\n"
+#if defined(CONFIG_SYS_I2C) || \
+ defined(CONFIG_I2C_MULTI_BUS) || CONFIG_IS_ENABLED(DM_I2C)
+ "i2c dev [dev] - show or set current I2C bus\n"
+#endif /* CONFIG_I2C_MULTI_BUS */
+#if defined(CONFIG_I2C_EDID)
+ "i2c edid chip - print EDID configuration information\n"
+#endif /* CONFIG_I2C_EDID */
+ "i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device\n"
+ "i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device\n"
+ "i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)\n"
+ "i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill)\n"
+ "i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)\n"
+ "i2c probe [address] - test for and show device(s) on the I2C bus\n"
+ "i2c read chip address[.0, .1, .2] length memaddress - read to memory\n"
+ "i2c write memaddress chip address[.0, .1, .2] length [-s] - write memory\n"
+ " to I2C; the -s option selects bulk write in a single transaction\n"
+#if CONFIG_IS_ENABLED(DM_I2C)
+ "i2c flags chip [flags] - set or get chip flags\n"
+ "i2c olen chip [offset_length] - set or get chip offset length\n"
+#endif
+ "i2c reset - re-init the I2C Controller\n"
+#if defined(CONFIG_CMD_SDRAM)
+ "i2c sdram chip - print SDRAM configuration information\n"
+#endif
+ "i2c speed [speed] - show or set I2C bus speed";
+#endif
+
+U_BOOT_CMD(
+ i2c, 7, 1, do_i2c,
+ "I2C sub-system",
+ i2c_help_text
+);
diff --git a/roms/u-boot/cmd/ide.c b/roms/u-boot/cmd/ide.c
new file mode 100644
index 000000000..b78c38e15
--- /dev/null
+++ b/roms/u-boot/cmd/ide.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2011
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * IDE support
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <config.h>
+#include <watchdog.h>
+#include <command.h>
+#include <image.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#include <ide.h>
+#include <ata.h>
+
+#ifdef CONFIG_LED_STATUS
+# include <status_led.h>
+#endif
+
+/* Current I/O Device */
+static int curr_device;
+
+int do_ide(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc == 2) {
+ if (strncmp(argv[1], "res", 3) == 0) {
+ puts("\nReset IDE: ");
+ ide_init();
+ return 0;
+ }
+ }
+
+ return blk_common_cmd(argc, argv, IF_TYPE_IDE, &curr_device);
+}
+
+int do_diskboot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return common_diskboot(cmdtp, "ide", argc, argv);
+}
+
+U_BOOT_CMD(ide, 5, 1, do_ide,
+ "IDE sub-system",
+ "reset - reset IDE controller\n"
+ "ide info - show available IDE devices\n"
+ "ide device [dev] - show or set current device\n"
+ "ide part [dev] - print partition table of one or all IDE devices\n"
+ "ide read addr blk# cnt\n"
+ "ide write addr blk# cnt - read/write `cnt'"
+ " blocks starting at block `blk#'\n"
+ " to/from memory address `addr'");
+
+U_BOOT_CMD(diskboot, 3, 1, do_diskboot,
+ "boot from IDE device", "loadAddr dev:part");
diff --git a/roms/u-boot/cmd/ini.c b/roms/u-boot/cmd/ini.c
new file mode 100644
index 000000000..c075be623
--- /dev/null
+++ b/roms/u-boot/cmd/ini.c
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * inih -- simple .INI file parser
+ *
+ * Copyright (c) 2009, Brush Technology
+ * Copyright (c) 2012:
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.com
+ * All rights reserved.
+ *
+ * Go to the project home page for more info:
+ * http://code.google.com/p/inih/
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+
+#ifdef CONFIG_INI_MAX_LINE
+#define MAX_LINE CONFIG_INI_MAX_LINE
+#else
+#define MAX_LINE 200
+#endif
+
+#ifdef CONFIG_INI_MAX_SECTION
+#define MAX_SECTION CONFIG_INI_MAX_SECTION
+#else
+#define MAX_SECTION 50
+#endif
+
+#ifdef CONFIG_INI_MAX_NAME
+#define MAX_NAME CONFIG_INI_MAX_NAME
+#else
+#define MAX_NAME 50
+#endif
+
+/* Strip whitespace chars off end of given string, in place. Return s. */
+static char *rstrip(char *s)
+{
+ char *p = s + strlen(s);
+
+ while (p > s && isspace(*--p))
+ *p = '\0';
+ return s;
+}
+
+/* Return pointer to first non-whitespace char in given string. */
+static char *lskip(const char *s)
+{
+ while (*s && isspace(*s))
+ s++;
+ return (char *)s;
+}
+
+/* Return pointer to first char c or ';' comment in given string, or pointer to
+ null at end of string if neither found. ';' must be prefixed by a whitespace
+ character to register as a comment. */
+static char *find_char_or_comment(const char *s, char c)
+{
+ int was_whitespace = 0;
+
+ while (*s && *s != c && !(was_whitespace && *s == ';')) {
+ was_whitespace = isspace(*s);
+ s++;
+ }
+ return (char *)s;
+}
+
+/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
+static char *strncpy0(char *dest, const char *src, size_t size)
+{
+ strncpy(dest, src, size);
+ dest[size - 1] = '\0';
+ return dest;
+}
+
+/* Emulate the behavior of fgets but on memory */
+static char *memgets(char *str, int num, char **mem, size_t *memsize)
+{
+ char *end;
+ int len;
+ int newline = 1;
+
+ end = memchr(*mem, '\n', *memsize);
+ if (end == NULL) {
+ if (*memsize == 0)
+ return NULL;
+ end = *mem + *memsize;
+ newline = 0;
+ }
+ len = min((end - *mem) + newline, num);
+ memcpy(str, *mem, len);
+ if (len < num)
+ str[len] = '\0';
+
+ /* prepare the mem vars for the next call */
+ *memsize -= (end - *mem) + newline;
+ *mem += (end - *mem) + newline;
+
+ return str;
+}
+
+/* Parse given INI-style file. May have [section]s, name=value pairs
+ (whitespace stripped), and comments starting with ';' (semicolon). Section
+ is "" if name=value pair parsed before any section heading. name:value
+ pairs are also supported as a concession to Python's ConfigParser.
+
+ For each name=value pair parsed, call handler function with given user
+ pointer as well as section, name, and value (data only valid for duration
+ of handler call). Handler should return nonzero on success, zero on error.
+
+ Returns 0 on success, line number of first error on parse error (doesn't
+ stop on first error).
+*/
+static int ini_parse(char *filestart, size_t filelen,
+ int (*handler)(void *, char *, char *, char *), void *user)
+{
+ /* Uses a fair bit of stack (use heap instead if you need to) */
+ char line[MAX_LINE];
+ char section[MAX_SECTION] = "";
+ char prev_name[MAX_NAME] = "";
+
+ char *curmem = filestart;
+ char *start;
+ char *end;
+ char *name;
+ char *value;
+ size_t memleft = filelen;
+ int lineno = 0;
+ int error = 0;
+
+ /* Scan through file line by line */
+ while (memgets(line, sizeof(line), &curmem, &memleft) != NULL) {
+ lineno++;
+ start = lskip(rstrip(line));
+
+ if (*start == ';' || *start == '#') {
+ /*
+ * Per Python ConfigParser, allow '#' comments at start
+ * of line
+ */
+ }
+#if CONFIG_INI_ALLOW_MULTILINE
+ else if (*prev_name && *start && start > line) {
+ /*
+ * Non-blank line with leading whitespace, treat as
+ * continuation of previous name's value (as per Python
+ * ConfigParser).
+ */
+ if (!handler(user, section, prev_name, start) && !error)
+ error = lineno;
+ }
+#endif
+ else if (*start == '[') {
+ /* A "[section]" line */
+ end = find_char_or_comment(start + 1, ']');
+ if (*end == ']') {
+ *end = '\0';
+ strncpy0(section, start + 1, sizeof(section));
+ *prev_name = '\0';
+ } else if (!error) {
+ /* No ']' found on section line */
+ error = lineno;
+ }
+ } else if (*start && *start != ';') {
+ /* Not a comment, must be a name[=:]value pair */
+ end = find_char_or_comment(start, '=');
+ if (*end != '=')
+ end = find_char_or_comment(start, ':');
+ if (*end == '=' || *end == ':') {
+ *end = '\0';
+ name = rstrip(start);
+ value = lskip(end + 1);
+ end = find_char_or_comment(value, '\0');
+ if (*end == ';')
+ *end = '\0';
+ rstrip(value);
+ /* Strip double-quotes */
+ if (value[0] == '"' &&
+ value[strlen(value)-1] == '"') {
+ value[strlen(value)-1] = '\0';
+ value += 1;
+ }
+
+ /*
+ * Valid name[=:]value pair found, call handler
+ */
+ strncpy0(prev_name, name, sizeof(prev_name));
+ if (!handler(user, section, name, value) &&
+ !error)
+ error = lineno;
+ } else if (!error)
+ /* No '=' or ':' found on name[=:]value line */
+ error = lineno;
+ }
+ }
+
+ return error;
+}
+
+static int ini_handler(void *user, char *section, char *name, char *value)
+{
+ char *requested_section = (char *)user;
+#ifdef CONFIG_INI_CASE_INSENSITIVE
+ int i;
+
+ for (i = 0; i < strlen(requested_section); i++)
+ requested_section[i] = tolower(requested_section[i]);
+ for (i = 0; i < strlen(section); i++)
+ section[i] = tolower(section[i]);
+#endif
+
+ if (!strcmp(section, requested_section)) {
+#ifdef CONFIG_INI_CASE_INSENSITIVE
+ for (i = 0; i < strlen(name); i++)
+ name[i] = tolower(name[i]);
+ for (i = 0; i < strlen(value); i++)
+ value[i] = tolower(value[i]);
+#endif
+ env_set(name, value);
+ printf("ini: Imported %s as %s\n", name, value);
+ }
+
+ /* success */
+ return 1;
+}
+
+static int do_ini(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const char *section;
+ char *file_address;
+ size_t file_size;
+
+ if (argc == 1)
+ return CMD_RET_USAGE;
+
+ section = argv[1];
+ file_address = (char *)simple_strtoul(
+ argc < 3 ? env_get("loadaddr") : argv[2], NULL, 16);
+ file_size = (size_t)simple_strtoul(
+ argc < 4 ? env_get("filesize") : argv[3], NULL, 16);
+
+ return ini_parse(file_address, file_size, ini_handler, (void *)section);
+}
+
+U_BOOT_CMD(
+ ini, 4, 0, do_ini,
+ "parse an ini file in memory and merge the specified section into the env",
+ "section [[file-address] file-size]"
+);
diff --git a/roms/u-boot/cmd/io.c b/roms/u-boot/cmd/io.c
new file mode 100644
index 000000000..c7e964153
--- /dev/null
+++ b/roms/u-boot/cmd/io.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ */
+
+/*
+ * IO space access commands.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+
+/* Display values from last command */
+static ulong last_addr, last_size;
+static ulong last_length = 0x40;
+static ulong base_address;
+
+#define DISP_LINE_LEN 16
+
+/*
+ * IO Display
+ *
+ * Syntax:
+ * iod{.b, .w, .l} {addr}
+ */
+int do_io_iod(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong addr, length, bytes;
+ u8 buf[DISP_LINE_LEN];
+ int size, todo;
+
+ /*
+ * We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ addr = last_addr;
+ size = last_size;
+ length = last_length;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /*
+ * New command specified. Check for a size specification.
+ * Defaults to long if no or incorrect specification.
+ */
+ size = cmd_get_data_size(argv[0], 4);
+ if (size < 0)
+ return 1;
+
+ /* Address is specified since argc > 1 */
+ addr = simple_strtoul(argv[1], NULL, 16);
+ addr += base_address;
+
+ /*
+ * If another parameter, it is the length to display.
+ * Length is the number of objects, not number of bytes.
+ */
+ if (argc > 2)
+ length = simple_strtoul(argv[2], NULL, 16);
+ }
+
+ bytes = size * length;
+
+ /* Print the lines */
+ for (; bytes > 0; addr += todo) {
+ u8 *ptr = buf;
+ int i;
+
+ todo = min(bytes, (ulong)DISP_LINE_LEN);
+ for (i = 0; i < todo; i += size, ptr += size) {
+ if (size == 4)
+ *(u32 *)ptr = inl(addr + i);
+ else if (size == 2)
+ *(u16 *)ptr = inw(addr + i);
+ else
+ *ptr = inb(addr + i);
+ }
+ print_buffer(addr, buf, size, todo / size,
+ DISP_LINE_LEN / size);
+ bytes -= todo;
+ }
+
+ last_addr = addr;
+ last_length = length;
+ last_size = size;
+
+ return 0;
+}
+
+int do_io_iow(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong addr, val;
+ int size;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ size = cmd_get_data_size(argv[0], 4);
+ if (size < 0)
+ return 1;
+
+ addr = simple_strtoul(argv[1], NULL, 16);
+ val = simple_strtoul(argv[2], NULL, 16);
+
+ if (size == 4)
+ outl((u32) val, addr);
+ else if (size == 2)
+ outw((u16) val, addr);
+ else
+ outb((u8) val, addr);
+
+ return 0;
+}
+
+/**************************************************/
+U_BOOT_CMD(iod, 3, 1, do_io_iod,
+ "IO space display", "[.b, .w, .l] address");
+
+U_BOOT_CMD(iow, 3, 0, do_io_iow,
+ "IO space modify",
+ "[.b, .w, .l] address value");
diff --git a/roms/u-boot/cmd/iotrace.c b/roms/u-boot/cmd/iotrace.c
new file mode 100644
index 000000000..652ebefb8
--- /dev/null
+++ b/roms/u-boot/cmd/iotrace.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2014 Google, Inc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <iotrace.h>
+
+static void do_print_stats(void)
+{
+ ulong start, size, needed_size, offset, count;
+
+ printf("iotrace is %sabled\n", iotrace_get_enabled() ? "en" : "dis");
+ iotrace_get_buffer(&start, &size, &needed_size, &offset, &count);
+ printf("Start: %08lx\n", start);
+ printf("Actual Size: %08lx\n", size);
+ printf("Needed Size: %08lx\n", needed_size);
+ iotrace_get_region(&start, &size);
+ printf("Region: %08lx\n", start);
+ printf("Size: %08lx\n", size);
+ printf("Offset: %08lx\n", offset);
+ printf("Output: %08lx\n", start + offset);
+ printf("Count: %08lx\n", count);
+ printf("CRC32: %08lx\n", (ulong)iotrace_get_checksum());
+}
+
+static void do_print_trace(void)
+{
+ ulong start, size, needed_size, offset, count;
+
+ struct iotrace_record *cur_record;
+
+ iotrace_get_buffer(&start, &size, &needed_size, &offset, &count);
+
+ if (!start || !size || !count)
+ return;
+
+ printf("Timestamp Value Address\n");
+
+ cur_record = (struct iotrace_record *)start;
+ for (int i = 0; i < count; i++) {
+ if (cur_record->flags & IOT_WRITE)
+ printf("%08llu: 0x%08lx --> 0x%08llx\n",
+ cur_record->timestamp,
+ cur_record->value,
+ (unsigned long long)cur_record->addr);
+ else
+ printf("%08llu: 0x%08lx <-- 0x%08llx\n",
+ cur_record->timestamp,
+ cur_record->value,
+ (unsigned long long)cur_record->addr);
+
+ cur_record++;
+ }
+}
+
+static int do_set_buffer(int argc, char *const argv[])
+{
+ ulong addr = 0, size = 0;
+
+ if (argc == 2) {
+ addr = simple_strtoul(*argv++, NULL, 16);
+ size = simple_strtoul(*argv++, NULL, 16);
+ } else if (argc != 0) {
+ return CMD_RET_USAGE;
+ }
+
+ iotrace_set_buffer(addr, size);
+
+ return 0;
+}
+
+static int do_set_region(int argc, char *const argv[])
+{
+ ulong addr = 0, size = 0;
+
+ if (argc == 2) {
+ addr = simple_strtoul(*argv++, NULL, 16);
+ size = simple_strtoul(*argv++, NULL, 16);
+ } else if (argc != 0) {
+ return CMD_RET_USAGE;
+ }
+
+ iotrace_set_region(addr, size);
+
+ return 0;
+}
+
+int do_iotrace(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const char *cmd = argc < 2 ? NULL : argv[1];
+
+ if (!cmd)
+ return cmd_usage(cmdtp);
+ switch (*cmd) {
+ case 'b':
+ return do_set_buffer(argc - 2, argv + 2);
+ case 'l':
+ return do_set_region(argc - 2, argv + 2);
+ case 'p':
+ iotrace_set_enabled(0);
+ break;
+ case 'r':
+ iotrace_set_enabled(1);
+ break;
+ case 's':
+ do_print_stats();
+ break;
+ case 'd':
+ do_print_trace();
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ iotrace, 4, 1, do_iotrace,
+ "iotrace utility commands",
+ "stats - display iotrace stats\n"
+ "iotrace buffer <address> <size> - set iotrace buffer\n"
+ "iotrace limit <address> <size> - set iotrace region limit\n"
+ "iotrace pause - pause tracing\n"
+ "iotrace resume - resume tracing\n"
+ "iotrace dump - dump iotrace buffer"
+);
diff --git a/roms/u-boot/cmd/irq.c b/roms/u-boot/cmd/irq.c
new file mode 100644
index 000000000..1d3e28cb3
--- /dev/null
+++ b/roms/u-boot/cmd/irq.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <irq_func.h>
+
+static int do_interrupts(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ /* on */
+ if (strncmp(argv[1], "on", 2) == 0)
+ enable_interrupts();
+ else
+ disable_interrupts();
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ interrupts, 5, 0, do_interrupts,
+ "enable or disable interrupts",
+ "[on, off]"
+);
+
+/* Implemented in $(CPU)/interrupts.c */
+int do_irqinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+
+U_BOOT_CMD(
+ irqinfo, 1, 1, do_irqinfo,
+ "print information about IRQs",
+ ""
+);
diff --git a/roms/u-boot/cmd/itest.c b/roms/u-boot/cmd/itest.c
new file mode 100644
index 000000000..9a441ce9b
--- /dev/null
+++ b/roms/u-boot/cmd/itest.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2003
+ * Tait Electronics Limited, Christchurch, New Zealand
+ */
+
+/*
+ * This file provides a shell like 'test' function to return
+ * true/false from an integer or string compare of two memory
+ * locations or a location and a scalar/literal.
+ * A few parts were lifted from bash 'test' command
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <env.h>
+#include <mapmem.h>
+
+#include <asm/io.h>
+
+#define EQ 0
+#define NE 1
+#define LT 2
+#define GT 3
+#define LE 4
+#define GE 5
+
+struct op_tbl_s {
+ char *op; /* operator string */
+ int opcode; /* internal representation of opcode */
+};
+
+typedef struct op_tbl_s op_tbl_t;
+
+static const op_tbl_t op_table [] = {
+ { "-lt", LT },
+ { "<" , LT },
+ { "-gt", GT },
+ { ">" , GT },
+ { "-eq", EQ },
+ { "==" , EQ },
+ { "-ne", NE },
+ { "!=" , NE },
+ { "<>" , NE },
+ { "-ge", GE },
+ { ">=" , GE },
+ { "-le", LE },
+ { "<=" , LE },
+};
+
+static long evalexp(char *s, int w)
+{
+ long l = 0;
+ unsigned long addr;
+ void *buf;
+
+ /* if the parameter starts with a * then assume is a pointer to the value we want */
+ if (s[0] == '*') {
+ addr = simple_strtoul(&s[1], NULL, 16);
+ buf = map_physmem(addr, w, MAP_WRBACK);
+ if (!buf && addr) {
+ puts("Failed to map physical memory\n");
+ return 0;
+ }
+ switch (w) {
+ case 1:
+ l = (long)(*(u8 *)buf);
+ break;
+ case 2:
+ l = (long)(*(u16 *)buf);
+ break;
+ case 4:
+ l = (long)(*(u32 *)buf);
+ break;
+#ifdef CONFIG_PHYS_64BIT
+ case 8:
+ l = (long)(*(unsigned long *)buf);
+ break;
+#endif
+ }
+ unmap_physmem(buf, w);
+ return l;
+ } else {
+ l = simple_strtoul(s, NULL, 16);
+ }
+
+ /* avoid overflow on mask calculus */
+ return (w >= sizeof(long)) ? l : (l & ((1UL << (w * 8)) - 1));
+}
+
+static char * evalstr(char *s)
+{
+ /* if the parameter starts with a * then assume a string pointer else its a literal */
+ if (s[0] == '*') {
+ return (char *)simple_strtoul(&s[1], NULL, 16);
+ } else if (s[0] == '$') {
+ int i = 2;
+
+ if (s[1] != '{')
+ return NULL;
+
+ while (s[i] != '}') {
+ if (s[i] == 0)
+ return NULL;
+ i++;
+ }
+ s[i] = 0;
+ return env_get((const char *)&s[2]);
+ } else {
+ return s;
+ }
+}
+
+static int stringcomp(char *s, char *t, int op)
+{
+ int p;
+ char *l, *r;
+
+ l = evalstr(s);
+ r = evalstr(t);
+
+ p = strcmp(l, r);
+ switch (op) {
+ case EQ: return (p == 0);
+ case NE: return (p != 0);
+ case LT: return (p < 0);
+ case GT: return (p > 0);
+ case LE: return (p <= 0);
+ case GE: return (p >= 0);
+ }
+ return (0);
+}
+
+static int arithcomp (char *s, char *t, int op, int w)
+{
+ long l, r;
+
+ l = evalexp (s, w);
+ r = evalexp (t, w);
+
+ switch (op) {
+ case EQ: return (l == r);
+ case NE: return (l != r);
+ case LT: return (l < r);
+ case GT: return (l > r);
+ case LE: return (l <= r);
+ case GE: return (l >= r);
+ }
+ return (0);
+}
+
+static int binary_test(char *op, char *arg1, char *arg2, int w)
+{
+ int len, i;
+ const op_tbl_t *optp;
+
+ len = strlen(op);
+
+ for (optp = (op_tbl_t *)&op_table, i = 0;
+ i < ARRAY_SIZE(op_table);
+ optp++, i++) {
+
+ if ((strncmp (op, optp->op, len) == 0) && (len == strlen (optp->op))) {
+ if (w == 0) {
+ return (stringcomp(arg1, arg2, optp->opcode));
+ } else {
+ return (arithcomp (arg1, arg2, optp->opcode, w));
+ }
+ }
+ }
+
+ printf("Unknown operator '%s'\n", op);
+ return 0; /* op code not found */
+}
+
+/* command line interface to the shell test */
+static int do_itest(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int value, w;
+
+ /* Validate arguments */
+ if ((argc != 4))
+ return CMD_RET_USAGE;
+
+ /* Check for a data width specification.
+ * Defaults to long (4) if no specification.
+ * Uses -2 as 'width' for .s (string) so as not to upset existing code
+ */
+ switch (w = cmd_get_data_size(argv[0], 4)) {
+ case 1:
+ case 2:
+ case 4:
+#ifdef CONFIG_PHYS_64BIT
+ case 8:
+#endif
+ value = binary_test (argv[2], argv[1], argv[3], w);
+ break;
+ case CMD_DATA_SIZE_STR:
+ value = binary_test (argv[2], argv[1], argv[3], 0);
+ break;
+ case CMD_DATA_SIZE_ERR:
+ default:
+ puts("Invalid data width specifier\n");
+ value = 0;
+ break;
+ }
+
+ return !value;
+}
+
+U_BOOT_CMD(
+ itest, 4, 0, do_itest,
+ "return true/false on integer compare",
+#ifdef CONFIG_PHYS_64BIT
+ "[.b, .w, .l, .q, .s] [*]value1 <op> [*]value2"
+#else
+ "[.b, .w, .l, .s] [*]value1 <op> [*]value2"
+#endif
+);
diff --git a/roms/u-boot/cmd/jffs2.c b/roms/u-boot/cmd/jffs2.c
new file mode 100644
index 000000000..9540988e3
--- /dev/null
+++ b/roms/u-boot/cmd/jffs2.c
@@ -0,0 +1,625 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>
+ *
+ * (C) Copyright 2003
+ * Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.de>
+ *
+ * (C) Copyright 2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Added support for reading flash partition table from environment.
+ * Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4
+ * kernel tree.
+ *
+ * $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $
+ * Copyright 2002 SYSGO Real-Time Solutions GmbH
+ */
+
+/*
+ * Three environment variables are used by the parsing routines:
+ *
+ * 'partition' - keeps current partition identifier
+ *
+ * partition := <part-id>
+ * <part-id> := <dev-id>,part_num
+ *
+ *
+ * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping
+ *
+ * mtdids=<idmap>[,<idmap>,...]
+ *
+ * <idmap> := <dev-id>=<mtd-id>
+ * <dev-id> := 'nand'|'nor'|'onenand'<dev-num>
+ * <dev-num> := mtd device number, 0...
+ * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)
+ *
+ *
+ * 'mtdparts' - partition list
+ *
+ * mtdparts=mtdparts=<mtd-def>[;<mtd-def>...]
+ *
+ * <mtd-def> := <mtd-id>:<part-def>[,<part-def>...]
+ * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)
+ * <part-def> := <size>[@<offset>][<name>][<ro-flag>]
+ * <size> := standard linux memsize OR '-' to denote all remaining space
+ * <offset> := partition start offset within the device
+ * <name> := '(' NAME ')'
+ * <ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)
+ *
+ * Notes:
+ * - each <mtd-id> used in mtdparts must albo exist in 'mtddis' mapping
+ * - if the above variables are not set defaults for a given target are used
+ *
+ * Examples:
+ *
+ * 1 NOR Flash, with 1 single writable partition:
+ * mtdids=nor0=edb7312-nor
+ * mtdparts=mtdparts=edb7312-nor:-
+ *
+ * 1 NOR Flash with 2 partitions, 1 NAND with one
+ * mtdids=nor0=edb7312-nor,nand0=edb7312-nand
+ * mtdparts=mtdparts=edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
+ *
+ */
+
+/*
+ * JFFS2/CRAMFS support
+ */
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <flash.h>
+#include <image.h>
+#include <malloc.h>
+#include <jffs2/jffs2.h>
+#include <linux/bug.h>
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <cramfs/cramfs_fs.h>
+
+#if defined(CONFIG_CMD_NAND)
+#include <linux/mtd/rawnand.h>
+#include <nand.h>
+#endif
+
+#if defined(CONFIG_CMD_ONENAND)
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <onenand_uboot.h>
+#endif
+
+/* enable/disable debugging messages */
+#define DEBUG_JFFS
+#undef DEBUG_JFFS
+
+#ifdef DEBUG_JFFS
+# define DEBUGF(fmt, args...) printf(fmt ,##args)
+#else
+# define DEBUGF(fmt, args...)
+#endif
+
+/* special size referring to all the remaining space in a partition */
+#define SIZE_REMAINING 0xFFFFFFFF
+
+/* special offset value, it is used when not provided by user
+ *
+ * this value is used temporarily during parsing, later such offests
+ * are recalculated */
+#define OFFSET_NOT_SPECIFIED 0xFFFFFFFF
+
+/* minimum partition size */
+#define MIN_PART_SIZE 4096
+
+/* this flag needs to be set in part_info struct mask_flags
+ * field for read-only partitions */
+#define MTD_WRITEABLE_CMD 1
+
+/* current active device and partition number */
+#ifdef CONFIG_CMD_MTDPARTS
+/* Use the ones declared in cmd_mtdparts.c */
+extern struct mtd_device *current_mtd_dev;
+extern u8 current_mtd_partnum;
+#else
+/* Use local ones */
+struct mtd_device *current_mtd_dev = NULL;
+u8 current_mtd_partnum = 0;
+#endif
+
+#if defined(CONFIG_CMD_CRAMFS)
+extern int cramfs_check (struct part_info *info);
+extern int cramfs_load (char *loadoffset, struct part_info *info, char *filename);
+extern int cramfs_ls (struct part_info *info, char *filename);
+extern int cramfs_info (struct part_info *info);
+#else
+/* defining empty macros for function names is ugly but avoids ifdef clutter
+ * all over the code */
+#define cramfs_check(x) (0)
+#define cramfs_load(x,y,z) (-1)
+#define cramfs_ls(x,y) (0)
+#define cramfs_info(x) (0)
+#endif
+
+#ifndef CONFIG_CMD_MTDPARTS
+/**
+ * Check device number to be within valid range for given device type.
+ *
+ * @param dev device to validate
+ * @return 0 if device is valid, 1 otherwise
+ */
+static int mtd_device_validate(u8 type, u8 num, u32 *size)
+{
+ if (type == MTD_DEV_TYPE_NOR) {
+#if defined(CONFIG_CMD_FLASH)
+ if (num < CONFIG_SYS_MAX_FLASH_BANKS) {
+ extern flash_info_t flash_info[];
+ *size = flash_info[num].size;
+
+ return 0;
+ }
+
+ printf("no such FLASH device: %s%d (valid range 0 ... %d\n",
+ MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_FLASH_BANKS - 1);
+#else
+ printf("support for FLASH devices not present\n");
+#endif
+ } else if (type == MTD_DEV_TYPE_NAND) {
+#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
+ struct mtd_info *mtd = get_nand_dev_by_index(num);
+ if (mtd) {
+ *size = mtd->size;
+ return 0;
+ }
+
+ printf("no such NAND device: %s%d (valid range 0 ... %d)\n",
+ MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_NAND_DEVICE - 1);
+#else
+ printf("support for NAND devices not present\n");
+#endif
+ } else if (type == MTD_DEV_TYPE_ONENAND) {
+#if defined(CONFIG_CMD_ONENAND)
+ *size = onenand_mtd.size;
+ return 0;
+#else
+ printf("support for OneNAND devices not present\n");
+#endif
+ } else
+ printf("Unknown defice type %d\n", type);
+
+ return 1;
+}
+
+/**
+ * Parse device id string <dev-id> := 'nand'|'nor'|'onenand'<dev-num>,
+ * return device type and number.
+ *
+ * @param id string describing device id
+ * @param ret_id output pointer to next char after parse completes (output)
+ * @param dev_type parsed device type (output)
+ * @param dev_num parsed device number (output)
+ * @return 0 on success, 1 otherwise
+ */
+static int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num)
+{
+ const char *p = id;
+
+ *dev_type = 0;
+ if (strncmp(p, "nand", 4) == 0) {
+ *dev_type = MTD_DEV_TYPE_NAND;
+ p += 4;
+ } else if (strncmp(p, "nor", 3) == 0) {
+ *dev_type = MTD_DEV_TYPE_NOR;
+ p += 3;
+ } else if (strncmp(p, "onenand", 7) == 0) {
+ *dev_type = MTD_DEV_TYPE_ONENAND;
+ p += 7;
+ } else {
+ printf("incorrect device type in %s\n", id);
+ return 1;
+ }
+
+ if (!isdigit(*p)) {
+ printf("incorrect device number in %s\n", id);
+ return 1;
+ }
+
+ *dev_num = simple_strtoul(p, (char **)&p, 0);
+ if (ret_id)
+ *ret_id = p;
+ return 0;
+}
+
+/*
+ * 'Static' version of command line mtdparts_init() routine. Single partition on
+ * a single device configuration.
+ */
+
+/**
+ * Calculate sector size.
+ *
+ * @return sector size
+ */
+static inline u32 get_part_sector_size_nand(struct mtdids *id)
+{
+#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
+ struct mtd_info *mtd;
+
+ mtd = get_nand_dev_by_index(id->num);
+
+ return mtd->erasesize;
+#else
+ BUG();
+ return 0;
+#endif
+}
+
+static inline u32 get_part_sector_size_nor(struct mtdids *id, struct part_info *part)
+{
+#if defined(CONFIG_CMD_FLASH)
+ extern flash_info_t flash_info[];
+
+ u32 end_phys, start_phys, sector_size = 0, size = 0;
+ int i;
+ flash_info_t *flash;
+
+ flash = &flash_info[id->num];
+
+ start_phys = flash->start[0] + part->offset;
+ end_phys = start_phys + part->size - 1;
+
+ for (i = 0; i < flash->sector_count; i++) {
+ if (flash->start[i] >= end_phys)
+ break;
+
+ if (flash->start[i] >= start_phys) {
+ if (i == flash->sector_count - 1) {
+ size = flash->start[0] + flash->size - flash->start[i];
+ } else {
+ size = flash->start[i+1] - flash->start[i];
+ }
+
+ if (sector_size < size)
+ sector_size = size;
+ }
+ }
+
+ return sector_size;
+#else
+ BUG();
+ return 0;
+#endif
+}
+
+static inline u32 get_part_sector_size_onenand(void)
+{
+#if defined(CONFIG_CMD_ONENAND)
+ struct mtd_info *mtd;
+
+ mtd = &onenand_mtd;
+
+ return mtd->erasesize;
+#else
+ BUG();
+ return 0;
+#endif
+}
+
+static inline u32 get_part_sector_size(struct mtdids *id, struct part_info *part)
+{
+ if (id->type == MTD_DEV_TYPE_NAND)
+ return get_part_sector_size_nand(id);
+ else if (id->type == MTD_DEV_TYPE_NOR)
+ return get_part_sector_size_nor(id, part);
+ else if (id->type == MTD_DEV_TYPE_ONENAND)
+ return get_part_sector_size_onenand();
+ else
+ DEBUGF("Error: Unknown device type.\n");
+
+ return 0;
+}
+
+/**
+ * Parse and initialize global mtdids mapping and create global
+ * device/partition list.
+ *
+ * 'Static' version of command line mtdparts_init() routine. Single partition on
+ * a single device configuration.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+int mtdparts_init(void)
+{
+ static int initialized = 0;
+ u32 size;
+ char *dev_name;
+
+ DEBUGF("\n---mtdparts_init---\n");
+ if (!initialized) {
+ struct mtdids *id;
+ struct part_info *part;
+
+ initialized = 1;
+ current_mtd_dev = (struct mtd_device *)
+ malloc(sizeof(struct mtd_device) +
+ sizeof(struct part_info) +
+ sizeof(struct mtdids));
+ if (!current_mtd_dev) {
+ printf("out of memory\n");
+ return 1;
+ }
+ memset(current_mtd_dev, 0, sizeof(struct mtd_device) +
+ sizeof(struct part_info) + sizeof(struct mtdids));
+
+ id = (struct mtdids *)(current_mtd_dev + 1);
+ part = (struct part_info *)(id + 1);
+
+ /* id */
+ id->mtd_id = "single part";
+
+#if defined(CONFIG_JFFS2_DEV)
+ dev_name = CONFIG_JFFS2_DEV;
+#else
+ dev_name = "nor0";
+#endif
+
+ if ((mtd_id_parse(dev_name, NULL, &id->type, &id->num) != 0) ||
+ (mtd_device_validate(id->type, id->num, &size) != 0)) {
+ printf("incorrect device: %s%d\n", MTD_DEV_TYPE(id->type), id->num);
+ free(current_mtd_dev);
+ return 1;
+ }
+ id->size = size;
+ INIT_LIST_HEAD(&id->link);
+
+ DEBUGF("dev id: type = %d, num = %d, size = 0x%08lx, mtd_id = %s\n",
+ id->type, id->num, id->size, id->mtd_id);
+
+ /* partition */
+ part->name = "static";
+ part->auto_name = 0;
+
+#if defined(CONFIG_JFFS2_PART_SIZE)
+ part->size = CONFIG_JFFS2_PART_SIZE;
+#else
+ part->size = SIZE_REMAINING;
+#endif
+
+#if defined(CONFIG_JFFS2_PART_OFFSET)
+ part->offset = CONFIG_JFFS2_PART_OFFSET;
+#else
+ part->offset = 0x00000000;
+#endif
+
+ part->dev = current_mtd_dev;
+ INIT_LIST_HEAD(&part->link);
+
+ /* recalculate size if needed */
+ if (part->size == SIZE_REMAINING)
+ part->size = id->size - part->offset;
+
+ part->sector_size = get_part_sector_size(id, part);
+
+ DEBUGF("part : name = %s, size = 0x%08lx, offset = 0x%08lx\n",
+ part->name, part->size, part->offset);
+
+ /* device */
+ current_mtd_dev->id = id;
+ INIT_LIST_HEAD(&current_mtd_dev->link);
+ current_mtd_dev->num_parts = 1;
+ INIT_LIST_HEAD(&current_mtd_dev->parts);
+ list_add(&part->link, &current_mtd_dev->parts);
+ }
+
+ return 0;
+}
+#endif /* #ifndef CONFIG_CMD_MTDPARTS */
+
+/**
+ * Return pointer to the partition of a requested number from a requested
+ * device.
+ *
+ * @param dev device that is to be searched for a partition
+ * @param part_num requested partition number
+ * @return pointer to the part_info, NULL otherwise
+ */
+static struct part_info* jffs2_part_info(struct mtd_device *dev, unsigned int part_num)
+{
+ struct list_head *entry;
+ struct part_info *part;
+ int num;
+
+ if (!dev)
+ return NULL;
+
+ DEBUGF("\n--- jffs2_part_info: partition number %d for device %s%d (%s)\n",
+ part_num, MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+
+ if (part_num >= dev->num_parts) {
+ printf("invalid partition number %d for device %s%d (%s)\n",
+ part_num, MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+ return NULL;
+ }
+
+ /* locate partition number, return it */
+ num = 0;
+ list_for_each(entry, &dev->parts) {
+ part = list_entry(entry, struct part_info, link);
+
+ if (part_num == num++) {
+ return part;
+ }
+ }
+
+ return NULL;
+}
+
+/***************************************************/
+/* U-Boot commands */
+/***************************************************/
+
+/**
+ * Routine implementing fsload u-boot command. This routine tries to load
+ * a requested file from jffs2/cramfs filesystem on a current partition.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_jffs2_fsload(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *fsname;
+ char *filename;
+ int size;
+ struct part_info *part;
+ ulong offset = image_load_addr;
+
+ /* pre-set Boot file name */
+ filename = env_get("bootfile");
+ if (!filename)
+ filename = "uImage";
+
+ if (argc == 2) {
+ filename = argv[1];
+ }
+ if (argc == 3) {
+ offset = simple_strtoul(argv[1], NULL, 16);
+ image_load_addr = offset;
+ filename = argv[2];
+ }
+
+ /* make sure we are in sync with env variables */
+ if (mtdparts_init() !=0)
+ return 1;
+
+ if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
+
+ /* check partition type for cramfs */
+ fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2");
+ printf("### %s loading '%s' to 0x%lx\n", fsname, filename, offset);
+
+ if (cramfs_check(part)) {
+ size = cramfs_load ((char *) offset, part, filename);
+ } else {
+ /* if this is not cramfs assume jffs2 */
+ size = jffs2_1pass_load((char *)offset, part, filename);
+ }
+
+ if (size > 0) {
+ printf("### %s load complete: %d bytes loaded to 0x%lx\n",
+ fsname, size, offset);
+ env_set_hex("filesize", size);
+ } else {
+ printf("### %s LOAD ERROR<%x> for %s!\n", fsname, size, filename);
+ }
+
+ return !(size > 0);
+ }
+ return 1;
+}
+
+/**
+ * Routine implementing u-boot ls command which lists content of a given
+ * directory on a current partition.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_jffs2_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *filename = "/";
+ int ret;
+ struct part_info *part;
+
+ if (argc == 2)
+ filename = argv[1];
+
+ /* make sure we are in sync with env variables */
+ if (mtdparts_init() !=0)
+ return 1;
+
+ if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
+
+ /* check partition type for cramfs */
+ if (cramfs_check(part)) {
+ ret = cramfs_ls (part, filename);
+ } else {
+ /* if this is not cramfs assume jffs2 */
+ ret = jffs2_1pass_ls(part, filename);
+ }
+
+ return ret ? 0 : 1;
+ }
+ return 1;
+}
+
+/**
+ * Routine implementing u-boot fsinfo command. This routine prints out
+ * miscellaneous filesystem informations/statistics.
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+int do_jffs2_fsinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct part_info *part;
+ char *fsname;
+ int ret;
+
+ /* make sure we are in sync with env variables */
+ if (mtdparts_init() !=0)
+ return 1;
+
+ if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
+
+ /* check partition type for cramfs */
+ fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2");
+ printf("### filesystem type is %s\n", fsname);
+
+ if (cramfs_check(part)) {
+ ret = cramfs_info (part);
+ } else {
+ /* if this is not cramfs assume jffs2 */
+ ret = jffs2_1pass_info(part);
+ }
+
+ return ret ? 0 : 1;
+ }
+ return 1;
+}
+
+/***************************************************/
+U_BOOT_CMD(
+ fsload, 3, 0, do_jffs2_fsload,
+ "load binary file from a filesystem image",
+ "[ off ] [ filename ]\n"
+ " - load binary file from flash bank\n"
+ " with offset 'off'"
+);
+U_BOOT_CMD(
+ fsls, 2, 1, do_jffs2_ls,
+ "list files in a directory (default /)",
+ "[ directory ]"
+);
+
+U_BOOT_CMD(
+ fsinfo, 1, 1, do_jffs2_fsinfo,
+ "print information about filesystems",
+ ""
+);
+/***************************************************/
diff --git a/roms/u-boot/cmd/led.c b/roms/u-boot/cmd/led.c
new file mode 100644
index 000000000..aa7751933
--- /dev/null
+++ b/roms/u-boot/cmd/led.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <led.h>
+#include <dm/uclass-internal.h>
+
+#define LED_TOGGLE LEDST_COUNT
+
+static const char *const state_label[] = {
+ [LEDST_OFF] = "off",
+ [LEDST_ON] = "on",
+ [LEDST_TOGGLE] = "toggle",
+#ifdef CONFIG_LED_BLINK
+ [LEDST_BLINK] = "blink",
+#endif
+};
+
+enum led_state_t get_led_cmd(char *var)
+{
+ int i;
+
+ for (i = 0; i < LEDST_COUNT; i++) {
+ if (!strncmp(var, state_label[i], strlen(var)))
+ return i;
+ }
+
+ return -1;
+}
+
+static int show_led_state(struct udevice *dev)
+{
+ int ret;
+
+ ret = led_get_state(dev);
+ if (ret >= LEDST_COUNT)
+ ret = -EINVAL;
+ if (ret >= 0)
+ printf("%s\n", state_label[ret]);
+
+ return ret;
+}
+
+static int list_leds(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ for (uclass_find_first_device(UCLASS_LED, &dev);
+ dev;
+ uclass_find_next_device(&dev)) {
+ struct led_uc_plat *plat = dev_get_uclass_plat(dev);
+
+ if (!plat->label)
+ continue;
+ printf("%-15s ", plat->label);
+ if (device_active(dev)) {
+ ret = show_led_state(dev);
+ if (ret < 0)
+ printf("Error %d\n", ret);
+ } else {
+ printf("<inactive>\n");
+ }
+ }
+
+ return 0;
+}
+
+int do_led(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ enum led_state_t cmd;
+ const char *led_label;
+ struct udevice *dev;
+#ifdef CONFIG_LED_BLINK
+ int freq_ms = 0;
+#endif
+ int ret;
+
+ /* Validate arguments */
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ led_label = argv[1];
+ if (strncmp(led_label, "list", 4) == 0)
+ return list_leds();
+
+ cmd = argc > 2 ? get_led_cmd(argv[2]) : LEDST_COUNT;
+#ifdef CONFIG_LED_BLINK
+ if (cmd == LEDST_BLINK) {
+ if (argc < 4)
+ return CMD_RET_USAGE;
+ freq_ms = simple_strtoul(argv[3], NULL, 10);
+ }
+#endif
+ ret = led_get_by_label(led_label, &dev);
+ if (ret) {
+ printf("LED '%s' not found (err=%d)\n", led_label, ret);
+ return CMD_RET_FAILURE;
+ }
+ switch (cmd) {
+ case LEDST_OFF:
+ case LEDST_ON:
+ case LEDST_TOGGLE:
+ ret = led_set_state(dev, cmd);
+ break;
+#ifdef CONFIG_LED_BLINK
+ case LEDST_BLINK:
+ ret = led_set_period(dev, freq_ms);
+ if (!ret)
+ ret = led_set_state(dev, LEDST_BLINK);
+ break;
+#endif
+ case LEDST_COUNT:
+ printf("LED '%s': ", led_label);
+ ret = show_led_state(dev);
+ break;
+ }
+ if (ret < 0) {
+ printf("LED '%s' operation failed (err=%d)\n", led_label, ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_LED_BLINK
+#define BLINK "|blink [blink-freq in ms]"
+#else
+#define BLINK ""
+#endif
+
+U_BOOT_CMD(
+ led, 4, 1, do_led,
+ "manage LEDs",
+ "<led_label> on|off|toggle" BLINK "\tChange LED state\n"
+ "led <led_label>\tGet LED state\n"
+ "led list\t\tshow a list of LEDs"
+);
diff --git a/roms/u-boot/cmd/legacy-mtd-utils.c b/roms/u-boot/cmd/legacy-mtd-utils.c
new file mode 100644
index 000000000..ac7139f84
--- /dev/null
+++ b/roms/u-boot/cmd/legacy-mtd-utils.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <jffs2/jffs2.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/string.h>
+#include <mtd.h>
+
+static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size,
+ loff_t *maxsize, int devtype)
+{
+#ifdef CONFIG_CMD_MTDPARTS
+ struct mtd_device *dev;
+ struct part_info *part;
+ u8 pnum;
+ int ret;
+
+ ret = mtdparts_init();
+ if (ret)
+ return ret;
+
+ ret = find_dev_and_part(partname, &dev, &pnum, &part);
+ if (ret)
+ return ret;
+
+ if (dev->id->type != devtype) {
+ printf("not same typ %d != %d\n", dev->id->type, devtype);
+ return -1;
+ }
+
+ *off = part->offset;
+ *size = part->size;
+ *maxsize = part->size;
+ *idx = dev->id->num;
+
+ return 0;
+#else
+ puts("mtdparts support missing.\n");
+ return -1;
+#endif
+}
+
+int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
+ loff_t *maxsize, int devtype, uint64_t chipsize)
+{
+ if (!str2off(arg, off))
+ return get_part(arg, idx, off, size, maxsize, devtype);
+
+ if (*off >= chipsize) {
+ puts("Offset exceeds device limit\n");
+ return -1;
+ }
+
+ *maxsize = chipsize - *off;
+ *size = *maxsize;
+ return 0;
+}
+
+int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
+ loff_t *size, loff_t *maxsize, int devtype,
+ uint64_t chipsize)
+{
+ int ret;
+
+ if (argc == 0) {
+ *off = 0;
+ *size = chipsize;
+ *maxsize = *size;
+ goto print;
+ }
+
+ ret = mtd_arg_off(argv[0], idx, off, size, maxsize, devtype,
+ chipsize);
+ if (ret)
+ return ret;
+
+ if (argc == 1)
+ goto print;
+
+ if (!str2off(argv[1], size)) {
+ printf("'%s' is not a number\n", argv[1]);
+ return -1;
+ }
+
+ if (*size > *maxsize) {
+ puts("Size exceeds partition or device limit\n");
+ return -1;
+ }
+
+print:
+ printf("device %d ", *idx);
+ if (*size == chipsize)
+ puts("whole chip\n");
+ else
+ printf("offset 0x%llx, size 0x%llx\n",
+ (unsigned long long)*off, (unsigned long long)*size);
+ return 0;
+}
diff --git a/roms/u-boot/cmd/legacy-mtd-utils.h b/roms/u-boot/cmd/legacy-mtd-utils.h
new file mode 100644
index 000000000..ac441d555
--- /dev/null
+++ b/roms/u-boot/cmd/legacy-mtd-utils.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __LEGACY_MTD_UTILS_H
+#define __LEGACY_MTD_UTILS_H
+
+int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
+ loff_t *maxsize, int devtype, uint64_t chipsize);
+int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
+ loff_t *size, loff_t *maxsize, int devtype,
+ uint64_t chipsize);
+
+#endif /* LEGACY_MTD_UTILS_H */
diff --git a/roms/u-boot/cmd/legacy_led.c b/roms/u-boot/cmd/legacy_led.c
new file mode 100644
index 000000000..86cd969e4
--- /dev/null
+++ b/roms/u-boot/cmd/legacy_led.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2010
+ * Jason Kridner <jkridner@beagleboard.org>
+ *
+ * Based on cmd_led.c patch from:
+ * http://www.mail-archive.com/u-boot@lists.denx.de/msg06873.html
+ * (C) Copyright 2008
+ * Ulf Samuelsson <ulf.samuelsson@atmel.com>
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <status_led.h>
+
+struct led_tbl_s {
+ char *string; /* String for use in the command */
+ led_id_t mask; /* Mask used for calling __led_set() */
+ void (*off)(void); /* Optional function for turning LED off */
+ void (*on)(void); /* Optional function for turning LED on */
+ void (*toggle)(void);/* Optional function for toggling LED */
+};
+
+typedef struct led_tbl_s led_tbl_t;
+
+static const led_tbl_t led_commands[] = {
+#ifdef CONFIG_LED_STATUS_BOARD_SPECIFIC
+#ifdef CONFIG_LED_STATUS0
+ { "0", CONFIG_LED_STATUS_BIT, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS1
+ { "1", CONFIG_LED_STATUS_BIT1, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS2
+ { "2", CONFIG_LED_STATUS_BIT2, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS3
+ { "3", CONFIG_LED_STATUS_BIT3, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS4
+ { "4", CONFIG_LED_STATUS_BIT4, NULL, NULL, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS5
+ { "5", CONFIG_LED_STATUS_BIT5, NULL, NULL, NULL },
+#endif
+#endif
+#ifdef CONFIG_LED_STATUS_GREEN
+ { "green", CONFIG_LED_STATUS_GREEN, green_led_off, green_led_on, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS_YELLOW
+ { "yellow", CONFIG_LED_STATUS_YELLOW, yellow_led_off, yellow_led_on,
+ NULL },
+#endif
+#ifdef CONFIG_LED_STATUS_RED
+ { "red", CONFIG_LED_STATUS_RED, red_led_off, red_led_on, NULL },
+#endif
+#ifdef CONFIG_LED_STATUS_BLUE
+ { "blue", CONFIG_LED_STATUS_BLUE, blue_led_off, blue_led_on, NULL },
+#endif
+ { NULL, 0, NULL, NULL, NULL }
+};
+
+enum led_cmd { LED_ON, LED_OFF, LED_TOGGLE, LED_BLINK };
+
+enum led_cmd get_led_cmd(char *var)
+{
+ if (strcmp(var, "off") == 0)
+ return LED_OFF;
+ if (strcmp(var, "on") == 0)
+ return LED_ON;
+ if (strcmp(var, "toggle") == 0)
+ return LED_TOGGLE;
+ if (strcmp(var, "blink") == 0)
+ return LED_BLINK;
+
+ return -1;
+}
+
+/*
+ * LED drivers providing a blinking LED functionality, like the
+ * PCA9551, can override this empty weak function
+ */
+void __weak __led_blink(led_id_t mask, int freq)
+{
+}
+
+int do_legacy_led(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int i, match = 0;
+ enum led_cmd cmd;
+ int freq;
+
+ /* Validate arguments */
+ if ((argc < 3) || (argc > 4))
+ return CMD_RET_USAGE;
+
+ cmd = get_led_cmd(argv[2]);
+ if (cmd < 0) {
+ return CMD_RET_USAGE;
+ }
+
+ for (i = 0; led_commands[i].string; i++) {
+ if ((strcmp("all", argv[1]) == 0) ||
+ (strcmp(led_commands[i].string, argv[1]) == 0)) {
+ match = 1;
+ switch (cmd) {
+ case LED_ON:
+ if (led_commands[i].on)
+ led_commands[i].on();
+ else
+ __led_set(led_commands[i].mask,
+ CONFIG_LED_STATUS_ON);
+ break;
+ case LED_OFF:
+ if (led_commands[i].off)
+ led_commands[i].off();
+ else
+ __led_set(led_commands[i].mask,
+ CONFIG_LED_STATUS_OFF);
+ break;
+ case LED_TOGGLE:
+ if (led_commands[i].toggle)
+ led_commands[i].toggle();
+ else
+ __led_toggle(led_commands[i].mask);
+ break;
+ case LED_BLINK:
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ freq = simple_strtoul(argv[3], NULL, 10);
+ __led_blink(led_commands[i].mask, freq);
+ }
+ /* Need to set only 1 led if led_name wasn't 'all' */
+ if (strcmp("all", argv[1]) != 0)
+ break;
+ }
+ }
+
+ /* If we ran out of matches, print Usage */
+ if (!match) {
+ return CMD_RET_USAGE;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ led, 4, 1, do_legacy_led,
+ "["
+#ifdef CONFIG_LED_STATUS_BOARD_SPECIFIC
+#ifdef CONFIG_LED_STATUS0
+ "0|"
+#endif
+#ifdef CONFIG_LED_STATUS1
+ "1|"
+#endif
+#ifdef CONFIG_LED_STATUS2
+ "2|"
+#endif
+#ifdef CONFIG_LED_STATUS3
+ "3|"
+#endif
+#ifdef CONFIG_LED_STATUS4
+ "4|"
+#endif
+#ifdef CONFIG_LED_STATUS5
+ "5|"
+#endif
+#endif
+#ifdef CONFIG_LED_STATUS_GREEN
+ "green|"
+#endif
+#ifdef CONFIG_LED_STATUS_YELLOW
+ "yellow|"
+#endif
+#ifdef CONFIG_LED_STATUS_RED
+ "red|"
+#endif
+#ifdef CONFIG_LED_STATUS_BLUE
+ "blue|"
+#endif
+ "all] [on|off|toggle|blink] [blink-freq in ms]",
+ "[led_name] [on|off|toggle|blink] sets or clears led(s)"
+);
diff --git a/roms/u-boot/cmd/license.c b/roms/u-boot/cmd/license.c
new file mode 100644
index 000000000..15411b5a9
--- /dev/null
+++ b/roms/u-boot/cmd/license.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007 by OpenMoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <gzip.h>
+#include <malloc.h>
+
+#include "license_data_gz.h"
+#include "license_data_size.h"
+
+static int do_license(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *dst;
+ unsigned long len = data_size;
+ int ret = CMD_RET_SUCCESS;
+
+ dst = malloc(data_size + 1);
+ if (!dst)
+ return CMD_RET_FAILURE;
+
+ ret = gunzip(dst, data_size, (unsigned char *)data_gz, &len);
+ if (ret) {
+ printf("Error uncompressing license text\n");
+ ret = CMD_RET_FAILURE;
+ goto free;
+ }
+
+ dst[data_size] = 0;
+ puts(dst);
+
+free:
+ free(dst);
+
+ return ret;
+}
+
+U_BOOT_CMD(
+ license, 1, 1, do_license,
+ "print GPL license text",
+ ""
+);
diff --git a/roms/u-boot/cmd/load.c b/roms/u-boot/cmd/load.c
new file mode 100644
index 000000000..b7894d7db
--- /dev/null
+++ b/roms/u-boot/cmd/load.c
@@ -0,0 +1,1096 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Serial up- and download support
+ */
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <cpu_func.h>
+#include <efi_loader.h>
+#include <env.h>
+#include <exports.h>
+#include <flash.h>
+#include <image.h>
+#include <mapmem.h>
+#include <net.h>
+#include <s_record.h>
+#include <serial.h>
+#include <xyzModem.h>
+#include <asm/cache.h>
+#include <asm/global_data.h>
+#include <linux/delay.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CMD_LOADB)
+static ulong load_serial_ymodem(ulong offset, int mode);
+#endif
+
+#if defined(CONFIG_CMD_LOADS)
+static ulong load_serial(long offset);
+static int read_record(char *buf, ulong len);
+# if defined(CONFIG_CMD_SAVES)
+static int save_serial(ulong offset, ulong size);
+static int write_record(char *buf);
+#endif
+
+static int do_echo = 1;
+#endif
+
+/* -------------------------------------------------------------------- */
+
+#if defined(CONFIG_CMD_LOADS)
+static int do_load_serial(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ long offset = 0;
+ ulong addr;
+ int i;
+ char *env_echo;
+ int rcode = 0;
+#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
+ int load_baudrate, current_baudrate;
+
+ load_baudrate = current_baudrate = gd->baudrate;
+#endif
+
+ env_echo = env_get("loads_echo");
+ if (env_echo && *env_echo == '1')
+ do_echo = 1;
+ else
+ do_echo = 0;
+
+#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
+ if (argc >= 2) {
+ offset = simple_strtol(argv[1], NULL, 16);
+ }
+ if (argc == 3) {
+ load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
+
+ /* default to current baudrate */
+ if (load_baudrate == 0)
+ load_baudrate = current_baudrate;
+ }
+ if (load_baudrate != current_baudrate) {
+ printf("## Switch baudrate to %d bps and press ENTER ...\n",
+ load_baudrate);
+ udelay(50000);
+ gd->baudrate = load_baudrate;
+ serial_setbrg();
+ udelay(50000);
+ for (;;) {
+ if (getchar() == '\r')
+ break;
+ }
+ }
+#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
+ if (argc == 2) {
+ offset = simple_strtol(argv[1], NULL, 16);
+ }
+#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */
+
+ printf("## Ready for S-Record download ...\n");
+
+ addr = load_serial(offset);
+
+ /*
+ * Gather any trailing characters (for instance, the ^D which
+ * is sent by 'cu' after sending a file), and give the
+ * box some time (100 * 1 ms)
+ */
+ for (i=0; i<100; ++i) {
+ if (tstc()) {
+ getchar();
+ }
+ udelay(1000);
+ }
+
+ if (addr == ~0) {
+ printf("## S-Record download aborted\n");
+ rcode = 1;
+ } else {
+ printf("## Start Addr = 0x%08lX\n", addr);
+ image_load_addr = addr;
+ }
+
+#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
+ if (load_baudrate != current_baudrate) {
+ printf("## Switch baudrate to %d bps and press ESC ...\n",
+ current_baudrate);
+ udelay(50000);
+ gd->baudrate = current_baudrate;
+ serial_setbrg();
+ udelay(50000);
+ for (;;) {
+ if (getchar() == 0x1B) /* ESC */
+ break;
+ }
+ }
+#endif
+ return rcode;
+}
+
+static ulong load_serial(long offset)
+{
+ char record[SREC_MAXRECLEN + 1]; /* buffer for one S-Record */
+ char binbuf[SREC_MAXBINLEN]; /* buffer for binary data */
+ int binlen; /* no. of data bytes in S-Rec. */
+ int type; /* return code for record type */
+ ulong addr; /* load address from S-Record */
+ ulong size; /* number of bytes transferred */
+ ulong store_addr;
+ ulong start_addr = ~0;
+ ulong end_addr = 0;
+ int line_count = 0;
+
+ while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
+ type = srec_decode(record, &binlen, &addr, binbuf);
+
+ if (type < 0) {
+ return (~0); /* Invalid S-Record */
+ }
+
+ switch (type) {
+ case SREC_DATA2:
+ case SREC_DATA3:
+ case SREC_DATA4:
+ store_addr = addr + offset;
+#ifdef CONFIG_MTD_NOR_FLASH
+ if (addr2info(store_addr)) {
+ int rc;
+
+ rc = flash_write((char *)binbuf,store_addr,binlen);
+ if (rc != 0) {
+ flash_perror(rc);
+ return (~0);
+ }
+ } else
+#endif
+ {
+ memcpy((char *)(store_addr), binbuf, binlen);
+ }
+ if ((store_addr) < start_addr)
+ start_addr = store_addr;
+ if ((store_addr + binlen - 1) > end_addr)
+ end_addr = store_addr + binlen - 1;
+ break;
+ case SREC_END2:
+ case SREC_END3:
+ case SREC_END4:
+ udelay(10000);
+ size = end_addr - start_addr + 1;
+ printf("\n"
+ "## First Load Addr = 0x%08lX\n"
+ "## Last Load Addr = 0x%08lX\n"
+ "## Total Size = 0x%08lX = %ld Bytes\n",
+ start_addr, end_addr, size, size
+ );
+ flush_cache(start_addr, size);
+ env_set_hex("filesize", size);
+ return (addr);
+ case SREC_START:
+ break;
+ default:
+ break;
+ }
+ if (!do_echo) { /* print a '.' every 100 lines */
+ if ((++line_count % 100) == 0)
+ putc('.');
+ }
+ }
+
+ return (~0); /* Download aborted */
+}
+
+static int read_record(char *buf, ulong len)
+{
+ char *p;
+ char c;
+
+ --len; /* always leave room for terminating '\0' byte */
+
+ for (p=buf; p < buf+len; ++p) {
+ c = getchar(); /* read character */
+ if (do_echo)
+ putc(c); /* ... and echo it */
+
+ switch (c) {
+ case '\r':
+ case '\n':
+ *p = '\0';
+ return (p - buf);
+ case '\0':
+ case 0x03: /* ^C - Control C */
+ return (-1);
+ default:
+ *p = c;
+ }
+
+ /* Check for the console hangup (if any different from serial) */
+ if (gd->jt->getc != getchar) {
+ if (ctrlc())
+ return (-1);
+ }
+ }
+
+ /* line too long - truncate */
+ *p = '\0';
+ return (p - buf);
+}
+
+#if defined(CONFIG_CMD_SAVES)
+
+int do_save_serial(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong offset = 0;
+ ulong size = 0;
+#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
+ int save_baudrate, current_baudrate;
+
+ save_baudrate = current_baudrate = gd->baudrate;
+#endif
+
+ if (argc >= 2) {
+ offset = simple_strtoul(argv[1], NULL, 16);
+ }
+#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
+ if (argc >= 3) {
+ size = simple_strtoul(argv[2], NULL, 16);
+ }
+ if (argc == 4) {
+ save_baudrate = (int)simple_strtoul(argv[3], NULL, 10);
+
+ /* default to current baudrate */
+ if (save_baudrate == 0)
+ save_baudrate = current_baudrate;
+ }
+ if (save_baudrate != current_baudrate) {
+ printf("## Switch baudrate to %d bps and press ENTER ...\n",
+ save_baudrate);
+ udelay(50000);
+ gd->baudrate = save_baudrate;
+ serial_setbrg();
+ udelay(50000);
+ for (;;) {
+ if (getchar() == '\r')
+ break;
+ }
+ }
+#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
+ if (argc == 3) {
+ size = simple_strtoul(argv[2], NULL, 16);
+ }
+#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */
+
+ printf("## Ready for S-Record upload, press ENTER to proceed ...\n");
+ for (;;) {
+ if (getchar() == '\r')
+ break;
+ }
+ if (save_serial(offset, size)) {
+ printf("## S-Record upload aborted\n");
+ } else {
+ printf("## S-Record upload complete\n");
+ }
+#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
+ if (save_baudrate != current_baudrate) {
+ printf("## Switch baudrate to %d bps and press ESC ...\n",
+ (int)current_baudrate);
+ udelay(50000);
+ gd->baudrate = current_baudrate;
+ serial_setbrg();
+ udelay(50000);
+ for (;;) {
+ if (getchar() == 0x1B) /* ESC */
+ break;
+ }
+ }
+#endif
+ return 0;
+}
+
+#define SREC3_START "S0030000FC\n"
+#define SREC3_FORMAT "S3%02X%08lX%s%02X\n"
+#define SREC3_END "S70500000000FA\n"
+#define SREC_BYTES_PER_RECORD 16
+
+static int save_serial(ulong address, ulong count)
+{
+ int i, c, reclen, checksum, length;
+ char *hex = "0123456789ABCDEF";
+ char record[2*SREC_BYTES_PER_RECORD+16]; /* buffer for one S-Record */
+ char data[2*SREC_BYTES_PER_RECORD+1]; /* buffer for hex data */
+
+ reclen = 0;
+ checksum = 0;
+
+ if(write_record(SREC3_START)) /* write the header */
+ return (-1);
+ do {
+ if(count) { /* collect hex data in the buffer */
+ c = *(volatile uchar*)(address + reclen); /* get one byte */
+ checksum += c; /* accumulate checksum */
+ data[2*reclen] = hex[(c>>4)&0x0f];
+ data[2*reclen+1] = hex[c & 0x0f];
+ data[2*reclen+2] = '\0';
+ ++reclen;
+ --count;
+ }
+ if(reclen == SREC_BYTES_PER_RECORD || count == 0) {
+ /* enough data collected for one record: dump it */
+ if(reclen) { /* build & write a data record: */
+ /* address + data + checksum */
+ length = 4 + reclen + 1;
+
+ /* accumulate length bytes into checksum */
+ for(i = 0; i < 2; i++)
+ checksum += (length >> (8*i)) & 0xff;
+
+ /* accumulate address bytes into checksum: */
+ for(i = 0; i < 4; i++)
+ checksum += (address >> (8*i)) & 0xff;
+
+ /* make proper checksum byte: */
+ checksum = ~checksum & 0xff;
+
+ /* output one record: */
+ sprintf(record, SREC3_FORMAT, length, address, data, checksum);
+ if(write_record(record))
+ return (-1);
+ }
+ address += reclen; /* increment address */
+ checksum = 0;
+ reclen = 0;
+ }
+ }
+ while(count);
+ if(write_record(SREC3_END)) /* write the final record */
+ return (-1);
+ return(0);
+}
+
+static int write_record(char *buf)
+{
+ char c;
+
+ while((c = *buf++))
+ putc(c);
+
+ /* Check for the console hangup (if any different from serial) */
+
+ if (ctrlc()) {
+ return (-1);
+ }
+ return (0);
+}
+# endif
+
+#endif
+
+
+#if defined(CONFIG_CMD_LOADB)
+/*
+ * loadb command (load binary) included
+ */
+#define XON_CHAR 17
+#define XOFF_CHAR 19
+#define START_CHAR 0x01
+#define ETX_CHAR 0x03
+#define END_CHAR 0x0D
+#define SPACE 0x20
+#define K_ESCAPE 0x23
+#define SEND_TYPE 'S'
+#define DATA_TYPE 'D'
+#define ACK_TYPE 'Y'
+#define NACK_TYPE 'N'
+#define BREAK_TYPE 'B'
+#define tochar(x) ((char) (((x) + SPACE) & 0xff))
+#define untochar(x) ((int) (((x) - SPACE) & 0xff))
+
+static void set_kerm_bin_mode(unsigned long *);
+static int k_recv(void);
+static ulong load_serial_bin(ulong offset);
+
+
+static char his_eol; /* character he needs at end of packet */
+static int his_pad_count; /* number of pad chars he needs */
+static char his_pad_char; /* pad chars he needs */
+static char his_quote; /* quote chars he'll use */
+
+static int do_load_serial_bin(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong offset = 0;
+ ulong addr;
+ int load_baudrate, current_baudrate;
+ int rcode = 0;
+ char *s;
+
+ /* pre-set offset from CONFIG_SYS_LOAD_ADDR */
+ offset = CONFIG_SYS_LOAD_ADDR;
+
+ /* pre-set offset from $loadaddr */
+ s = env_get("loadaddr");
+ if (s)
+ offset = simple_strtoul(s, NULL, 16);
+
+ load_baudrate = current_baudrate = gd->baudrate;
+
+ if (argc >= 2) {
+ offset = simple_strtoul(argv[1], NULL, 16);
+ }
+ if (argc == 3) {
+ load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
+
+ /* default to current baudrate */
+ if (load_baudrate == 0)
+ load_baudrate = current_baudrate;
+ }
+
+ if (load_baudrate != current_baudrate) {
+ printf("## Switch baudrate to %d bps and press ENTER ...\n",
+ load_baudrate);
+ udelay(50000);
+ gd->baudrate = load_baudrate;
+ serial_setbrg();
+ udelay(50000);
+ for (;;) {
+ if (getchar() == '\r')
+ break;
+ }
+ }
+
+ if (strcmp(argv[0],"loady")==0) {
+ printf("## Ready for binary (ymodem) download "
+ "to 0x%08lX at %d bps...\n",
+ offset,
+ load_baudrate);
+
+ addr = load_serial_ymodem(offset, xyzModem_ymodem);
+
+ } else if (strcmp(argv[0],"loadx")==0) {
+ printf("## Ready for binary (xmodem) download "
+ "to 0x%08lX at %d bps...\n",
+ offset,
+ load_baudrate);
+
+ addr = load_serial_ymodem(offset, xyzModem_xmodem);
+
+ } else {
+
+ printf("## Ready for binary (kermit) download "
+ "to 0x%08lX at %d bps...\n",
+ offset,
+ load_baudrate);
+ addr = load_serial_bin(offset);
+
+ if (addr == ~0) {
+ image_load_addr = 0;
+ printf("## Binary (kermit) download aborted\n");
+ rcode = 1;
+ } else {
+ printf("## Start Addr = 0x%08lX\n", addr);
+ image_load_addr = addr;
+ }
+ }
+ if (load_baudrate != current_baudrate) {
+ printf("## Switch baudrate to %d bps and press ESC ...\n",
+ current_baudrate);
+ udelay(50000);
+ gd->baudrate = current_baudrate;
+ serial_setbrg();
+ udelay(50000);
+ for (;;) {
+ if (getchar() == 0x1B) /* ESC */
+ break;
+ }
+ }
+
+ return rcode;
+}
+
+
+static ulong load_serial_bin(ulong offset)
+{
+ int size, i;
+
+ set_kerm_bin_mode((ulong *) offset);
+ size = k_recv();
+
+ /*
+ * Gather any trailing characters (for instance, the ^D which
+ * is sent by 'cu' after sending a file), and give the
+ * box some time (100 * 1 ms)
+ */
+ for (i=0; i<100; ++i) {
+ if (tstc()) {
+ getchar();
+ }
+ udelay(1000);
+ }
+
+ flush_cache(offset, size);
+
+ printf("## Total Size = 0x%08x = %d Bytes\n", size, size);
+ env_set_hex("filesize", size);
+
+ return offset;
+}
+
+static void send_pad(void)
+{
+ int count = his_pad_count;
+
+ while (count-- > 0)
+ putc(his_pad_char);
+}
+
+/* converts escaped kermit char to binary char */
+static char ktrans(char in)
+{
+ if ((in & 0x60) == 0x40) {
+ return (char) (in & ~0x40);
+ } else if ((in & 0x7f) == 0x3f) {
+ return (char) (in | 0x40);
+ } else
+ return in;
+}
+
+static int chk1(char *buffer)
+{
+ int total = 0;
+
+ while (*buffer) {
+ total += *buffer++;
+ }
+ return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);
+}
+
+static void s1_sendpacket(char *packet)
+{
+ send_pad();
+ while (*packet) {
+ putc(*packet++);
+ }
+}
+
+static char a_b[24];
+static void send_ack(int n)
+{
+ a_b[0] = START_CHAR;
+ a_b[1] = tochar(3);
+ a_b[2] = tochar(n);
+ a_b[3] = ACK_TYPE;
+ a_b[4] = '\0';
+ a_b[4] = tochar(chk1(&a_b[1]));
+ a_b[5] = his_eol;
+ a_b[6] = '\0';
+ s1_sendpacket(a_b);
+}
+
+static void send_nack(int n)
+{
+ a_b[0] = START_CHAR;
+ a_b[1] = tochar(3);
+ a_b[2] = tochar(n);
+ a_b[3] = NACK_TYPE;
+ a_b[4] = '\0';
+ a_b[4] = tochar(chk1(&a_b[1]));
+ a_b[5] = his_eol;
+ a_b[6] = '\0';
+ s1_sendpacket(a_b);
+}
+
+
+static void (*os_data_init)(void);
+static void (*os_data_char)(char new_char);
+static int os_data_state, os_data_state_saved;
+static char *os_data_addr, *os_data_addr_saved;
+static char *bin_start_address;
+
+static void bin_data_init(void)
+{
+ os_data_state = 0;
+ os_data_addr = bin_start_address;
+}
+
+static void os_data_save(void)
+{
+ os_data_state_saved = os_data_state;
+ os_data_addr_saved = os_data_addr;
+}
+
+static void os_data_restore(void)
+{
+ os_data_state = os_data_state_saved;
+ os_data_addr = os_data_addr_saved;
+}
+
+static void bin_data_char(char new_char)
+{
+ switch (os_data_state) {
+ case 0: /* data */
+ *os_data_addr++ = new_char;
+ break;
+ }
+}
+
+static void set_kerm_bin_mode(unsigned long *addr)
+{
+ bin_start_address = (char *) addr;
+ os_data_init = bin_data_init;
+ os_data_char = bin_data_char;
+}
+
+
+/* k_data_* simply handles the kermit escape translations */
+static int k_data_escape, k_data_escape_saved;
+static void k_data_init(void)
+{
+ k_data_escape = 0;
+ os_data_init();
+}
+
+static void k_data_save(void)
+{
+ k_data_escape_saved = k_data_escape;
+ os_data_save();
+}
+
+static void k_data_restore(void)
+{
+ k_data_escape = k_data_escape_saved;
+ os_data_restore();
+}
+
+static void k_data_char(char new_char)
+{
+ if (k_data_escape) {
+ /* last char was escape - translate this character */
+ os_data_char(ktrans(new_char));
+ k_data_escape = 0;
+ } else {
+ if (new_char == his_quote) {
+ /* this char is escape - remember */
+ k_data_escape = 1;
+ } else {
+ /* otherwise send this char as-is */
+ os_data_char(new_char);
+ }
+ }
+}
+
+#define SEND_DATA_SIZE 20
+static char send_parms[SEND_DATA_SIZE];
+static char *send_ptr;
+
+/* handle_send_packet interprits the protocol info and builds and
+ sends an appropriate ack for what we can do */
+static void handle_send_packet(int n)
+{
+ int length = 3;
+ int bytes;
+
+ /* initialize some protocol parameters */
+ his_eol = END_CHAR; /* default end of line character */
+ his_pad_count = 0;
+ his_pad_char = '\0';
+ his_quote = K_ESCAPE;
+
+ /* ignore last character if it filled the buffer */
+ if (send_ptr == &send_parms[SEND_DATA_SIZE - 1])
+ --send_ptr;
+ bytes = send_ptr - send_parms; /* how many bytes we'll process */
+ do {
+ if (bytes-- <= 0)
+ break;
+ /* handle MAXL - max length */
+ /* ignore what he says - most I'll take (here) is 94 */
+ a_b[++length] = tochar(94);
+ if (bytes-- <= 0)
+ break;
+ /* handle TIME - time you should wait for my packets */
+ /* ignore what he says - don't wait for my ack longer than 1 second */
+ a_b[++length] = tochar(1);
+ if (bytes-- <= 0)
+ break;
+ /* handle NPAD - number of pad chars I need */
+ /* remember what he says - I need none */
+ his_pad_count = untochar(send_parms[2]);
+ a_b[++length] = tochar(0);
+ if (bytes-- <= 0)
+ break;
+ /* handle PADC - pad chars I need */
+ /* remember what he says - I need none */
+ his_pad_char = ktrans(send_parms[3]);
+ a_b[++length] = 0x40; /* He should ignore this */
+ if (bytes-- <= 0)
+ break;
+ /* handle EOL - end of line he needs */
+ /* remember what he says - I need CR */
+ his_eol = untochar(send_parms[4]);
+ a_b[++length] = tochar(END_CHAR);
+ if (bytes-- <= 0)
+ break;
+ /* handle QCTL - quote control char he'll use */
+ /* remember what he says - I'll use '#' */
+ his_quote = send_parms[5];
+ a_b[++length] = '#';
+ if (bytes-- <= 0)
+ break;
+ /* handle QBIN - 8-th bit prefixing */
+ /* ignore what he says - I refuse */
+ a_b[++length] = 'N';
+ if (bytes-- <= 0)
+ break;
+ /* handle CHKT - the clock check type */
+ /* ignore what he says - I do type 1 (for now) */
+ a_b[++length] = '1';
+ if (bytes-- <= 0)
+ break;
+ /* handle REPT - the repeat prefix */
+ /* ignore what he says - I refuse (for now) */
+ a_b[++length] = 'N';
+ if (bytes-- <= 0)
+ break;
+ /* handle CAPAS - the capabilities mask */
+ /* ignore what he says - I only do long packets - I don't do windows */
+ a_b[++length] = tochar(2); /* only long packets */
+ a_b[++length] = tochar(0); /* no windows */
+ a_b[++length] = tochar(94); /* large packet msb */
+ a_b[++length] = tochar(94); /* large packet lsb */
+ } while (0);
+
+ a_b[0] = START_CHAR;
+ a_b[1] = tochar(length);
+ a_b[2] = tochar(n);
+ a_b[3] = ACK_TYPE;
+ a_b[++length] = '\0';
+ a_b[length] = tochar(chk1(&a_b[1]));
+ a_b[++length] = his_eol;
+ a_b[++length] = '\0';
+ s1_sendpacket(a_b);
+}
+
+/* k_recv receives a OS Open image file over kermit line */
+static int k_recv(void)
+{
+ char new_char;
+ char k_state, k_state_saved;
+ int sum;
+ int done;
+ int length;
+ int n, last_n;
+ int len_lo, len_hi;
+
+ /* initialize some protocol parameters */
+ his_eol = END_CHAR; /* default end of line character */
+ his_pad_count = 0;
+ his_pad_char = '\0';
+ his_quote = K_ESCAPE;
+
+ /* initialize the k_recv and k_data state machine */
+ done = 0;
+ k_state = 0;
+ k_data_init();
+ k_state_saved = k_state;
+ k_data_save();
+ n = 0; /* just to get rid of a warning */
+ last_n = -1;
+
+ /* expect this "type" sequence (but don't check):
+ S: send initiate
+ F: file header
+ D: data (multiple)
+ Z: end of file
+ B: break transmission
+ */
+
+ /* enter main loop */
+ while (!done) {
+ /* set the send packet pointer to begining of send packet parms */
+ send_ptr = send_parms;
+
+ /* With each packet, start summing the bytes starting with the length.
+ Save the current sequence number.
+ Note the type of the packet.
+ If a character less than SPACE (0x20) is received - error.
+ */
+
+#if 0
+ /* OLD CODE, Prior to checking sequence numbers */
+ /* first have all state machines save current states */
+ k_state_saved = k_state;
+ k_data_save ();
+#endif
+
+ /* get a packet */
+ /* wait for the starting character or ^C */
+ for (;;) {
+ switch (getchar()) {
+ case START_CHAR: /* start packet */
+ goto START;
+ case ETX_CHAR: /* ^C waiting for packet */
+ return (0);
+ default:
+ ;
+ }
+ }
+START:
+ /* get length of packet */
+ sum = 0;
+ new_char = getchar();
+ if ((new_char & 0xE0) == 0)
+ goto packet_error;
+ sum += new_char & 0xff;
+ length = untochar(new_char);
+ /* get sequence number */
+ new_char = getchar();
+ if ((new_char & 0xE0) == 0)
+ goto packet_error;
+ sum += new_char & 0xff;
+ n = untochar(new_char);
+ --length;
+
+ /* NEW CODE - check sequence numbers for retried packets */
+ /* Note - this new code assumes that the sequence number is correctly
+ * received. Handling an invalid sequence number adds another layer
+ * of complexity that may not be needed - yet! At this time, I'm hoping
+ * that I don't need to buffer the incoming data packets and can write
+ * the data into memory in real time.
+ */
+ if (n == last_n) {
+ /* same sequence number, restore the previous state */
+ k_state = k_state_saved;
+ k_data_restore();
+ } else {
+ /* new sequence number, checkpoint the download */
+ last_n = n;
+ k_state_saved = k_state;
+ k_data_save();
+ }
+ /* END NEW CODE */
+
+ /* get packet type */
+ new_char = getchar();
+ if ((new_char & 0xE0) == 0)
+ goto packet_error;
+ sum += new_char & 0xff;
+ k_state = new_char;
+ --length;
+ /* check for extended length */
+ if (length == -2) {
+ /* (length byte was 0, decremented twice) */
+ /* get the two length bytes */
+ new_char = getchar();
+ if ((new_char & 0xE0) == 0)
+ goto packet_error;
+ sum += new_char & 0xff;
+ len_hi = untochar(new_char);
+ new_char = getchar();
+ if ((new_char & 0xE0) == 0)
+ goto packet_error;
+ sum += new_char & 0xff;
+ len_lo = untochar(new_char);
+ length = len_hi * 95 + len_lo;
+ /* check header checksum */
+ new_char = getchar();
+ if ((new_char & 0xE0) == 0)
+ goto packet_error;
+ if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
+ goto packet_error;
+ sum += new_char & 0xff;
+/* --length; */ /* new length includes only data and block check to come */
+ }
+ /* bring in rest of packet */
+ while (length > 1) {
+ new_char = getchar();
+ if ((new_char & 0xE0) == 0)
+ goto packet_error;
+ sum += new_char & 0xff;
+ --length;
+ if (k_state == DATA_TYPE) {
+ /* pass on the data if this is a data packet */
+ k_data_char (new_char);
+ } else if (k_state == SEND_TYPE) {
+ /* save send pack in buffer as is */
+ *send_ptr++ = new_char;
+ /* if too much data, back off the pointer */
+ if (send_ptr >= &send_parms[SEND_DATA_SIZE])
+ --send_ptr;
+ }
+ }
+ /* get and validate checksum character */
+ new_char = getchar();
+ if ((new_char & 0xE0) == 0)
+ goto packet_error;
+ if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
+ goto packet_error;
+ /* get END_CHAR */
+ new_char = getchar();
+ if (new_char != END_CHAR) {
+ packet_error:
+ /* restore state machines */
+ k_state = k_state_saved;
+ k_data_restore();
+ /* send a negative acknowledge packet in */
+ send_nack(n);
+ } else if (k_state == SEND_TYPE) {
+ /* crack the protocol parms, build an appropriate ack packet */
+ handle_send_packet(n);
+ } else {
+ /* send simple acknowledge packet in */
+ send_ack(n);
+ /* quit if end of transmission */
+ if (k_state == BREAK_TYPE)
+ done = 1;
+ }
+ }
+ return ((ulong) os_data_addr - (ulong) bin_start_address);
+}
+
+static int getcxmodem(void) {
+ if (tstc())
+ return (getchar());
+ return -1;
+}
+static ulong load_serial_ymodem(ulong offset, int mode)
+{
+ int size;
+ int err;
+ int res;
+ connection_info_t info;
+ char ymodemBuf[1024];
+ ulong store_addr = ~0;
+ ulong addr = 0;
+
+ size = 0;
+ info.mode = mode;
+ res = xyzModem_stream_open(&info, &err);
+ if (!res) {
+
+ while ((res =
+ xyzModem_stream_read(ymodemBuf, 1024, &err)) > 0) {
+ store_addr = addr + offset;
+ size += res;
+ addr += res;
+#ifdef CONFIG_MTD_NOR_FLASH
+ if (addr2info(store_addr)) {
+ int rc;
+
+ rc = flash_write((char *) ymodemBuf,
+ store_addr, res);
+ if (rc != 0) {
+ flash_perror(rc);
+ return (~0);
+ }
+ } else
+#endif
+ {
+ memcpy((char *)(store_addr), ymodemBuf,
+ res);
+ }
+
+ }
+ if (IS_ENABLED(CONFIG_CMD_BOOTEFI))
+ efi_set_bootdev("Uart", "", "",
+ map_sysmem(offset, 0), size);
+
+ } else {
+ printf("%s\n", xyzModem_error(err));
+ }
+
+ xyzModem_stream_close(&err);
+ xyzModem_stream_terminate(false, &getcxmodem);
+
+
+ flush_cache(offset, ALIGN(size, ARCH_DMA_MINALIGN));
+
+ printf("## Total Size = 0x%08x = %d Bytes\n", size, size);
+ env_set_hex("filesize", size);
+
+ return offset;
+}
+
+#endif
+
+/* -------------------------------------------------------------------- */
+
+#if defined(CONFIG_CMD_LOADS)
+
+#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
+U_BOOT_CMD(
+ loads, 3, 0, do_load_serial,
+ "load S-Record file over serial line",
+ "[ off ] [ baud ]\n"
+ " - load S-Record file over serial line"
+ " with offset 'off' and baudrate 'baud'"
+);
+
+#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
+U_BOOT_CMD(
+ loads, 2, 0, do_load_serial,
+ "load S-Record file over serial line",
+ "[ off ]\n"
+ " - load S-Record file over serial line with offset 'off'"
+);
+#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */
+
+/*
+ * SAVES always requires LOADS support, but not vice versa
+ */
+
+
+#if defined(CONFIG_CMD_SAVES)
+#ifdef CONFIG_SYS_LOADS_BAUD_CHANGE
+U_BOOT_CMD(
+ saves, 4, 0, do_save_serial,
+ "save S-Record file over serial line",
+ "[ off ] [size] [ baud ]\n"
+ " - save S-Record file over serial line"
+ " with offset 'off', size 'size' and baudrate 'baud'"
+);
+#else /* ! CONFIG_SYS_LOADS_BAUD_CHANGE */
+U_BOOT_CMD(
+ saves, 3, 0, do_save_serial,
+ "save S-Record file over serial line",
+ "[ off ] [size]\n"
+ " - save S-Record file over serial line with offset 'off' and size 'size'"
+);
+#endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */
+#endif /* CONFIG_CMD_SAVES */
+#endif /* CONFIG_CMD_LOADS */
+
+
+#if defined(CONFIG_CMD_LOADB)
+U_BOOT_CMD(
+ loadb, 3, 0, do_load_serial_bin,
+ "load binary file over serial line (kermit mode)",
+ "[ addr [ baud ] ]\n"
+ " - load binary file over serial line"
+ " at address 'addr' with baudrate 'baud'"
+);
+
+U_BOOT_CMD(
+ loadx, 3, 0, do_load_serial_bin,
+ "load binary file over serial line (xmodem mode)",
+ "[ addr [ baud ] ]\n"
+ " - load binary file over serial line"
+ " at address 'addr' with baudrate 'baud'"
+);
+
+U_BOOT_CMD(
+ loady, 3, 0, do_load_serial_bin,
+ "load binary file over serial line (ymodem mode)",
+ "[ addr [ baud ] ]\n"
+ " - load binary file over serial line"
+ " at address 'addr' with baudrate 'baud'"
+);
+
+#endif /* CONFIG_CMD_LOADB */
diff --git a/roms/u-boot/cmd/log.c b/roms/u-boot/cmd/log.c
new file mode 100644
index 000000000..72380c569
--- /dev/null
+++ b/roms/u-boot/cmd/log.c
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <getopt.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+
+static char log_fmt_chars[LOGF_COUNT] = "clFLfm";
+
+static enum log_level_t parse_log_level(char *const arg)
+{
+ enum log_level_t ret;
+ ulong level;
+
+ if (!strict_strtoul(arg, 10, &level)) {
+ if (level > _LOG_MAX_LEVEL) {
+ printf("Only log levels <= %d are supported\n",
+ _LOG_MAX_LEVEL);
+ return LOGL_NONE;
+ }
+ return level;
+ }
+
+ ret = log_get_level_by_name(arg);
+ if (ret == LOGL_NONE)
+ printf("Unknown log level \"%s\"\n", arg);
+ return ret;
+}
+
+static int do_log_level(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum log_level_t log_level;
+
+ if (argc > 1) {
+ log_level = parse_log_level(argv[1]);
+
+ if (log_level == LOGL_NONE)
+ return CMD_RET_FAILURE;
+ gd->default_log_level = log_level;
+ } else {
+ for (log_level = LOGL_FIRST; log_level <= _LOG_MAX_LEVEL;
+ log_level++)
+ printf("%s%s\n", log_get_level_name(log_level),
+ log_level == gd->default_log_level ?
+ " (default)" : "");
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_log_categories(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum log_category_t cat;
+ const char *name;
+
+ for (cat = LOGC_FIRST; cat < LOGC_COUNT; cat++) {
+ name = log_get_cat_name(cat);
+ /*
+ * Invalid category names (e.g. <invalid> or <missing>) begin
+ * with '<'.
+ */
+ if (name[0] == '<')
+ continue;
+ printf("%s\n", name);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_log_drivers(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct log_device *ldev;
+
+ list_for_each_entry(ldev, &gd->log_head, sibling_node)
+ printf("%s\n", ldev->drv->name);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_log_filter_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int opt;
+ const char *drv_name = "console";
+ struct getopt_state gs;
+ struct log_filter *filt;
+ struct log_device *ldev;
+
+ getopt_init_state(&gs);
+ while ((opt = getopt(&gs, argc, argv, "d:")) > 0) {
+ switch (opt) {
+ case 'd':
+ drv_name = gs.arg;
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+
+ if (gs.index != argc)
+ return CMD_RET_USAGE;
+
+ ldev = log_device_find_by_name(drv_name);
+ if (!ldev) {
+ printf("Could not find log device for \"%s\"\n", drv_name);
+ return CMD_RET_FAILURE;
+ }
+
+ /* <3> < 6 > <2+1 + 7 > < 16 > < unbounded... */
+ printf("num policy level categories files\n");
+ list_for_each_entry(filt, &ldev->filter_head, sibling_node) {
+ printf("%3d %6.6s %s %-7.7s ", filt->filter_num,
+ filt->flags & LOGFF_DENY ? "deny" : "allow",
+ filt->flags & LOGFF_LEVEL_MIN ? ">=" : "<=",
+ log_get_level_name(filt->level));
+
+ if (filt->flags & LOGFF_HAS_CAT) {
+ int i;
+
+ if (filt->cat_list[0] != LOGC_END)
+ printf("%16.16s %s\n",
+ log_get_cat_name(filt->cat_list[0]),
+ filt->file_list ? filt->file_list : "");
+
+ for (i = 1; i < LOGF_MAX_CATEGORIES &&
+ filt->cat_list[i] != LOGC_END; i++)
+ printf("%21c %16.16s\n", ' ',
+ log_get_cat_name(filt->cat_list[i]));
+ } else {
+ printf("%16c %s\n", ' ',
+ filt->file_list ? filt->file_list : "");
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_log_filter_add(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bool level_set = false;
+ bool print_num = false;
+ bool type_set = false;
+ char *file_list = NULL;
+ const char *drv_name = "console";
+ int opt, err;
+ int cat_count = 0;
+ int flags = 0;
+ enum log_category_t cat_list[LOGF_MAX_CATEGORIES + 1];
+ enum log_level_t level = LOGL_MAX;
+ struct getopt_state gs;
+
+ getopt_init_state(&gs);
+ while ((opt = getopt(&gs, argc, argv, "Ac:d:Df:l:L:p")) > 0) {
+ switch (opt) {
+ case 'A':
+#define do_type() do { \
+ if (type_set) { \
+ printf("Allow or deny set twice\n"); \
+ return CMD_RET_USAGE; \
+ } \
+ type_set = true; \
+} while (0)
+ do_type();
+ break;
+ case 'c': {
+ enum log_category_t cat;
+
+ if (cat_count >= LOGF_MAX_CATEGORIES) {
+ printf("Too many categories\n");
+ return CMD_RET_FAILURE;
+ }
+
+ cat = log_get_cat_by_name(gs.arg);
+ if (cat == LOGC_NONE) {
+ printf("Unknown category \"%s\"\n", gs.arg);
+ return CMD_RET_FAILURE;
+ }
+
+ cat_list[cat_count++] = cat;
+ break;
+ }
+ case 'd':
+ drv_name = gs.arg;
+ break;
+ case 'D':
+ do_type();
+ flags |= LOGFF_DENY;
+ break;
+ case 'f':
+ file_list = gs.arg;
+ break;
+ case 'l':
+#define do_level() do { \
+ if (level_set) { \
+ printf("Log level set twice\n"); \
+ return CMD_RET_USAGE; \
+ } \
+ level = parse_log_level(gs.arg); \
+ if (level == LOGL_NONE) \
+ return CMD_RET_FAILURE; \
+ level_set = true; \
+} while (0)
+ do_level();
+ break;
+ case 'L':
+ do_level();
+ flags |= LOGFF_LEVEL_MIN;
+ break;
+ case 'p':
+ print_num = true;
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+
+ if (gs.index != argc)
+ return CMD_RET_USAGE;
+
+ cat_list[cat_count] = LOGC_END;
+ err = log_add_filter_flags(drv_name, cat_count ? cat_list : NULL, level,
+ file_list, flags);
+ if (err < 0) {
+ printf("Could not add filter (err = %d)\n", err);
+ return CMD_RET_FAILURE;
+ } else if (print_num) {
+ printf("%d\n", err);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_log_filter_remove(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bool all = false;
+ int opt, err;
+ ulong filter_num;
+ const char *drv_name = "console";
+ struct getopt_state gs;
+
+ getopt_init_state(&gs);
+ while ((opt = getopt(&gs, argc, argv, "ad:")) > 0) {
+ switch (opt) {
+ case 'a':
+ all = true;
+ break;
+ case 'd':
+ drv_name = gs.arg;
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+
+ if (all) {
+ struct log_filter *filt, *tmp_filt;
+ struct log_device *ldev;
+
+ if (gs.index != argc)
+ return CMD_RET_USAGE;
+
+ ldev = log_device_find_by_name(drv_name);
+ if (!ldev) {
+ printf("Could not find log device for \"%s\"\n",
+ drv_name);
+ return CMD_RET_FAILURE;
+ }
+
+ list_for_each_entry_safe(filt, tmp_filt, &ldev->filter_head,
+ sibling_node) {
+ list_del(&filt->sibling_node);
+ free(filt);
+ }
+ } else {
+ if (gs.index + 1 != argc)
+ return CMD_RET_USAGE;
+
+ if (strict_strtoul(argv[gs.index], 10, &filter_num)) {
+ printf("Invalid filter number \"%s\"\n", argv[gs.index]);
+ return CMD_RET_FAILURE;
+ }
+
+ err = log_remove_filter(drv_name, filter_num);
+ if (err) {
+ printf("Could not remove filter (err = %d)\n", err);
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_log_format(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int i;
+
+ if (argc > 1) {
+ const char *str = argv[1];
+
+ if (!strcmp(str, "default")) {
+ gd->log_fmt = log_get_default_format();
+ } else if (!strcmp(str, "all")) {
+ gd->log_fmt = LOGF_ALL;
+ } else {
+ gd->log_fmt = 0;
+ for (; *str; str++) {
+ char *ptr = strchr(log_fmt_chars, *str);
+
+ if (!ptr) {
+ printf("Invalid log char '%c'\n", *str);
+ return CMD_RET_FAILURE;
+ }
+ gd->log_fmt |= 1 << (ptr - log_fmt_chars);
+ }
+ }
+ } else {
+ printf("Log format: ");
+ for (i = 0; i < LOGF_COUNT; i++) {
+ if (gd->log_fmt & (1 << i))
+ printf("%c", log_fmt_chars[i]);
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
+
+static int do_log_rec(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum log_category_t cat;
+ enum log_level_t level;
+ const char *file;
+ uint line;
+ const char *func;
+ const char *msg;
+ char *end;
+
+ if (argc < 7)
+ return CMD_RET_USAGE;
+ cat = log_get_cat_by_name(argv[1]);
+ level = simple_strtoul(argv[2], &end, 10);
+ if (end == argv[2]) {
+ level = log_get_level_by_name(argv[2]);
+
+ if (level == LOGL_NONE) {
+ printf("Invalid log level '%s'\n", argv[2]);
+ return CMD_RET_USAGE;
+ }
+ }
+ if (level >= LOGL_MAX) {
+ printf("Invalid log level %u\n", level);
+ return CMD_RET_USAGE;
+ }
+ file = argv[3];
+ line = simple_strtoul(argv[4], NULL, 10);
+ func = argv[5];
+ msg = argv[6];
+ if (_log(cat, level, file, line, func, "%s\n", msg))
+ return CMD_RET_FAILURE;
+
+ return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char log_help_text[] =
+ "level [<level>] - get/set log level\n"
+ "categories - list log categories\n"
+ "drivers - list log drivers\n"
+ "log filter-list [OPTIONS] - list all filters for a log driver\n"
+ "\t-d <driver> - Specify the log driver to list filters from; defaults\n"
+ "\t to console\n"
+ "log filter-add [OPTIONS] - add a new filter to a driver\n"
+ "\t-A - Allow messages matching this filter; mutually exclusive with -D\n"
+ "\t This is the default.\n"
+ "\t-c <category> - Category to match; may be specified multiple times\n"
+ "\t-d <driver> - Specify the log driver to add the filter to; defaults\n"
+ "\t to console\n"
+ "\t-D - Deny messages matching this filter; mutually exclusive with -A\n"
+ "\t-f <files_list> - A comma-separated list of files to match\n"
+ "\t-l <level> - Match log levels less than or equal to <level>;\n"
+ "\t mutually-exclusive with -L\n"
+ "\t-L <level> - Match log levels greather than or equal to <level>;\n"
+ "\t mutually-exclusive with -l\n"
+ "\t-p - Print the filter number on success\n"
+ "log filter-remove [OPTIONS] [<num>] - Remove filter number <num>\n"
+ "\t-a - Remove ALL filters\n"
+ "\t-d <driver> - Specify the log driver to remove the filter from;\n"
+ "\t defaults to console\n"
+ "log format <fmt> - set log output format. <fmt> is a string where\n"
+ "\teach letter indicates something that should be displayed:\n"
+ "\tc=category, l=level, F=file, L=line number, f=function, m=msg\n"
+ "\tor 'default', or 'all' for all\n"
+ "log rec <category> <level> <file> <line> <func> <message> - "
+ "output a log record"
+ ;
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(log, "log system", log_help_text,
+ U_BOOT_SUBCMD_MKENT(level, 2, 1, do_log_level),
+ U_BOOT_SUBCMD_MKENT(categories, 1, 1, do_log_categories),
+ U_BOOT_SUBCMD_MKENT(drivers, 1, 1, do_log_drivers),
+ U_BOOT_SUBCMD_MKENT(filter-list, 3, 1, do_log_filter_list),
+ U_BOOT_SUBCMD_MKENT(filter-add, CONFIG_SYS_MAXARGS, 1,
+ do_log_filter_add),
+ U_BOOT_SUBCMD_MKENT(filter-remove, 4, 1, do_log_filter_remove),
+ U_BOOT_SUBCMD_MKENT(format, 2, 1, do_log_format),
+ U_BOOT_SUBCMD_MKENT(rec, 7, 1, do_log_rec),
+);
diff --git a/roms/u-boot/cmd/lsblk.c b/roms/u-boot/cmd/lsblk.c
new file mode 100644
index 000000000..6a1c8f5ef
--- /dev/null
+++ b/roms/u-boot/cmd/lsblk.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020
+ * Niel Fourie, DENX Software Engineering, lusus@denx.de.
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <command.h>
+#include <dm.h>
+
+static int do_lsblk(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+ struct driver *d = ll_entry_start(struct driver, driver);
+ const int n_ents = ll_entry_count(struct driver, driver);
+ struct driver *entry;
+ struct udevice *udev;
+ struct uclass *uc;
+ struct blk_desc *desc;
+ int ret, i;
+
+ ret = uclass_get(UCLASS_BLK, &uc);
+ if (ret) {
+ puts("Could not get BLK uclass.\n");
+ return CMD_RET_FAILURE;
+ }
+ puts("Block Driver Devices\n");
+ puts("-----------------------------\n");
+ for (entry = d; entry < d + n_ents; entry++) {
+ if (entry->id != UCLASS_BLK)
+ continue;
+ i = 0;
+ printf("%-20.20s", entry->name);
+ uclass_foreach_dev(udev, uc) {
+ if (udev->driver != entry)
+ continue;
+ desc = dev_get_uclass_plat(udev);
+ printf("%c %s %u", i ? ',' : ':',
+ blk_get_if_type_name(desc->if_type),
+ desc->devnum);
+ i++;
+ }
+ if (!i)
+ puts(": <none>");
+ puts("\n");
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(lsblk, 1, 0, do_lsblk, "list block drivers and devices",
+ "- display list of block device drivers and attached block devices"
+);
diff --git a/roms/u-boot/cmd/lzmadec.c b/roms/u-boot/cmd/lzmadec.c
new file mode 100644
index 000000000..3b8db0a85
--- /dev/null
+++ b/roms/u-boot/cmd/lzmadec.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013 Patrice Bouchand <pbfwdlist_gmail_com>
+ * lzma uncompress command in Uboot
+ *
+ * made from existing cmd_unzip.c file of Uboot
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <mapmem.h>
+#include <asm/io.h>
+
+#include <lzma/LzmaTools.h>
+
+static int do_lzmadec(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long src, dst;
+ SizeT src_len = ~0UL, dst_len = ~0UL;
+ int ret;
+
+ switch (argc) {
+ case 4:
+ dst_len = simple_strtoul(argv[3], NULL, 16);
+ /* fall through */
+ case 3:
+ src = simple_strtoul(argv[1], NULL, 16);
+ dst = simple_strtoul(argv[2], NULL, 16);
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ ret = lzmaBuffToBuffDecompress(map_sysmem(dst, dst_len), &src_len,
+ map_sysmem(src, 0), dst_len);
+
+ if (ret != SZ_OK)
+ return 1;
+ printf("Uncompressed size: %ld = %#lX\n", (ulong)src_len,
+ (ulong)src_len);
+ env_set_hex("filesize", src_len);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ lzmadec, 4, 1, do_lzmadec,
+ "lzma uncompress a memory region",
+ "srcaddr dstaddr [dstsize]"
+);
diff --git a/roms/u-boot/cmd/mac.c b/roms/u-boot/cmd/mac.c
new file mode 100644
index 000000000..a39e1168a
--- /dev/null
+++ b/roms/u-boot/cmd/mac.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2006 Freescale Semiconductor
+ * York Sun (yorksun@freescale.com)
+ */
+
+#include <common.h>
+#include <command.h>
+
+extern int do_mac(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+
+U_BOOT_CMD(
+ mac, 3, 1, do_mac,
+ "display and program the system ID and MAC addresses in EEPROM",
+ "[read|save|id|num|errata|date|ports|port_number]\n"
+ "mac read\n"
+ " - read EEPROM content into memory data structure\n"
+ "mac save\n"
+ " - save memory data structure to the EEPROM\n"
+ "mac id\n"
+ " - program system id per hard coded value\n"
+ "mac num string\n"
+ " - program system serial number to value string\n"
+ "mac errata string\n"
+ " - program errata data to value string\n"
+ "mac date YYMMDDhhmmss\n"
+ " - program date to string value YYMMDDhhmmss\n"
+ "mac ports N\n"
+ " - program the number of network ports to integer N\n"
+ "mac X string\n"
+ " - program MAC addr for port X [X=0,1..] to colon separated string"
+);
diff --git a/roms/u-boot/cmd/mbr.c b/roms/u-boot/cmd/mbr.c
new file mode 100644
index 000000000..da2e3a472
--- /dev/null
+++ b/roms/u-boot/cmd/mbr.c
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * cmd_mbr.c -- MBR (Master Boot Record) handling command
+ *
+ * Copyright (C) 2020 Samsung Electronics
+ * author: Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * based on the gpt command.
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <command.h>
+#include <malloc.h>
+#include <part.h>
+
+/**
+ * extract_val() - Extract a value from the key=value pair list
+ * @str: pointer to string with key=values pairs
+ * @key: pointer to the key to search for
+ *
+ * The list of parameters is come separated, only a value for
+ * the given key is returend.
+ *
+ * Function allocates memory for the value, remember to free!
+ *
+ * Return: Pointer to allocated string with the value.
+ */
+static char *extract_val(const char *str, const char *key)
+{
+ char *v, *k;
+ char *s, *strcopy;
+ char *new = NULL;
+
+ strcopy = strdup(str);
+ if (strcopy == NULL)
+ return NULL;
+
+ s = strcopy;
+ while (s) {
+ v = strsep(&s, ",");
+ if (!v)
+ break;
+ k = strsep(&v, "=");
+ if (!k)
+ break;
+ if (strcmp(k, key) == 0) {
+ new = strdup(v);
+ break;
+ }
+ }
+
+ free(strcopy);
+
+ return new;
+}
+
+/**
+ * found_key() - Search for a key without a value in the parameter list
+ * @str: pointer to string with key
+ * @key: pointer to the key to search for
+ *
+ * The list of parameters is come separated.
+ *
+ * Return: True if key has been found.
+ */
+static bool found_key(const char *str, const char *key)
+{
+ char *k;
+ char *s, *strcopy;
+ bool result = false;
+
+ strcopy = strdup(str);
+ if (!strcopy)
+ return NULL;
+
+ s = strcopy;
+ while (s) {
+ k = strsep(&s, ",");
+ if (!k)
+ break;
+ if (strcmp(k, key) == 0) {
+ result = true;
+ break;
+ }
+ }
+
+ free(strcopy);
+
+ return result;
+}
+
+static int str_to_partitions(const char *str_part, int blksz,
+ unsigned long *disk_uuid, struct disk_partition **partitions,
+ int *parts_count)
+{
+ char *tok, *str, *s;
+ int i;
+ char *val, *p;
+ int p_count;
+ struct disk_partition *parts;
+ int errno = 0;
+ uint64_t size_ll, start_ll;
+
+ if (str_part == NULL)
+ return -1;
+
+ str = strdup(str_part);
+ if (str == NULL)
+ return -ENOMEM;
+
+ /* extract disk guid */
+ s = str;
+ val = extract_val(str, "uuid_disk");
+ if (val) {
+ val = strsep(&val, ";");
+ p = val;
+ *disk_uuid = ustrtoull(p, &p, 0);
+ free(val);
+ /* Move s to first partition */
+ strsep(&s, ";");
+ }
+ if (s == NULL) {
+ printf("Error: is the partitions string NULL-terminated?\n");
+ return -EINVAL;
+ }
+
+ /* remove the optional semicolon at the end of the string */
+ i = strlen(s) - 1;
+ if (s[i] == ';')
+ s[i] = '\0';
+
+ /* calculate expected number of partitions */
+ p_count = 1;
+ p = s;
+ while (*p) {
+ if (*p++ == ';')
+ p_count++;
+ }
+
+ /* allocate memory for partitions */
+ parts = calloc(sizeof(struct disk_partition), p_count);
+ if (parts == NULL)
+ return -ENOMEM;
+
+ /* retrieve partitions data from string */
+ for (i = 0; i < p_count; i++) {
+ tok = strsep(&s, ";");
+
+ if (tok == NULL)
+ break;
+
+ /* size */
+ val = extract_val(tok, "size");
+ if (!val) { /* 'size' is mandatory */
+ errno = -4;
+ goto err;
+ }
+ p = val;
+ if ((strcmp(p, "-") == 0)) {
+ /* auto extend the size */
+ parts[i].size = 0;
+ } else {
+ size_ll = ustrtoull(p, &p, 0);
+ parts[i].size = size_ll / blksz;
+ }
+ free(val);
+
+ /* start address */
+ val = extract_val(tok, "start");
+ if (val) { /* start address is optional */
+ p = val;
+ start_ll = ustrtoull(p, &p, 0);
+ parts[i].start = start_ll / blksz;
+ free(val);
+ }
+
+ /* system id */
+ val = extract_val(tok, "id");
+ if (!val) { /* '' is mandatory */
+ errno = -4;
+ goto err;
+ }
+ p = val;
+ parts[i].sys_ind = ustrtoul(p, &p, 0);
+ free(val);
+
+ /* bootable */
+ if (found_key(tok, "bootable"))
+ parts[i].bootable = PART_BOOTABLE;
+ }
+
+ *parts_count = p_count;
+ *partitions = parts;
+ free(str);
+
+ return 0;
+err:
+ free(str);
+ free(parts);
+
+ return errno;
+}
+
+static int do_write_mbr(struct blk_desc *dev, const char *str)
+{
+ unsigned long disk_uuid = 0;
+ struct disk_partition *partitions;
+ int blksz = dev->blksz;
+ int count;
+
+ if (str_to_partitions(str, blksz, &disk_uuid, &partitions, &count)) {
+ printf("MBR: failed to setup partitions from \"%s\"\n", str);
+ return -1;
+ }
+
+ if (layout_mbr_partitions(partitions, count, dev->lba)) {
+ printf("MBR: failed to layout partitions on the device\n");
+ free(partitions);
+ return -1;
+ }
+
+ if (write_mbr_partitions(dev, partitions, count, disk_uuid)) {
+ printf("MBR: failed to write partitions to the device\n");
+ free(partitions);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int do_verify_mbr(struct blk_desc *dev, const char *str)
+{
+ unsigned long disk_uuid = 0;
+ struct disk_partition *partitions;
+ int blksz = dev->blksz;
+ int count, i, ret = 1;
+
+ if (str_to_partitions(str, blksz, &disk_uuid, &partitions, &count)) {
+ printf("MBR: failed to setup partitions from \"%s\"\n", str);
+ return -1;
+ }
+
+ for (i = 0; i < count; i++) {
+ struct disk_partition p;
+
+ if (part_get_info(dev, i+1, &p))
+ goto fail;
+
+ if ((partitions[i].size && p.size < partitions[i].size) ||
+ (partitions[i].start && p.start < partitions[i].start) ||
+ (p.sys_ind != partitions[i].sys_ind))
+ goto fail;
+ }
+ ret = 0;
+fail:
+ free(partitions);
+ return ret;
+}
+
+static int do_mbr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const char *parts = NULL;
+ int ret = CMD_RET_SUCCESS;
+ int dev = 0;
+ char *ep;
+ struct blk_desc *blk_dev_desc = NULL;
+
+ if (argc != 4 && argc != 5)
+ return CMD_RET_USAGE;
+
+ dev = (int)simple_strtoul(argv[3], &ep, 10);
+ if (!ep || ep[0] != '\0') {
+ printf("'%s' is not a number\n", argv[3]);
+ return CMD_RET_USAGE;
+ }
+ blk_dev_desc = blk_get_dev(argv[2], dev);
+ if (!blk_dev_desc) {
+ printf("%s: %s dev %d NOT available\n",
+ __func__, argv[2], dev);
+ return CMD_RET_FAILURE;
+ }
+
+ if ((strcmp(argv[1], "write") == 0)) {
+ parts = (argc == 5) ? argv[4] : env_get("mbr_parts");
+ printf("MBR: write ");
+ ret = do_write_mbr(blk_dev_desc, parts);
+ } else if ((strcmp(argv[1], "verify") == 0)) {
+ printf("MBR: verify ");
+ parts = (argc == 5) ? argv[4] : env_get("mbr_parts");
+ ret = do_verify_mbr(blk_dev_desc, parts);
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ if (ret) {
+ printf("error!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ printf("success!\n");
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(mbr, CONFIG_SYS_MAXARGS, 1, do_mbr,
+ "MBR (Master Boot Record)",
+ "<command> <interface> <dev> <partitions_list>\n"
+ " - MBR partition table restoration utility\n"
+ " Restore or check partition information on a device connected\n"
+ " to the given block interface\n"
+ " Example usage:\n"
+ " mbr write mmc 0 [\"${mbr_parts}\"]\n"
+ " mbr verify mmc 0 [\"${partitions}\"]\n"
+);
diff --git a/roms/u-boot/cmd/md5sum.c b/roms/u-boot/cmd/md5sum.c
new file mode 100644
index 000000000..5ae3ddf85
--- /dev/null
+++ b/roms/u-boot/cmd/md5sum.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.com
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <mapmem.h>
+#include <u-boot/md5.h>
+#include <asm/io.h>
+
+/*
+ * Store the resulting sum to an address or variable
+ */
+static void store_result(const u8 *sum, const char *dest)
+{
+ unsigned int i;
+
+ if (*dest == '*') {
+ u8 *ptr;
+
+ ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16);
+ for (i = 0; i < 16; i++)
+ *ptr++ = sum[i];
+ } else {
+ char str_output[33];
+ char *str_ptr = str_output;
+
+ for (i = 0; i < 16; i++) {
+ sprintf(str_ptr, "%02x", sum[i]);
+ str_ptr += 2;
+ }
+ env_set(dest, str_output);
+ }
+}
+
+#ifdef CONFIG_MD5SUM_VERIFY
+static int parse_verify_sum(char *verify_str, u8 *vsum)
+{
+ if (*verify_str == '*') {
+ u8 *ptr;
+
+ ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16);
+ memcpy(vsum, ptr, 16);
+ } else {
+ unsigned int i;
+ char *vsum_str;
+
+ if (strlen(verify_str) == 32)
+ vsum_str = verify_str;
+ else {
+ vsum_str = env_get(verify_str);
+ if (vsum_str == NULL || strlen(vsum_str) != 32)
+ return 1;
+ }
+
+ for (i = 0; i < 16; i++) {
+ char *nullp = vsum_str + (i + 1) * 2;
+ char end = *nullp;
+
+ *nullp = '\0';
+ *(u8 *)(vsum + i) =
+ simple_strtoul(vsum_str + (i * 2), NULL, 16);
+ *nullp = end;
+ }
+ }
+ return 0;
+}
+
+int do_md5sum(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong addr, len;
+ unsigned int i;
+ u8 output[16];
+ u8 vsum[16];
+ int verify = 0;
+ int ac;
+ char * const *av;
+ void *buf;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ av = argv + 1;
+ ac = argc - 1;
+ if (strcmp(*av, "-v") == 0) {
+ verify = 1;
+ av++;
+ ac--;
+ if (ac < 3)
+ return CMD_RET_USAGE;
+ }
+
+ addr = simple_strtoul(*av++, NULL, 16);
+ len = simple_strtoul(*av++, NULL, 16);
+
+ buf = map_sysmem(addr, len);
+ md5_wd(buf, len, output, CHUNKSZ_MD5);
+ unmap_sysmem(buf);
+
+ if (!verify) {
+ printf("md5 for %08lx ... %08lx ==> ", addr, addr + len - 1);
+ for (i = 0; i < 16; i++)
+ printf("%02x", output[i]);
+ printf("\n");
+
+ if (ac > 2)
+ store_result(output, *av);
+ } else {
+ char *verify_str = *av++;
+
+ if (parse_verify_sum(verify_str, vsum)) {
+ printf("ERROR: %s does not contain a valid md5 sum\n",
+ verify_str);
+ return 1;
+ }
+ if (memcmp(output, vsum, 16) != 0) {
+ printf("md5 for %08lx ... %08lx ==> ", addr,
+ addr + len - 1);
+ for (i = 0; i < 16; i++)
+ printf("%02x", output[i]);
+ printf(" != ");
+ for (i = 0; i < 16; i++)
+ printf("%02x", vsum[i]);
+ printf(" ** ERROR **\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}
+#else
+static int do_md5sum(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long addr, len;
+ unsigned int i;
+ u8 output[16];
+ void *buf;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[1], NULL, 16);
+ len = simple_strtoul(argv[2], NULL, 16);
+
+ buf = map_sysmem(addr, len);
+ md5_wd(buf, len, output, CHUNKSZ_MD5);
+ unmap_sysmem(buf);
+
+ printf("md5 for %08lx ... %08lx ==> ", addr, addr + len - 1);
+ for (i = 0; i < 16; i++)
+ printf("%02x", output[i]);
+ printf("\n");
+
+ if (argc > 3)
+ store_result(output, argv[3]);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_MD5SUM_VERIFY
+U_BOOT_CMD(
+ md5sum, 5, 1, do_md5sum,
+ "compute MD5 message digest",
+ "address count [[*]sum]\n"
+ " - compute MD5 message digest [save to sum]\n"
+ "md5sum -v address count [*]sum\n"
+ " - verify md5sum of memory area"
+);
+#else
+U_BOOT_CMD(
+ md5sum, 4, 1, do_md5sum,
+ "compute MD5 message digest",
+ "address count [[*]sum]\n"
+ " - compute MD5 message digest [save to sum]"
+);
+#endif
diff --git a/roms/u-boot/cmd/mdio.c b/roms/u-boot/cmd/mdio.c
new file mode 100644
index 000000000..cfa45ad12
--- /dev/null
+++ b/roms/u-boot/cmd/mdio.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011 Freescale Semiconductor, Inc
+ * Andy Fleming
+ */
+
+/*
+ * MDIO Commands
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <phy.h>
+
+static char last_op[2];
+static uint last_data;
+static uint last_addr_lo;
+static uint last_addr_hi;
+static uint last_devad_lo;
+static uint last_devad_hi;
+static uint last_reg_lo;
+static uint last_reg_hi;
+
+static int extract_range(char *input, int *plo, int *phi)
+{
+ char *end;
+ *plo = simple_strtol(input, &end, 16);
+ if (end == input)
+ return -1;
+
+ if ((*end == '-') && *(++end))
+ *phi = simple_strtol(end, NULL, 16);
+ else if (*end == '\0')
+ *phi = *plo;
+ else
+ return -1;
+
+ return 0;
+}
+
+static int mdio_write_ranges(struct mii_dev *bus,
+ int addrlo,
+ int addrhi, int devadlo, int devadhi,
+ int reglo, int reghi, unsigned short data,
+ int extended)
+{
+ struct phy_device *phydev;
+ int addr, devad, reg;
+ int err = 0;
+
+ for (addr = addrlo; addr <= addrhi; addr++) {
+ phydev = bus->phymap[addr];
+
+ for (devad = devadlo; devad <= devadhi; devad++) {
+ for (reg = reglo; reg <= reghi; reg++) {
+ if (!phydev)
+ err = bus->write(bus, addr, devad,
+ reg, data);
+ else if (!extended)
+ err = phy_write_mmd(phydev, devad,
+ reg, data);
+ else
+ err = phydev->drv->writeext(phydev,
+ addr, devad, reg, data);
+
+ if (err)
+ goto err_out;
+ }
+ }
+ }
+
+err_out:
+ return err;
+}
+
+static int mdio_read_ranges(struct mii_dev *bus,
+ int addrlo,
+ int addrhi, int devadlo, int devadhi,
+ int reglo, int reghi, int extended)
+{
+ int addr, devad, reg;
+ struct phy_device *phydev;
+
+ printf("Reading from bus %s\n", bus->name);
+ for (addr = addrlo; addr <= addrhi; addr++) {
+ phydev = bus->phymap[addr];
+ printf("PHY at address %x:\n", addr);
+
+ for (devad = devadlo; devad <= devadhi; devad++) {
+ for (reg = reglo; reg <= reghi; reg++) {
+ int val;
+
+ if (!phydev)
+ val = bus->read(bus, addr, devad, reg);
+ else if (!extended)
+ val = phy_read_mmd(phydev, devad, reg);
+ else
+ val = phydev->drv->readext(phydev, addr,
+ devad, reg);
+
+ if (val < 0) {
+ printf("Error\n");
+
+ return val;
+ }
+
+ if (devad >= 0)
+ printf("%d.", devad);
+
+ printf("%d - 0x%x\n", reg, val & 0xffff);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* The register will be in the form [a[-b].]x[-y] */
+static int extract_reg_range(char *input, int *devadlo, int *devadhi,
+ int *reglo, int *reghi)
+{
+ char *regstr;
+
+ /* use strrchr to find the last string after a '.' */
+ regstr = strrchr(input, '.');
+
+ /* If it exists, extract the devad(s) */
+ if (regstr) {
+ char devadstr[32];
+
+ strncpy(devadstr, input, regstr - input);
+ devadstr[regstr - input] = '\0';
+
+ if (extract_range(devadstr, devadlo, devadhi))
+ return -1;
+
+ regstr++;
+ } else {
+ /* Otherwise, we have no devad, and we just got regs */
+ *devadlo = *devadhi = MDIO_DEVAD_NONE;
+
+ regstr = input;
+ }
+
+ return extract_range(regstr, reglo, reghi);
+}
+
+static int extract_phy_range(char *const argv[], int argc, struct mii_dev **bus,
+ struct phy_device **phydev,
+ int *addrlo, int *addrhi)
+{
+ struct phy_device *dev = *phydev;
+
+ if ((argc < 1) || (argc > 2))
+ return -1;
+
+ /* If there are two arguments, it's busname addr */
+ if (argc == 2) {
+ *bus = miiphy_get_dev_by_name(argv[0]);
+
+ if (!*bus)
+ return -1;
+
+ return extract_range(argv[1], addrlo, addrhi);
+ }
+
+ /* It must be one argument, here */
+
+ /*
+ * This argument can be one of two things:
+ * 1) Ethernet device name
+ * 2) Just an address (use the previously-used bus)
+ *
+ * We check all buses for a PHY which is connected to an ethernet
+ * device by the given name. If none are found, we call
+ * extract_range() on the string, and see if it's an address range.
+ */
+ dev = mdio_phydev_for_ethname(argv[0]);
+
+ if (dev) {
+ *addrlo = *addrhi = dev->addr;
+ *bus = dev->bus;
+
+ return 0;
+ }
+
+ /* It's an address or nothing useful */
+ return extract_range(argv[0], addrlo, addrhi);
+}
+
+/* ---------------------------------------------------------------- */
+static int do_mdio(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char op[2];
+ int addrlo, addrhi, reglo, reghi, devadlo, devadhi;
+ unsigned short data;
+ int pos = argc - 1;
+ struct mii_dev *bus;
+ struct phy_device *phydev = NULL;
+ int extended = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+#ifdef CONFIG_DM_MDIO
+ /* probe DM MII device before any operation so they are all accesible */
+ dm_mdio_probe_devices();
+#endif
+
+ /*
+ * We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ op[0] = argv[1][0];
+ addrlo = last_addr_lo;
+ addrhi = last_addr_hi;
+ devadlo = last_devad_lo;
+ devadhi = last_devad_hi;
+ reglo = last_reg_lo;
+ reghi = last_reg_hi;
+ data = last_data;
+
+ bus = mdio_get_current_dev();
+
+ if (flag & CMD_FLAG_REPEAT)
+ op[0] = last_op[0];
+
+ if (strlen(argv[1]) > 1) {
+ op[1] = argv[1][1];
+ if (op[1] == 'x') {
+ phydev = mdio_phydev_for_ethname(argv[2]);
+
+ if (phydev) {
+ addrlo = phydev->addr;
+ addrhi = addrlo;
+ bus = phydev->bus;
+ extended = 1;
+ } else {
+ return CMD_RET_FAILURE;
+ }
+
+ if (!phydev->drv ||
+ (!phydev->drv->writeext && (op[0] == 'w')) ||
+ (!phydev->drv->readext && (op[0] == 'r'))) {
+ puts("PHY does not have extended functions\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+ }
+
+ switch (op[0]) {
+ case 'w':
+ if (pos > 1)
+ data = simple_strtoul(argv[pos--], NULL, 16);
+ /* Intentional fall-through - Get reg for read and write */
+ case 'r':
+ if (pos > 1)
+ if (extract_reg_range(argv[pos--], &devadlo, &devadhi,
+ &reglo, &reghi))
+ return CMD_RET_FAILURE;
+ /* Intentional fall-through - Get phy for all commands */
+ default:
+ if (pos > 1)
+ if (extract_phy_range(&argv[2], pos - 1, &bus,
+ &phydev, &addrlo, &addrhi))
+ return CMD_RET_FAILURE;
+
+ break;
+ }
+
+ if (!bus) {
+ puts("No MDIO bus found\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (op[0] == 'l') {
+ mdio_list_devices();
+
+ return 0;
+ }
+
+ /* Save the chosen bus */
+ miiphy_set_current_dev(bus->name);
+
+ switch (op[0]) {
+ case 'w':
+ mdio_write_ranges(bus, addrlo, addrhi, devadlo, devadhi,
+ reglo, reghi, data, extended);
+ break;
+
+ case 'r':
+ mdio_read_ranges(bus, addrlo, addrhi, devadlo, devadhi,
+ reglo, reghi, extended);
+ break;
+ }
+
+ /*
+ * Save the parameters for repeats.
+ */
+ last_op[0] = op[0];
+ last_addr_lo = addrlo;
+ last_addr_hi = addrhi;
+ last_devad_lo = devadlo;
+ last_devad_hi = devadhi;
+ last_reg_lo = reglo;
+ last_reg_hi = reghi;
+ last_data = data;
+
+ return 0;
+}
+
+/***************************************************/
+
+U_BOOT_CMD(
+ mdio, 6, 1, do_mdio,
+ "MDIO utility commands",
+ "list - List MDIO buses\n"
+ "mdio read <phydev> [<devad>.]<reg> - "
+ "read PHY's register at <devad>.<reg>\n"
+ "mdio write <phydev> [<devad>.]<reg> <data> - "
+ "write PHY's register at <devad>.<reg>\n"
+ "mdio rx <phydev> [<devad>.]<reg> - "
+ "read PHY's extended register at <devad>.<reg>\n"
+ "mdio wx <phydev> [<devad>.]<reg> <data> - "
+ "write PHY's extended register at <devad>.<reg>\n"
+ "<phydev> may be:\n"
+ " <busname> <addr>\n"
+ " <addr>\n"
+ " <eth name>\n"
+ "<addr> <devad>, and <reg> may be ranges, e.g. 1-5.4-0x1f.\n"
+);
diff --git a/roms/u-boot/cmd/mem.c b/roms/u-boot/cmd/mem.c
new file mode 100644
index 000000000..1eb83b757
--- /dev/null
+++ b/roms/u-boot/cmd/mem.c
@@ -0,0 +1,1456 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Memory Functions
+ *
+ * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
+ */
+
+#include <common.h>
+#include <console.h>
+#include <bootretry.h>
+#include <cli.h>
+#include <command.h>
+#include <console.h>
+#include <flash.h>
+#include <hash.h>
+#include <log.h>
+#include <mapmem.h>
+#include <rand.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Create a compile-time value */
+#ifdef MEM_SUPPORT_64BIT_DATA
+#define SUPPORT_64BIT_DATA 1
+#define HELP_Q ", .q"
+#else
+#define SUPPORT_64BIT_DATA 0
+#define HELP_Q ""
+#endif
+
+static int mod_mem(struct cmd_tbl *, int, int, int, char * const []);
+
+/* Display values from last command.
+ * Memory modify remembered values are different from display memory.
+ */
+static ulong dp_last_addr, dp_last_size;
+static ulong dp_last_length = 0x40;
+static ulong mm_last_addr, mm_last_size;
+
+static ulong base_address = 0;
+#ifdef CONFIG_CMD_MEM_SEARCH
+static ulong dp_last_ms_length;
+static u8 search_buf[64];
+static uint search_len;
+#endif
+
+/* Memory Display
+ *
+ * Syntax:
+ * md{.b, .w, .l, .q} {addr} {len}
+ */
+#define DISP_LINE_LEN 16
+static int do_mem_md(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr, length, bytes;
+ const void *buf;
+ int size;
+ int rc = 0;
+
+ /* We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ addr = dp_last_addr;
+ size = dp_last_size;
+ length = dp_last_length;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /* New command specified. Check for a size specification.
+ * Defaults to long if no or incorrect specification.
+ */
+ if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+ return 1;
+
+ /* Address is specified since argc > 1
+ */
+ addr = simple_strtoul(argv[1], NULL, 16);
+ addr += base_address;
+
+ /* If another parameter, it is the length to display.
+ * Length is the number of objects, not number of bytes.
+ */
+ if (argc > 2)
+ length = simple_strtoul(argv[2], NULL, 16);
+ }
+
+ bytes = size * length;
+ buf = map_sysmem(addr, bytes);
+
+ /* Print the lines. */
+ print_buffer(addr, buf, size, length, DISP_LINE_LEN / size);
+ addr += bytes;
+ unmap_sysmem(buf);
+
+ dp_last_addr = addr;
+ dp_last_length = length;
+ dp_last_size = size;
+ return (rc);
+}
+
+static int do_mem_mm(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return mod_mem (cmdtp, 1, flag, argc, argv);
+}
+
+static int do_mem_nm(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return mod_mem (cmdtp, 0, flag, argc, argv);
+}
+
+static int do_mem_mw(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong writeval; /* 64-bit if SUPPORT_64BIT_DATA */
+ ulong addr, count;
+ int size;
+ void *buf, *start;
+ ulong bytes;
+
+ if ((argc < 3) || (argc > 4))
+ return CMD_RET_USAGE;
+
+ /* Check for size specification.
+ */
+ if ((size = cmd_get_data_size(argv[0], 4)) < 1)
+ return 1;
+
+ /* Address is specified since argc > 1
+ */
+ addr = simple_strtoul(argv[1], NULL, 16);
+ addr += base_address;
+
+ /* Get the value to write.
+ */
+ if (SUPPORT_64BIT_DATA)
+ writeval = simple_strtoull(argv[2], NULL, 16);
+ else
+ writeval = simple_strtoul(argv[2], NULL, 16);
+
+ /* Count ? */
+ if (argc == 4) {
+ count = simple_strtoul(argv[3], NULL, 16);
+ } else {
+ count = 1;
+ }
+
+ bytes = size * count;
+ start = map_sysmem(addr, bytes);
+ buf = start;
+ while (count-- > 0) {
+ if (size == 4)
+ *((u32 *)buf) = (u32)writeval;
+ else if (SUPPORT_64BIT_DATA && size == 8)
+ *((ulong *)buf) = writeval;
+ else if (size == 2)
+ *((u16 *)buf) = (u16)writeval;
+ else
+ *((u8 *)buf) = (u8)writeval;
+ buf += size;
+ }
+ unmap_sysmem(start);
+ return 0;
+}
+
+#ifdef CONFIG_CMD_MX_CYCLIC
+static int do_mem_mdc(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int i;
+ ulong count;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ count = simple_strtoul(argv[3], NULL, 10);
+
+ for (;;) {
+ do_mem_md (NULL, 0, 3, argv);
+
+ /* delay for <count> ms... */
+ for (i=0; i<count; i++)
+ udelay(1000);
+
+ /* check for ctrl-c to abort... */
+ if (ctrlc()) {
+ puts("Abort\n");
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int do_mem_mwc(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int i;
+ ulong count;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ count = simple_strtoul(argv[3], NULL, 10);
+
+ for (;;) {
+ do_mem_mw (NULL, 0, 3, argv);
+
+ /* delay for <count> ms... */
+ for (i=0; i<count; i++)
+ udelay(1000);
+
+ /* check for ctrl-c to abort... */
+ if (ctrlc()) {
+ puts("Abort\n");
+ return 0;
+ }
+ }
+
+ return 0;
+}
+#endif /* CONFIG_CMD_MX_CYCLIC */
+
+static int do_mem_cmp(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr1, addr2, count, ngood, bytes;
+ int size;
+ int rcode = 0;
+ const char *type;
+ const void *buf1, *buf2, *base;
+ ulong word1, word2; /* 64-bit if SUPPORT_64BIT_DATA */
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ /* Check for size specification.
+ */
+ if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+ return 1;
+ type = size == 8 ? "double word" :
+ size == 4 ? "word" :
+ size == 2 ? "halfword" : "byte";
+
+ addr1 = simple_strtoul(argv[1], NULL, 16);
+ addr1 += base_address;
+
+ addr2 = simple_strtoul(argv[2], NULL, 16);
+ addr2 += base_address;
+
+ count = simple_strtoul(argv[3], NULL, 16);
+
+ bytes = size * count;
+ base = buf1 = map_sysmem(addr1, bytes);
+ buf2 = map_sysmem(addr2, bytes);
+ for (ngood = 0; ngood < count; ++ngood) {
+ if (size == 4) {
+ word1 = *(u32 *)buf1;
+ word2 = *(u32 *)buf2;
+ } else if (SUPPORT_64BIT_DATA && size == 8) {
+ word1 = *(ulong *)buf1;
+ word2 = *(ulong *)buf2;
+ } else if (size == 2) {
+ word1 = *(u16 *)buf1;
+ word2 = *(u16 *)buf2;
+ } else {
+ word1 = *(u8 *)buf1;
+ word2 = *(u8 *)buf2;
+ }
+ if (word1 != word2) {
+ ulong offset = buf1 - base;
+ printf("%s at 0x%08lx (%#0*lx) != %s at 0x%08lx (%#0*lx)\n",
+ type, (ulong)(addr1 + offset), size, word1,
+ type, (ulong)(addr2 + offset), size, word2);
+ rcode = 1;
+ break;
+ }
+
+ buf1 += size;
+ buf2 += size;
+
+ /* reset watchdog from time to time */
+ if ((ngood % (64 << 10)) == 0)
+ WATCHDOG_RESET();
+ }
+ unmap_sysmem(buf1);
+ unmap_sysmem(buf2);
+
+ printf("Total of %ld %s(s) were the same\n", ngood, type);
+ return rcode;
+}
+
+static int do_mem_cp(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr, dest, count;
+ void *src, *dst;
+ int size;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ /* Check for size specification.
+ */
+ if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+ return 1;
+
+ addr = simple_strtoul(argv[1], NULL, 16);
+ addr += base_address;
+
+ dest = simple_strtoul(argv[2], NULL, 16);
+ dest += base_address;
+
+ count = simple_strtoul(argv[3], NULL, 16);
+
+ if (count == 0) {
+ puts ("Zero length ???\n");
+ return 1;
+ }
+
+ src = map_sysmem(addr, count * size);
+ dst = map_sysmem(dest, count * size);
+
+#ifdef CONFIG_MTD_NOR_FLASH
+ /* check if we are copying to Flash */
+ if (addr2info((ulong)dst)) {
+ int rc;
+
+ puts ("Copy to Flash... ");
+
+ rc = flash_write((char *)src, (ulong)dst, count * size);
+ if (rc != 0) {
+ flash_perror(rc);
+ unmap_sysmem(src);
+ unmap_sysmem(dst);
+ return (1);
+ }
+ puts ("done\n");
+ unmap_sysmem(src);
+ unmap_sysmem(dst);
+ return 0;
+ }
+#endif
+
+ memcpy(dst, src, count * size);
+
+ unmap_sysmem(src);
+ unmap_sysmem(dst);
+ return 0;
+}
+
+#ifdef CONFIG_CMD_MEM_SEARCH
+static int do_mem_search(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr, length, bytes, offset;
+ u8 *ptr, *end, *buf;
+ bool quiet = false;
+ ulong last_pos; /* Offset of last match in 'size' units*/
+ ulong last_addr; /* Address of last displayed line */
+ int limit = 10;
+ int used_len;
+ int count;
+ int size;
+ int i;
+
+ /* We use the last specified parameters, unless new ones are entered */
+ addr = dp_last_addr;
+ size = dp_last_size;
+ length = dp_last_ms_length;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if (!(flag & CMD_FLAG_REPEAT)) {
+ /*
+ * Check for a size specification.
+ * Defaults to long if no or incorrect specification.
+ */
+ size = cmd_get_data_size(argv[0], 4);
+ if (size < 0 && size != CMD_DATA_SIZE_STR)
+ return 1;
+
+ argc--;
+ argv++;
+ while (argc && *argv[0] == '-') {
+ int ch = argv[0][1];
+
+ if (ch == 'q')
+ quiet = true;
+ else if (ch == 'l' && isxdigit(argv[0][2]))
+ limit = simple_strtoul(argv[0] + 2, NULL, 16);
+ else
+ return CMD_RET_USAGE;
+ argc--;
+ argv++;
+ }
+
+ /* Address is specified since argc > 1 */
+ addr = simple_strtoul(argv[0], NULL, 16);
+ addr += base_address;
+
+ /* Length is the number of objects, not number of bytes */
+ length = simple_strtoul(argv[1], NULL, 16);
+
+ /* Read the bytes to search for */
+ end = search_buf + sizeof(search_buf);
+ for (i = 2, ptr = search_buf; i < argc && ptr < end; i++) {
+ if (MEM_SUPPORT_64BIT_DATA && size == 8) {
+ u64 val = simple_strtoull(argv[i], NULL, 16);
+
+ *(u64 *)ptr = val;
+ } else if (size == -2) { /* string */
+ int len = min(strlen(argv[i]),
+ (size_t)(end - ptr));
+
+ memcpy(ptr, argv[i], len);
+ ptr += len;
+ continue;
+ } else {
+ u32 val = simple_strtoul(argv[i], NULL, 16);
+
+ switch (size) {
+ case 1:
+ *ptr = val;
+ break;
+ case 2:
+ *(u16 *)ptr = val;
+ break;
+ case 4:
+ *(u32 *)ptr = val;
+ break;
+ }
+ }
+ ptr += size;
+ }
+ search_len = ptr - search_buf;
+ }
+
+ /* Do the search */
+ if (size == -2)
+ size = 1;
+ bytes = size * length;
+ buf = map_sysmem(addr, bytes);
+ last_pos = 0;
+ last_addr = 0;
+ count = 0;
+ for (offset = 0;
+ offset < bytes && offset <= bytes - search_len && count < limit;
+ offset += size) {
+ void *ptr = buf + offset;
+
+ if (!memcmp(ptr, search_buf, search_len)) {
+ uint align = (addr + offset) & 0xf;
+ ulong match = addr + offset;
+
+ if (!count || (last_addr & ~0xf) != (match & ~0xf)) {
+ if (!quiet) {
+ if (count)
+ printf("--\n");
+ print_buffer(match - align, ptr - align,
+ size,
+ ALIGN(search_len + align,
+ 16) / size, 0);
+ }
+ last_addr = match;
+ last_pos = offset / size;
+ }
+ count++;
+ }
+ }
+ if (!quiet) {
+ printf("%d match%s", count, count == 1 ? "" : "es");
+ if (count == limit)
+ printf(" (repeat command to check for more)");
+ printf("\n");
+ }
+ env_set_hex("memmatches", count);
+ env_set_hex("memaddr", last_addr);
+ env_set_hex("mempos", last_pos);
+
+ unmap_sysmem(buf);
+
+ used_len = offset / size;
+ dp_last_addr = addr + used_len;
+ dp_last_size = size;
+ dp_last_ms_length = length < used_len ? 0 : length - used_len;
+
+ return count ? 0 : CMD_RET_FAILURE;
+}
+#endif
+
+static int do_mem_base(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc > 1) {
+ /* Set new base address.
+ */
+ base_address = simple_strtoul(argv[1], NULL, 16);
+ }
+ /* Print the current base address.
+ */
+ printf("Base Address: 0x%08lx\n", base_address);
+ return 0;
+}
+
+static int do_mem_loop(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr, length, i, bytes;
+ int size;
+ volatile ulong *llp; /* 64-bit if SUPPORT_64BIT_DATA */
+ volatile u32 *longp;
+ volatile u16 *shortp;
+ volatile u8 *cp;
+ const void *buf;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ /*
+ * Check for a size specification.
+ * Defaults to long if no or incorrect specification.
+ */
+ if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+ return 1;
+
+ /* Address is always specified.
+ */
+ addr = simple_strtoul(argv[1], NULL, 16);
+
+ /* Length is the number of objects, not number of bytes.
+ */
+ length = simple_strtoul(argv[2], NULL, 16);
+
+ bytes = size * length;
+ buf = map_sysmem(addr, bytes);
+
+ /* We want to optimize the loops to run as fast as possible.
+ * If we have only one object, just run infinite loops.
+ */
+ if (length == 1) {
+ if (SUPPORT_64BIT_DATA && size == 8) {
+ llp = (ulong *)buf;
+ for (;;)
+ i = *llp;
+ }
+ if (size == 4) {
+ longp = (u32 *)buf;
+ for (;;)
+ i = *longp;
+ }
+ if (size == 2) {
+ shortp = (u16 *)buf;
+ for (;;)
+ i = *shortp;
+ }
+ cp = (u8 *)buf;
+ for (;;)
+ i = *cp;
+ }
+
+ if (SUPPORT_64BIT_DATA && size == 8) {
+ for (;;) {
+ llp = (ulong *)buf;
+ i = length;
+ while (i-- > 0)
+ *llp++;
+ }
+ }
+ if (size == 4) {
+ for (;;) {
+ longp = (u32 *)buf;
+ i = length;
+ while (i-- > 0)
+ *longp++;
+ }
+ }
+ if (size == 2) {
+ for (;;) {
+ shortp = (u16 *)buf;
+ i = length;
+ while (i-- > 0)
+ *shortp++;
+ }
+ }
+ for (;;) {
+ cp = (u8 *)buf;
+ i = length;
+ while (i-- > 0)
+ *cp++;
+ }
+ unmap_sysmem(buf);
+
+ return 0;
+}
+
+#ifdef CONFIG_LOOPW
+static int do_mem_loopw(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr, length, i, bytes;
+ int size;
+ volatile ulong *llp; /* 64-bit if SUPPORT_64BIT_DATA */
+ ulong data; /* 64-bit if SUPPORT_64BIT_DATA */
+ volatile u32 *longp;
+ volatile u16 *shortp;
+ volatile u8 *cp;
+ void *buf;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ /*
+ * Check for a size specification.
+ * Defaults to long if no or incorrect specification.
+ */
+ if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+ return 1;
+
+ /* Address is always specified.
+ */
+ addr = simple_strtoul(argv[1], NULL, 16);
+
+ /* Length is the number of objects, not number of bytes.
+ */
+ length = simple_strtoul(argv[2], NULL, 16);
+
+ /* data to write */
+ if (SUPPORT_64BIT_DATA)
+ data = simple_strtoull(argv[3], NULL, 16);
+ else
+ data = simple_strtoul(argv[3], NULL, 16);
+
+ bytes = size * length;
+ buf = map_sysmem(addr, bytes);
+
+ /* We want to optimize the loops to run as fast as possible.
+ * If we have only one object, just run infinite loops.
+ */
+ if (length == 1) {
+ if (SUPPORT_64BIT_DATA && size == 8) {
+ llp = (ulong *)buf;
+ for (;;)
+ *llp = data;
+ }
+ if (size == 4) {
+ longp = (u32 *)buf;
+ for (;;)
+ *longp = data;
+ }
+ if (size == 2) {
+ shortp = (u16 *)buf;
+ for (;;)
+ *shortp = data;
+ }
+ cp = (u8 *)buf;
+ for (;;)
+ *cp = data;
+ }
+
+ if (SUPPORT_64BIT_DATA && size == 8) {
+ for (;;) {
+ llp = (ulong *)buf;
+ i = length;
+ while (i-- > 0)
+ *llp++ = data;
+ }
+ }
+ if (size == 4) {
+ for (;;) {
+ longp = (u32 *)buf;
+ i = length;
+ while (i-- > 0)
+ *longp++ = data;
+ }
+ }
+ if (size == 2) {
+ for (;;) {
+ shortp = (u16 *)buf;
+ i = length;
+ while (i-- > 0)
+ *shortp++ = data;
+ }
+ }
+ for (;;) {
+ cp = (u8 *)buf;
+ i = length;
+ while (i-- > 0)
+ *cp++ = data;
+ }
+}
+#endif /* CONFIG_LOOPW */
+
+#ifdef CONFIG_CMD_MEMTEST
+static ulong mem_test_alt(vu_long *buf, ulong start_addr, ulong end_addr,
+ vu_long *dummy)
+{
+ vu_long *addr;
+ ulong errs = 0;
+ ulong val, readback;
+ int j;
+ vu_long offset;
+ vu_long test_offset;
+ vu_long pattern;
+ vu_long temp;
+ vu_long anti_pattern;
+ vu_long num_words;
+ static const ulong bitpattern[] = {
+ 0x00000001, /* single bit */
+ 0x00000003, /* two adjacent bits */
+ 0x00000007, /* three adjacent bits */
+ 0x0000000F, /* four adjacent bits */
+ 0x00000005, /* two non-adjacent bits */
+ 0x00000015, /* three non-adjacent bits */
+ 0x00000055, /* four non-adjacent bits */
+ 0xaaaaaaaa, /* alternating 1/0 */
+ };
+
+ num_words = (end_addr - start_addr) / sizeof(vu_long);
+
+ /*
+ * Data line test: write a pattern to the first
+ * location, write the 1's complement to a 'parking'
+ * address (changes the state of the data bus so a
+ * floating bus doesn't give a false OK), and then
+ * read the value back. Note that we read it back
+ * into a variable because the next time we read it,
+ * it might be right (been there, tough to explain to
+ * the quality guys why it prints a failure when the
+ * "is" and "should be" are obviously the same in the
+ * error message).
+ *
+ * Rather than exhaustively testing, we test some
+ * patterns by shifting '1' bits through a field of
+ * '0's and '0' bits through a field of '1's (i.e.
+ * pattern and ~pattern).
+ */
+ addr = buf;
+ for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
+ val = bitpattern[j];
+ for (; val != 0; val <<= 1) {
+ *addr = val;
+ *dummy = ~val; /* clear the test data off the bus */
+ readback = *addr;
+ if (readback != val) {
+ printf("FAILURE (data line): "
+ "expected %08lx, actual %08lx\n",
+ val, readback);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ *addr = ~val;
+ *dummy = val;
+ readback = *addr;
+ if (readback != ~val) {
+ printf("FAILURE (data line): "
+ "Is %08lx, should be %08lx\n",
+ readback, ~val);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ }
+ }
+
+ /*
+ * Based on code whose Original Author and Copyright
+ * information follows: Copyright (c) 1998 by Michael
+ * Barr. This software is placed into the public
+ * domain and may be used for any purpose. However,
+ * this notice must not be changed or removed and no
+ * warranty is either expressed or implied by its
+ * publication or distribution.
+ */
+
+ /*
+ * Address line test
+
+ * Description: Test the address bus wiring in a
+ * memory region by performing a walking
+ * 1's test on the relevant bits of the
+ * address and checking for aliasing.
+ * This test will find single-bit
+ * address failures such as stuck-high,
+ * stuck-low, and shorted pins. The base
+ * address and size of the region are
+ * selected by the caller.
+
+ * Notes: For best results, the selected base
+ * address should have enough LSB 0's to
+ * guarantee single address bit changes.
+ * For example, to test a 64-Kbyte
+ * region, select a base address on a
+ * 64-Kbyte boundary. Also, select the
+ * region size as a power-of-two if at
+ * all possible.
+ *
+ * Returns: 0 if the test succeeds, 1 if the test fails.
+ */
+ pattern = (vu_long) 0xaaaaaaaa;
+ anti_pattern = (vu_long) 0x55555555;
+
+ debug("%s:%d: length = 0x%.8lx\n", __func__, __LINE__, num_words);
+ /*
+ * Write the default pattern at each of the
+ * power-of-two offsets.
+ */
+ for (offset = 1; offset < num_words; offset <<= 1)
+ addr[offset] = pattern;
+
+ /*
+ * Check for address bits stuck high.
+ */
+ test_offset = 0;
+ addr[test_offset] = anti_pattern;
+
+ for (offset = 1; offset < num_words; offset <<= 1) {
+ temp = addr[offset];
+ if (temp != pattern) {
+ printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
+ " expected 0x%.8lx, actual 0x%.8lx\n",
+ start_addr + offset*sizeof(vu_long),
+ pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ }
+ addr[test_offset] = pattern;
+ WATCHDOG_RESET();
+
+ /*
+ * Check for addr bits stuck low or shorted.
+ */
+ for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
+ addr[test_offset] = anti_pattern;
+
+ for (offset = 1; offset < num_words; offset <<= 1) {
+ temp = addr[offset];
+ if ((temp != pattern) && (offset != test_offset)) {
+ printf("\nFAILURE: Address bit stuck low or"
+ " shorted @ 0x%.8lx: expected 0x%.8lx,"
+ " actual 0x%.8lx\n",
+ start_addr + offset*sizeof(vu_long),
+ pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ }
+ addr[test_offset] = pattern;
+ }
+
+ /*
+ * Description: Test the integrity of a physical
+ * memory device by performing an
+ * increment/decrement test over the
+ * entire region. In the process every
+ * storage bit in the device is tested
+ * as a zero and a one. The base address
+ * and the size of the region are
+ * selected by the caller.
+ *
+ * Returns: 0 if the test succeeds, 1 if the test fails.
+ */
+ num_words++;
+
+ /*
+ * Fill memory with a known pattern.
+ */
+ for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+ WATCHDOG_RESET();
+ addr[offset] = pattern;
+ }
+
+ /*
+ * Check each location and invert it for the second pass.
+ */
+ for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+ WATCHDOG_RESET();
+ temp = addr[offset];
+ if (temp != pattern) {
+ printf("\nFAILURE (read/write) @ 0x%.8lx:"
+ " expected 0x%.8lx, actual 0x%.8lx)\n",
+ start_addr + offset*sizeof(vu_long),
+ pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+
+ anti_pattern = ~pattern;
+ addr[offset] = anti_pattern;
+ }
+
+ /*
+ * Check each location for the inverted pattern and zero it.
+ */
+ for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
+ WATCHDOG_RESET();
+ anti_pattern = ~pattern;
+ temp = addr[offset];
+ if (temp != anti_pattern) {
+ printf("\nFAILURE (read/write): @ 0x%.8lx:"
+ " expected 0x%.8lx, actual 0x%.8lx)\n",
+ start_addr + offset*sizeof(vu_long),
+ anti_pattern, temp);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ addr[offset] = 0;
+ }
+
+ return errs;
+}
+
+static int compare_regions(volatile unsigned long *bufa,
+ volatile unsigned long *bufb, size_t count)
+{
+ volatile unsigned long *p1 = bufa;
+ volatile unsigned long *p2 = bufb;
+ int errs = 0;
+ size_t i;
+
+ for (i = 0; i < count; i++, p1++, p2++) {
+ if (*p1 != *p2) {
+ printf("FAILURE: 0x%08lx != 0x%08lx (delta=0x%08lx -> bit %ld) at offset 0x%08lx\n",
+ (unsigned long)*p1, (unsigned long)*p2,
+ *p1 ^ *p2, __ffs(*p1 ^ *p2),
+ (unsigned long)(i * sizeof(unsigned long)));
+ errs++;
+ }
+ }
+
+ return errs;
+}
+
+static ulong test_bitflip_comparison(volatile unsigned long *bufa,
+ volatile unsigned long *bufb, size_t count)
+{
+ volatile unsigned long *p1 = bufa;
+ volatile unsigned long *p2 = bufb;
+ unsigned int j, k;
+ unsigned long q;
+ size_t i;
+ int max;
+ int errs = 0;
+
+ max = sizeof(unsigned long) * 8;
+ for (k = 0; k < max; k++) {
+ q = 0x00000001L << k;
+ for (j = 0; j < 8; j++) {
+ WATCHDOG_RESET();
+ q = ~q;
+ p1 = (volatile unsigned long *)bufa;
+ p2 = (volatile unsigned long *)bufb;
+ for (i = 0; i < count; i++)
+ *p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
+
+ errs += compare_regions(bufa, bufb, count);
+ }
+
+ if (ctrlc())
+ return -1UL;
+ }
+
+ return errs;
+}
+
+static ulong mem_test_bitflip(vu_long *buf, ulong start, ulong end)
+{
+ /*
+ * Split the specified range into two halves.
+ * Note that mtest range is inclusive of start,end.
+ * Bitflip test instead uses a count (of 32-bit words).
+ */
+ ulong half_size = (end - start + 1) / 2 / sizeof(unsigned long);
+
+ return test_bitflip_comparison(buf, buf + half_size, half_size);
+}
+
+static ulong mem_test_quick(vu_long *buf, ulong start_addr, ulong end_addr,
+ vu_long pattern, int iteration)
+{
+ vu_long *end;
+ vu_long *addr;
+ ulong errs = 0;
+ ulong incr, length;
+ ulong val, readback;
+
+ /* Alternate the pattern */
+ incr = 1;
+ if (iteration & 1) {
+ incr = -incr;
+ /*
+ * Flip the pattern each time to make lots of zeros and
+ * then, the next time, lots of ones. We decrement
+ * the "negative" patterns and increment the "positive"
+ * patterns to preserve this feature.
+ */
+ if (pattern & 0x80000000)
+ pattern = -pattern; /* complement & increment */
+ else
+ pattern = ~pattern;
+ }
+ length = (end_addr - start_addr) / sizeof(ulong);
+ end = buf + length;
+ printf("\rPattern %08lX Writing..."
+ "%12s"
+ "\b\b\b\b\b\b\b\b\b\b",
+ pattern, "");
+
+ for (addr = buf, val = pattern; addr < end; addr++) {
+ WATCHDOG_RESET();
+ *addr = val;
+ val += incr;
+ }
+
+ puts("Reading...");
+
+ for (addr = buf, val = pattern; addr < end; addr++) {
+ WATCHDOG_RESET();
+ readback = *addr;
+ if (readback != val) {
+ ulong offset = addr - buf;
+
+ printf("\nMem error @ 0x%08X: "
+ "found %08lX, expected %08lX\n",
+ (uint)(uintptr_t)(start_addr + offset*sizeof(vu_long)),
+ readback, val);
+ errs++;
+ if (ctrlc())
+ return -1;
+ }
+ val += incr;
+ }
+
+ return errs;
+}
+
+/*
+ * Perform a memory test. A more complete alternative test can be
+ * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
+ * interrupted by ctrl-c or by a failure of one of the sub-tests.
+ */
+static int do_mem_mtest(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong start, end;
+ vu_long scratch_space;
+ vu_long *buf, *dummy = &scratch_space;
+ ulong iteration_limit = 0;
+ ulong count = 0;
+ ulong errs = 0; /* number of errors, or -1 if interrupted */
+ ulong pattern = 0;
+ int iteration;
+
+ start = CONFIG_SYS_MEMTEST_START;
+ end = CONFIG_SYS_MEMTEST_END;
+
+ if (argc > 1)
+ if (strict_strtoul(argv[1], 16, &start) < 0)
+ return CMD_RET_USAGE;
+
+ if (argc > 2)
+ if (strict_strtoul(argv[2], 16, &end) < 0)
+ return CMD_RET_USAGE;
+
+ if (argc > 3)
+ if (strict_strtoul(argv[3], 16, &pattern) < 0)
+ return CMD_RET_USAGE;
+
+ if (argc > 4)
+ if (strict_strtoul(argv[4], 16, &iteration_limit) < 0)
+ return CMD_RET_USAGE;
+
+ if (end < start) {
+ printf("Refusing to do empty test\n");
+ return -1;
+ }
+
+ printf("Testing %08lx ... %08lx:\n", start, end);
+ debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__,
+ start, end);
+
+ buf = map_sysmem(start, end - start);
+ for (iteration = 0;
+ !iteration_limit || iteration < iteration_limit;
+ iteration++) {
+ if (ctrlc()) {
+ errs = -1UL;
+ break;
+ }
+
+ printf("Iteration: %6d\r", iteration + 1);
+ debug("\n");
+ if (IS_ENABLED(CONFIG_SYS_ALT_MEMTEST)) {
+ errs = mem_test_alt(buf, start, end, dummy);
+ if (errs == -1UL)
+ break;
+ if (IS_ENABLED(CONFIG_SYS_ALT_MEMTEST_BITFLIP)) {
+ count += errs;
+ errs = mem_test_bitflip(buf, start, end);
+ }
+ } else {
+ errs = mem_test_quick(buf, start, end, pattern,
+ iteration);
+ }
+ if (errs == -1UL)
+ break;
+ count += errs;
+ }
+
+ unmap_sysmem((void *)buf);
+
+ if (errs == -1UL) {
+ /* Memory test was aborted - write a newline to finish off */
+ putc('\n');
+ }
+ printf("Tested %d iteration(s) with %lu errors.\n", iteration, count);
+
+ return errs != 0;
+}
+#endif /* CONFIG_CMD_MEMTEST */
+
+/* Modify memory.
+ *
+ * Syntax:
+ * mm{.b, .w, .l, .q} {addr}
+ */
+static int
+mod_mem(struct cmd_tbl *cmdtp, int incrflag, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr;
+ ulong i; /* 64-bit if SUPPORT_64BIT_DATA */
+ int nbytes, size;
+ void *ptr = NULL;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ bootretry_reset_cmd_timeout(); /* got a good command to get here */
+ /* We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ addr = mm_last_addr;
+ size = mm_last_size;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ /* New command specified. Check for a size specification.
+ * Defaults to long if no or incorrect specification.
+ */
+ if ((size = cmd_get_data_size(argv[0], 4)) < 0)
+ return 1;
+
+ /* Address is specified since argc > 1
+ */
+ addr = simple_strtoul(argv[1], NULL, 16);
+ addr += base_address;
+ }
+
+ /* Print the address, followed by value. Then accept input for
+ * the next value. A non-converted value exits.
+ */
+ do {
+ ptr = map_sysmem(addr, size);
+ printf("%08lx:", addr);
+ if (size == 4)
+ printf(" %08x", *((u32 *)ptr));
+ else if (SUPPORT_64BIT_DATA && size == 8)
+ printf(" %0lx", *((ulong *)ptr));
+ else if (size == 2)
+ printf(" %04x", *((u16 *)ptr));
+ else
+ printf(" %02x", *((u8 *)ptr));
+
+ nbytes = cli_readline(" ? ");
+ if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
+ /* <CR> pressed as only input, don't modify current
+ * location and move to next. "-" pressed will go back.
+ */
+ if (incrflag)
+ addr += nbytes ? -size : size;
+ nbytes = 1;
+ /* good enough to not time out */
+ bootretry_reset_cmd_timeout();
+ }
+#ifdef CONFIG_BOOT_RETRY_TIME
+ else if (nbytes == -2) {
+ break; /* timed out, exit the command */
+ }
+#endif
+ else {
+ char *endp;
+ if (SUPPORT_64BIT_DATA)
+ i = simple_strtoull(console_buffer, &endp, 16);
+ else
+ i = simple_strtoul(console_buffer, &endp, 16);
+ nbytes = endp - console_buffer;
+ if (nbytes) {
+ /* good enough to not time out
+ */
+ bootretry_reset_cmd_timeout();
+ if (size == 4)
+ *((u32 *)ptr) = i;
+ else if (SUPPORT_64BIT_DATA && size == 8)
+ *((ulong *)ptr) = i;
+ else if (size == 2)
+ *((u16 *)ptr) = i;
+ else
+ *((u8 *)ptr) = i;
+ if (incrflag)
+ addr += size;
+ }
+ }
+ } while (nbytes);
+ if (ptr)
+ unmap_sysmem(ptr);
+
+ mm_last_addr = addr;
+ mm_last_size = size;
+ return 0;
+}
+
+#ifdef CONFIG_CMD_CRC32
+
+static int do_mem_crc(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int flags = 0;
+ int ac;
+ char * const *av;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ av = argv + 1;
+ ac = argc - 1;
+#ifdef CONFIG_CRC32_VERIFY
+ if (strcmp(*av, "-v") == 0) {
+ flags |= HASH_FLAG_VERIFY | HASH_FLAG_ENV;
+ av++;
+ ac--;
+ }
+#endif
+
+ return hash_command("crc32", flags, cmdtp, flag, ac, av);
+}
+
+#endif
+
+#ifdef CONFIG_CMD_RANDOM
+static int do_random(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long addr, len;
+ unsigned long seed; // NOT INITIALIZED ON PURPOSE
+ unsigned int *buf, *start;
+ unsigned char *buf8;
+ unsigned int i;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ len = simple_strtoul(argv[2], NULL, 16);
+ addr = simple_strtoul(argv[1], NULL, 16);
+
+ if (argc == 4) {
+ seed = simple_strtoul(argv[3], NULL, 16);
+ if (seed == 0) {
+ printf("The seed cannot be 0. Using 0xDEADBEEF.\n");
+ seed = 0xDEADBEEF;
+ }
+ } else {
+ seed = get_timer(0) ^ rand();
+ }
+
+ srand(seed);
+ start = map_sysmem(addr, len);
+ buf = start;
+ for (i = 0; i < (len / 4); i++)
+ *buf++ = rand();
+
+ buf8 = (unsigned char *)buf;
+ for (i = 0; i < (len % 4); i++)
+ *buf8++ = rand() & 0xFF;
+
+ unmap_sysmem(start);
+ printf("%lu bytes filled with random data\n", len);
+
+ return CMD_RET_SUCCESS;
+}
+#endif
+
+/**************************************************/
+U_BOOT_CMD(
+ md, 3, 1, do_mem_md,
+ "memory display",
+ "[.b, .w, .l" HELP_Q "] address [# of objects]"
+);
+
+
+U_BOOT_CMD(
+ mm, 2, 1, do_mem_mm,
+ "memory modify (auto-incrementing address)",
+ "[.b, .w, .l" HELP_Q "] address"
+);
+
+
+U_BOOT_CMD(
+ nm, 2, 1, do_mem_nm,
+ "memory modify (constant address)",
+ "[.b, .w, .l" HELP_Q "] address"
+);
+
+U_BOOT_CMD(
+ mw, 4, 1, do_mem_mw,
+ "memory write (fill)",
+ "[.b, .w, .l" HELP_Q "] address value [count]"
+);
+
+U_BOOT_CMD(
+ cp, 4, 1, do_mem_cp,
+ "memory copy",
+ "[.b, .w, .l" HELP_Q "] source target count"
+);
+
+U_BOOT_CMD(
+ cmp, 4, 1, do_mem_cmp,
+ "memory compare",
+ "[.b, .w, .l" HELP_Q "] addr1 addr2 count"
+);
+
+#ifdef CONFIG_CMD_MEM_SEARCH
+/**************************************************/
+U_BOOT_CMD(
+ ms, 255, 1, do_mem_search,
+ "memory search",
+ "[.b, .w, .l" HELP_Q ", .s] [-q | -<n>] address #-of-objects <value>..."
+ " -q = quiet, -l<val> = match limit"
+);
+#endif
+
+#ifdef CONFIG_CMD_CRC32
+
+#ifndef CONFIG_CRC32_VERIFY
+
+U_BOOT_CMD(
+ crc32, 4, 1, do_mem_crc,
+ "checksum calculation",
+ "address count [addr]\n - compute CRC32 checksum [save at addr]"
+);
+
+#else /* CONFIG_CRC32_VERIFY */
+
+U_BOOT_CMD(
+ crc32, 5, 1, do_mem_crc,
+ "checksum calculation",
+ "address count [addr]\n - compute CRC32 checksum [save at addr]\n"
+ "-v address count crc\n - verify crc of memory area"
+);
+
+#endif /* CONFIG_CRC32_VERIFY */
+
+#endif
+
+#ifdef CONFIG_CMD_MEMINFO
+static int do_mem_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ puts("DRAM: ");
+ print_size(gd->ram_size, "\n");
+
+ return 0;
+}
+#endif
+
+U_BOOT_CMD(
+ base, 2, 1, do_mem_base,
+ "print or set address offset",
+ "\n - print address offset for memory commands\n"
+ "base off\n - set address offset for memory commands to 'off'"
+);
+
+U_BOOT_CMD(
+ loop, 3, 1, do_mem_loop,
+ "infinite loop on address range",
+ "[.b, .w, .l" HELP_Q "] address number_of_objects"
+);
+
+#ifdef CONFIG_LOOPW
+U_BOOT_CMD(
+ loopw, 4, 1, do_mem_loopw,
+ "infinite write loop on address range",
+ "[.b, .w, .l" HELP_Q "] address number_of_objects data_to_write"
+);
+#endif /* CONFIG_LOOPW */
+
+#ifdef CONFIG_CMD_MEMTEST
+U_BOOT_CMD(
+ mtest, 5, 1, do_mem_mtest,
+ "simple RAM read/write test",
+ "[start [end [pattern [iterations]]]]"
+);
+#endif /* CONFIG_CMD_MEMTEST */
+
+#ifdef CONFIG_CMD_MX_CYCLIC
+U_BOOT_CMD(
+ mdc, 4, 1, do_mem_mdc,
+ "memory display cyclic",
+ "[.b, .w, .l" HELP_Q "] address count delay(ms)"
+);
+
+U_BOOT_CMD(
+ mwc, 4, 1, do_mem_mwc,
+ "memory write cyclic",
+ "[.b, .w, .l" HELP_Q "] address value delay(ms)"
+);
+#endif /* CONFIG_CMD_MX_CYCLIC */
+
+#ifdef CONFIG_CMD_MEMINFO
+U_BOOT_CMD(
+ meminfo, 3, 1, do_mem_info,
+ "display memory information",
+ ""
+);
+#endif
+
+#ifdef CONFIG_CMD_RANDOM
+U_BOOT_CMD(
+ random, 4, 0, do_random,
+ "fill memory with random pattern",
+ "<addr> <len> [<seed>]\n"
+ " - Fill 'len' bytes of memory starting at 'addr' with random data\n"
+);
+#endif
diff --git a/roms/u-boot/cmd/mfsl.c b/roms/u-boot/cmd/mfsl.c
new file mode 100644
index 000000000..31f5b36ad
--- /dev/null
+++ b/roms/u-boot/cmd/mfsl.c
@@ -0,0 +1,387 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal SIMEK <monstr@monstr.eu>
+ */
+
+/*
+ * Microblaze FSL support
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <asm/asm.h>
+
+int do_frd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned int fslnum;
+ unsigned int num;
+ unsigned int blocking;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ fslnum = (unsigned int)simple_strtoul (argv[1], NULL, 16);
+ blocking = (unsigned int)simple_strtoul (argv[2], NULL, 16);
+ if (fslnum < 0 || fslnum >= XILINX_FSL_NUMBER) {
+ puts ("Bad number of FSL\n");
+ return CMD_RET_USAGE;
+ }
+
+ switch (fslnum) {
+#if (XILINX_FSL_NUMBER > 0)
+ case 0:
+ switch (blocking) {
+ case 0: NGET (num, 0);
+ break;
+ case 1: NCGET (num, 0);
+ break;
+ case 2: GET (num, 0);
+ break;
+ case 3: CGET (num, 0);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 1)
+ case 1:
+ switch (blocking) {
+ case 0: NGET (num, 1);
+ break;
+ case 1: NCGET (num, 1);
+ break;
+ case 2: GET (num, 1);
+ break;
+ case 3: CGET (num, 1);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 2)
+ case 2:
+ switch (blocking) {
+ case 0: NGET (num, 2);
+ break;
+ case 1: NCGET (num, 2);
+ break;
+ case 2: GET (num, 2);
+ break;
+ case 3: CGET (num, 2);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 3)
+ case 3:
+ switch (blocking) {
+ case 0: NGET (num, 3);
+ break;
+ case 1: NCGET (num, 3);
+ break;
+ case 2: GET (num, 3);
+ break;
+ case 3: CGET (num, 3);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 4)
+ case 4:
+ switch (blocking) {
+ case 0: NGET (num, 4);
+ break;
+ case 1: NCGET (num, 4);
+ break;
+ case 2: GET (num, 4);
+ break;
+ case 3: CGET (num, 4);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 5)
+ case 5:
+ switch (blocking) {
+ case 0: NGET (num, 5);
+ break;
+ case 1: NCGET (num, 5);
+ break;
+ case 2: GET (num, 5);
+ break;
+ case 3: CGET (num, 5);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 6)
+ case 6:
+ switch (blocking) {
+ case 0: NGET (num, 6);
+ break;
+ case 1: NCGET (num, 6);
+ break;
+ case 2: GET (num, 6);
+ break;
+ case 3: CGET (num, 6);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 7)
+ case 7:
+ switch (blocking) {
+ case 0: NGET (num, 7);
+ break;
+ case 1: NCGET (num, 7);
+ break;
+ case 2: GET (num, 7);
+ break;
+ case 3: CGET (num, 7);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+ default:
+ return 1;
+ }
+
+ printf ("%01x: 0x%08x - %s %s read\n", fslnum, num,
+ blocking < 2 ? "non blocking" : "blocking",
+ ((blocking == 1) || (blocking == 3)) ? "control" : "data" );
+ return 0;
+}
+
+int do_fwr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned int fslnum;
+ unsigned int num;
+ unsigned int blocking;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ fslnum = (unsigned int)simple_strtoul (argv[1], NULL, 16);
+ num = (unsigned int)simple_strtoul (argv[2], NULL, 16);
+ blocking = (unsigned int)simple_strtoul (argv[3], NULL, 16);
+ if (fslnum < 0 || fslnum >= XILINX_FSL_NUMBER)
+ return CMD_RET_USAGE;
+
+ switch (fslnum) {
+#if (XILINX_FSL_NUMBER > 0)
+ case 0:
+ switch (blocking) {
+ case 0: NPUT (num, 0);
+ break;
+ case 1: NCPUT (num, 0);
+ break;
+ case 2: PUT (num, 0);
+ break;
+ case 3: CPUT (num, 0);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 1)
+ case 1:
+ switch (blocking) {
+ case 0: NPUT (num, 1);
+ break;
+ case 1: NCPUT (num, 1);
+ break;
+ case 2: PUT (num, 1);
+ break;
+ case 3: CPUT (num, 1);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 2)
+ case 2:
+ switch (blocking) {
+ case 0: NPUT (num, 2);
+ break;
+ case 1: NCPUT (num, 2);
+ break;
+ case 2: PUT (num, 2);
+ break;
+ case 3: CPUT (num, 2);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 3)
+ case 3:
+ switch (blocking) {
+ case 0: NPUT (num, 3);
+ break;
+ case 1: NCPUT (num, 3);
+ break;
+ case 2: PUT (num, 3);
+ break;
+ case 3: CPUT (num, 3);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 4)
+ case 4:
+ switch (blocking) {
+ case 0: NPUT (num, 4);
+ break;
+ case 1: NCPUT (num, 4);
+ break;
+ case 2: PUT (num, 4);
+ break;
+ case 3: CPUT (num, 4);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 5)
+ case 5:
+ switch (blocking) {
+ case 0: NPUT (num, 5);
+ break;
+ case 1: NCPUT (num, 5);
+ break;
+ case 2: PUT (num, 5);
+ break;
+ case 3: CPUT (num, 5);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 6)
+ case 6:
+ switch (blocking) {
+ case 0: NPUT (num, 6);
+ break;
+ case 1: NCPUT (num, 6);
+ break;
+ case 2: PUT (num, 6);
+ break;
+ case 3: CPUT (num, 6);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+#if (XILINX_FSL_NUMBER > 7)
+ case 7:
+ switch (blocking) {
+ case 0: NPUT (num, 7);
+ break;
+ case 1: NCPUT (num, 7);
+ break;
+ case 2: PUT (num, 7);
+ break;
+ case 3: CPUT (num, 7);
+ break;
+ default:
+ return 2;
+ }
+ break;
+#endif
+ default:
+ return 1;
+ }
+
+ printf ("%01x: 0x%08x - %s %s write\n", fslnum, num,
+ blocking < 2 ? "non blocking" : "blocking",
+ ((blocking == 1) || (blocking == 3)) ? "control" : "data" );
+ return 0;
+
+}
+
+int do_rspr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned int reg = 0;
+ unsigned int val = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ reg = (unsigned int)simple_strtoul (argv[1], NULL, 16);
+ val = (unsigned int)simple_strtoul (argv[2], NULL, 16);
+ switch (reg) {
+ case 0x1:
+ if (argc > 2) {
+ MTS (val, rmsr);
+ NOP;
+ MFS (val, rmsr);
+ } else {
+ MFS (val, rmsr);
+ }
+ puts ("MSR");
+ break;
+ case 0x3:
+ MFS (val, rear);
+ puts ("EAR");
+ break;
+ case 0x5:
+ MFS (val, resr);
+ puts ("ESR");
+ break;
+ default:
+ puts ("Unsupported register\n");
+ return 1;
+ }
+ printf (": 0x%08x\n", val);
+ return 0;
+}
+
+/***************************************************/
+
+U_BOOT_CMD (frd, 3, 1, do_frd,
+ "read data from FSL",
+ "- [fslnum [0|1|2|3]]\n"
+ " 0 - non blocking data read\n"
+ " 1 - non blocking control read\n"
+ " 2 - blocking data read\n"
+ " 3 - blocking control read");
+
+U_BOOT_CMD (fwr, 4, 1, do_fwr,
+ "write data to FSL",
+ "- [fslnum [0|1|2|3]]\n"
+ " 0 - non blocking data write\n"
+ " 1 - non blocking control write\n"
+ " 2 - blocking data write\n"
+ " 3 - blocking control write");
+
+U_BOOT_CMD (rspr, 3, 1, do_rspr,
+ "read/write special purpose register",
+ "- reg_num [write value] read/write special purpose register\n"
+ " 1 - MSR - Machine status register\n"
+ " 3 - EAR - Exception address register\n"
+ " 5 - ESR - Exception status register");
diff --git a/roms/u-boot/cmd/mii.c b/roms/u-boot/cmd/mii.c
new file mode 100644
index 000000000..fe8602eb7
--- /dev/null
+++ b/roms/u-boot/cmd/mii.c
@@ -0,0 +1,479 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2001
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ */
+
+/*
+ * MII Utilities
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <miiphy.h>
+
+typedef struct _MII_field_desc_t {
+ ushort hi;
+ ushort lo;
+ ushort mask;
+ const char *name;
+} MII_field_desc_t;
+
+static const MII_field_desc_t reg_0_desc_tbl[] = {
+ { 15, 15, 0x01, "reset" },
+ { 14, 14, 0x01, "loopback" },
+ { 13, 6, 0x81, "speed selection" }, /* special */
+ { 12, 12, 0x01, "A/N enable" },
+ { 11, 11, 0x01, "power-down" },
+ { 10, 10, 0x01, "isolate" },
+ { 9, 9, 0x01, "restart A/N" },
+ { 8, 8, 0x01, "duplex" }, /* special */
+ { 7, 7, 0x01, "collision test enable" },
+ { 5, 0, 0x3f, "(reserved)" }
+};
+
+static const MII_field_desc_t reg_1_desc_tbl[] = {
+ { 15, 15, 0x01, "100BASE-T4 able" },
+ { 14, 14, 0x01, "100BASE-X full duplex able" },
+ { 13, 13, 0x01, "100BASE-X half duplex able" },
+ { 12, 12, 0x01, "10 Mbps full duplex able" },
+ { 11, 11, 0x01, "10 Mbps half duplex able" },
+ { 10, 10, 0x01, "100BASE-T2 full duplex able" },
+ { 9, 9, 0x01, "100BASE-T2 half duplex able" },
+ { 8, 8, 0x01, "extended status" },
+ { 7, 7, 0x01, "(reserved)" },
+ { 6, 6, 0x01, "MF preamble suppression" },
+ { 5, 5, 0x01, "A/N complete" },
+ { 4, 4, 0x01, "remote fault" },
+ { 3, 3, 0x01, "A/N able" },
+ { 2, 2, 0x01, "link status" },
+ { 1, 1, 0x01, "jabber detect" },
+ { 0, 0, 0x01, "extended capabilities" },
+};
+
+static const MII_field_desc_t reg_2_desc_tbl[] = {
+ { 15, 0, 0xffff, "OUI portion" },
+};
+
+static const MII_field_desc_t reg_3_desc_tbl[] = {
+ { 15, 10, 0x3f, "OUI portion" },
+ { 9, 4, 0x3f, "manufacturer part number" },
+ { 3, 0, 0x0f, "manufacturer rev. number" },
+};
+
+static const MII_field_desc_t reg_4_desc_tbl[] = {
+ { 15, 15, 0x01, "next page able" },
+ { 14, 14, 0x01, "(reserved)" },
+ { 13, 13, 0x01, "remote fault" },
+ { 12, 12, 0x01, "(reserved)" },
+ { 11, 11, 0x01, "asymmetric pause" },
+ { 10, 10, 0x01, "pause enable" },
+ { 9, 9, 0x01, "100BASE-T4 able" },
+ { 8, 8, 0x01, "100BASE-TX full duplex able" },
+ { 7, 7, 0x01, "100BASE-TX able" },
+ { 6, 6, 0x01, "10BASE-T full duplex able" },
+ { 5, 5, 0x01, "10BASE-T able" },
+ { 4, 0, 0x1f, "selector" },
+};
+
+static const MII_field_desc_t reg_5_desc_tbl[] = {
+ { 15, 15, 0x01, "next page able" },
+ { 14, 14, 0x01, "acknowledge" },
+ { 13, 13, 0x01, "remote fault" },
+ { 12, 12, 0x01, "(reserved)" },
+ { 11, 11, 0x01, "asymmetric pause able" },
+ { 10, 10, 0x01, "pause able" },
+ { 9, 9, 0x01, "100BASE-T4 able" },
+ { 8, 8, 0x01, "100BASE-X full duplex able" },
+ { 7, 7, 0x01, "100BASE-TX able" },
+ { 6, 6, 0x01, "10BASE-T full duplex able" },
+ { 5, 5, 0x01, "10BASE-T able" },
+ { 4, 0, 0x1f, "partner selector" },
+};
+
+static const MII_field_desc_t reg_9_desc_tbl[] = {
+ { 15, 13, 0x07, "test mode" },
+ { 12, 12, 0x01, "manual master/slave enable" },
+ { 11, 11, 0x01, "manual master/slave value" },
+ { 10, 10, 0x01, "multi/single port" },
+ { 9, 9, 0x01, "1000BASE-T full duplex able" },
+ { 8, 8, 0x01, "1000BASE-T half duplex able" },
+ { 7, 7, 0x01, "automatic TDR on link down" },
+ { 6, 6, 0x7f, "(reserved)" },
+};
+
+static const MII_field_desc_t reg_10_desc_tbl[] = {
+ { 15, 15, 0x01, "master/slave config fault" },
+ { 14, 14, 0x01, "master/slave config result" },
+ { 13, 13, 0x01, "local receiver status OK" },
+ { 12, 12, 0x01, "remote receiver status OK" },
+ { 11, 11, 0x01, "1000BASE-T full duplex able" },
+ { 10, 10, 0x01, "1000BASE-T half duplex able" },
+ { 9, 8, 0x03, "(reserved)" },
+ { 7, 0, 0xff, "1000BASE-T idle error counter"},
+};
+
+typedef struct _MII_reg_desc_t {
+ ushort regno;
+ const MII_field_desc_t *pdesc;
+ ushort len;
+ const char *name;
+} MII_reg_desc_t;
+
+static const MII_reg_desc_t mii_reg_desc_tbl[] = {
+ { MII_BMCR, reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl),
+ "PHY control register" },
+ { MII_BMSR, reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl),
+ "PHY status register" },
+ { MII_PHYSID1, reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl),
+ "PHY ID 1 register" },
+ { MII_PHYSID2, reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl),
+ "PHY ID 2 register" },
+ { MII_ADVERTISE, reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl),
+ "Autonegotiation advertisement register" },
+ { MII_LPA, reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl),
+ "Autonegotiation partner abilities register" },
+ { MII_CTRL1000, reg_9_desc_tbl, ARRAY_SIZE(reg_9_desc_tbl),
+ "1000BASE-T control register" },
+ { MII_STAT1000, reg_10_desc_tbl, ARRAY_SIZE(reg_10_desc_tbl),
+ "1000BASE-T status register" },
+};
+
+static void dump_reg(
+ ushort regval,
+ const MII_reg_desc_t *prd);
+
+static bool special_field(ushort regno, const MII_field_desc_t *pdesc,
+ ushort regval);
+
+static void MII_dump(const ushort *regvals, uchar reglo, uchar reghi)
+{
+ ulong i;
+
+ for (i = 0; i < ARRAY_SIZE(mii_reg_desc_tbl); i++) {
+ const uchar reg = mii_reg_desc_tbl[i].regno;
+
+ if (reg >= reglo && reg <= reghi)
+ dump_reg(regvals[reg - reglo], &mii_reg_desc_tbl[i]);
+ }
+}
+
+/* Print out field position, value, name */
+static void dump_field(const MII_field_desc_t *pdesc, ushort regval)
+{
+ if (pdesc->hi == pdesc->lo)
+ printf("%2u ", pdesc->lo);
+ else
+ printf("%2u-%2u", pdesc->hi, pdesc->lo);
+
+ printf(" = %5u %s", (regval >> pdesc->lo) & pdesc->mask,
+ pdesc->name);
+}
+
+static void dump_reg(
+ ushort regval,
+ const MII_reg_desc_t *prd)
+{
+ ulong i;
+ ushort mask_in_place;
+ const MII_field_desc_t *pdesc;
+
+ printf("%u. (%04hx) -- %s --\n",
+ prd->regno, regval, prd->name);
+
+ for (i = 0; i < prd->len; i++) {
+ pdesc = &prd->pdesc[i];
+
+ mask_in_place = pdesc->mask << pdesc->lo;
+
+ printf(" (%04hx:%04x) %u.",
+ mask_in_place,
+ regval & mask_in_place,
+ prd->regno);
+
+ if (!special_field(prd->regno, pdesc, regval))
+ dump_field(pdesc, regval);
+ printf("\n");
+
+ }
+ printf("\n");
+}
+
+/* Special fields:
+** 0.6,13
+** 0.8
+** 2.15-0
+** 3.15-0
+** 4.4-0
+** 5.4-0
+*/
+
+static bool special_field(ushort regno, const MII_field_desc_t *pdesc,
+ ushort regval)
+{
+ const ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
+
+ if ((regno == MII_BMCR) && (pdesc->lo == 6)) {
+ ushort speed_bits = regval & (BMCR_SPEED1000 | BMCR_SPEED100);
+ printf("%2u,%2u = b%u%u speed selection = %s Mbps",
+ 6, 13,
+ (regval >> 6) & 1,
+ (regval >> 13) & 1,
+ speed_bits == BMCR_SPEED1000 ? "1000" :
+ speed_bits == BMCR_SPEED100 ? "100" :
+ "10");
+ return 1;
+ }
+
+ else if ((regno == MII_BMCR) && (pdesc->lo == 8)) {
+ dump_field(pdesc, regval);
+ printf(" = %s", ((regval >> pdesc->lo) & 1) ? "full" : "half");
+ return 1;
+ }
+
+ else if ((regno == MII_ADVERTISE) && (pdesc->lo == 0)) {
+ dump_field(pdesc, regval);
+ printf(" = %s",
+ sel_bits == PHY_ANLPAR_PSB_802_3 ? "IEEE 802.3 CSMA/CD" :
+ sel_bits == PHY_ANLPAR_PSB_802_9 ?
+ "IEEE 802.9 ISLAN-16T" : "???");
+ return 1;
+ }
+
+ else if ((regno == MII_LPA) && (pdesc->lo == 0)) {
+ dump_field(pdesc, regval);
+ printf(" = %s",
+ sel_bits == PHY_ANLPAR_PSB_802_3 ? "IEEE 802.3 CSMA/CD" :
+ sel_bits == PHY_ANLPAR_PSB_802_9 ?
+ "IEEE 802.9 ISLAN-16T" : "???");
+ return 1;
+ }
+
+ return 0;
+}
+
+static char last_op[2];
+static uint last_data;
+static uint last_addr_lo;
+static uint last_addr_hi;
+static uint last_reg_lo;
+static uint last_reg_hi;
+static uint last_mask;
+
+static void extract_range(
+ char * input,
+ unsigned char * plo,
+ unsigned char * phi)
+{
+ char * end;
+ *plo = simple_strtoul(input, &end, 16);
+ if (*end == '-') {
+ end++;
+ *phi = simple_strtoul(end, NULL, 16);
+ }
+ else {
+ *phi = *plo;
+ }
+}
+
+/* ---------------------------------------------------------------- */
+static int do_mii(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char op[2];
+ unsigned char addrlo, addrhi, reglo, reghi;
+ unsigned char addr, reg;
+ unsigned short data, mask;
+ int rcode = 0;
+ const char *devname;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+#if defined(CONFIG_MII_INIT)
+ mii_init ();
+#endif
+
+ /*
+ * We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ op[0] = last_op[0];
+ op[1] = last_op[1];
+ addrlo = last_addr_lo;
+ addrhi = last_addr_hi;
+ reglo = last_reg_lo;
+ reghi = last_reg_hi;
+ data = last_data;
+ mask = last_mask;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ op[0] = argv[1][0];
+ if (strlen(argv[1]) > 1)
+ op[1] = argv[1][1];
+ else
+ op[1] = '\0';
+
+ if (argc >= 3)
+ extract_range(argv[2], &addrlo, &addrhi);
+ if (argc >= 4)
+ extract_range(argv[3], &reglo, &reghi);
+ if (argc >= 5)
+ data = simple_strtoul(argv[4], NULL, 16);
+ if (argc >= 6)
+ mask = simple_strtoul(argv[5], NULL, 16);
+ }
+
+ if (addrhi > 31 && strncmp(op, "de", 2)) {
+ printf("Incorrect PHY address. Range should be 0-31\n");
+ return CMD_RET_USAGE;
+ }
+
+ /* use current device */
+ devname = miiphy_get_current_dev();
+
+ /*
+ * check info/read/write.
+ */
+ if (op[0] == 'i') {
+ unsigned char j, start, end;
+ unsigned int oui;
+ unsigned char model;
+ unsigned char rev;
+
+ /*
+ * Look for any and all PHYs. Valid addresses are 0..31.
+ */
+ if (argc >= 3) {
+ start = addrlo; end = addrhi;
+ } else {
+ start = 0; end = 31;
+ }
+
+ for (j = start; j <= end; j++) {
+ if (miiphy_info (devname, j, &oui, &model, &rev) == 0) {
+ printf("PHY 0x%02X: "
+ "OUI = 0x%04X, "
+ "Model = 0x%02X, "
+ "Rev = 0x%02X, "
+ "%3dbase%s, %s\n",
+ j, oui, model, rev,
+ miiphy_speed (devname, j),
+ miiphy_is_1000base_x (devname, j)
+ ? "X" : "T",
+ (miiphy_duplex (devname, j) == FULL)
+ ? "FDX" : "HDX");
+ }
+ }
+ } else if (op[0] == 'r') {
+ for (addr = addrlo; addr <= addrhi; addr++) {
+ for (reg = reglo; reg <= reghi; reg++) {
+ data = 0xffff;
+ if (miiphy_read (devname, addr, reg, &data) != 0) {
+ printf(
+ "Error reading from the PHY addr=%02x reg=%02x\n",
+ addr, reg);
+ rcode = 1;
+ } else {
+ if ((addrlo != addrhi) || (reglo != reghi))
+ printf("addr=%02x reg=%02x data=",
+ (uint)addr, (uint)reg);
+ printf("%04X\n", data & 0x0000FFFF);
+ }
+ }
+ if ((addrlo != addrhi) && (reglo != reghi))
+ printf("\n");
+ }
+ } else if (op[0] == 'w') {
+ for (addr = addrlo; addr <= addrhi; addr++) {
+ for (reg = reglo; reg <= reghi; reg++) {
+ if (miiphy_write (devname, addr, reg, data) != 0) {
+ printf("Error writing to the PHY addr=%02x reg=%02x\n",
+ addr, reg);
+ rcode = 1;
+ }
+ }
+ }
+ } else if (op[0] == 'm') {
+ for (addr = addrlo; addr <= addrhi; addr++) {
+ for (reg = reglo; reg <= reghi; reg++) {
+ unsigned short val = 0;
+ if (miiphy_read(devname, addr,
+ reg, &val)) {
+ printf("Error reading from the PHY");
+ printf(" addr=%02x", addr);
+ printf(" reg=%02x\n", reg);
+ rcode = 1;
+ } else {
+ val = (val & ~mask) | (data & mask);
+ if (miiphy_write(devname, addr,
+ reg, val)) {
+ printf("Error writing to the PHY");
+ printf(" addr=%02x", addr);
+ printf(" reg=%02x\n", reg);
+ rcode = 1;
+ }
+ }
+ }
+ }
+ } else if (strncmp(op, "du", 2) == 0) {
+ ushort regs[MII_STAT1000 + 1]; /* Last reg is 0x0a */
+ int ok = 1;
+ if (reglo > MII_STAT1000 || reghi > MII_STAT1000) {
+ printf("The MII dump command only formats the standard MII registers, 0-5, 9-a.\n");
+ return 1;
+ }
+ for (addr = addrlo; addr <= addrhi; addr++) {
+ for (reg = reglo; reg <= reghi; reg++) {
+ if (miiphy_read(devname, addr, reg,
+ &regs[reg - reglo]) != 0) {
+ ok = 0;
+ printf(
+ "Error reading from the PHY addr=%02x reg=%02x\n",
+ addr, reg);
+ rcode = 1;
+ }
+ }
+ if (ok)
+ MII_dump(regs, reglo, reghi);
+ printf("\n");
+ }
+ } else if (strncmp(op, "de", 2) == 0) {
+ if (argc == 2)
+ miiphy_listdev ();
+ else
+ miiphy_set_current_dev (argv[2]);
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ /*
+ * Save the parameters for repeats.
+ */
+ last_op[0] = op[0];
+ last_op[1] = op[1];
+ last_addr_lo = addrlo;
+ last_addr_hi = addrhi;
+ last_reg_lo = reglo;
+ last_reg_hi = reghi;
+ last_data = data;
+ last_mask = mask;
+
+ return rcode;
+}
+
+/***************************************************/
+
+U_BOOT_CMD(
+ mii, 6, 1, do_mii,
+ "MII utility commands",
+ "device - list available devices\n"
+ "mii device <devname> - set current device\n"
+ "mii info <addr> - display MII PHY info\n"
+ "mii read <addr> <reg> - read MII PHY <addr> register <reg>\n"
+ "mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"
+ "mii modify <addr> <reg> <data> <mask> - modify MII PHY <addr> register <reg>\n"
+ " updating bits identified in <mask>\n"
+ "mii dump <addr> <reg> - pretty-print <addr> <reg> (0-5 only)\n"
+ "Addr and/or reg may be ranges, e.g. 2-7."
+);
diff --git a/roms/u-boot/cmd/misc.c b/roms/u-boot/cmd/misc.c
new file mode 100644
index 000000000..ef540e836
--- /dev/null
+++ b/roms/u-boot/cmd/misc.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Wind River Systems, Inc.
+ *
+ * Author:
+ * Bin Meng <bin.meng@windriver.com>
+ *
+ * A command interface to access misc devices with MISC uclass driver APIs.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <errno.h>
+#include <misc.h>
+
+enum misc_op {
+ MISC_OP_READ,
+ MISC_OP_WRITE
+};
+
+static char *misc_op_str[] = {
+ "read",
+ "write"
+};
+
+static int do_misc_list(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct udevice *dev;
+
+ printf("Device Index Driver\n");
+ printf("-------------------------------------\n");
+ for (uclass_first_device(UCLASS_MISC, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ printf("%-20s %5d %10s\n", dev->name, dev_seq(dev),
+ dev->driver->name);
+ }
+
+ return 0;
+}
+
+static int do_misc_op(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[], enum misc_op op)
+{
+ int (*misc_op)(struct udevice *, int, void *, int);
+ struct udevice *dev;
+ int offset;
+ void *buf;
+ int size;
+ int ret;
+
+ ret = uclass_get_device_by_name(UCLASS_MISC, argv[0], &dev);
+ if (ret) {
+ printf("Unable to find device %s\n", argv[0]);
+ return ret;
+ }
+
+ offset = simple_strtoul(argv[1], NULL, 16);
+ buf = (void *)simple_strtoul(argv[2], NULL, 16);
+ size = simple_strtoul(argv[3], NULL, 16);
+
+ if (op == MISC_OP_READ)
+ misc_op = misc_read;
+ else
+ misc_op = misc_write;
+
+ ret = misc_op(dev, offset, buf, size);
+ if (ret < 0) {
+ if (ret == -ENOSYS) {
+ printf("The device does not support %s\n",
+ misc_op_str[op]);
+ ret = 0;
+ }
+ } else {
+ if (ret == size)
+ ret = 0;
+ else
+ printf("Partially %s %d bytes\n", misc_op_str[op], ret);
+ }
+
+ return ret;
+}
+
+static int do_misc_read(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ return do_misc_op(cmdtp, flag, argc, argv, MISC_OP_READ);
+}
+
+static int do_misc_write(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ return do_misc_op(cmdtp, flag, argc, argv, MISC_OP_WRITE);
+}
+
+static struct cmd_tbl misc_commands[] = {
+ U_BOOT_CMD_MKENT(list, 0, 1, do_misc_list, "", ""),
+ U_BOOT_CMD_MKENT(read, 4, 1, do_misc_read, "", ""),
+ U_BOOT_CMD_MKENT(write, 4, 1, do_misc_write, "", ""),
+};
+
+static int do_misc(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct cmd_tbl *misc_cmd;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ misc_cmd = find_cmd_tbl(argv[1], misc_commands,
+ ARRAY_SIZE(misc_commands));
+ argc -= 2;
+ argv += 2;
+ if (!misc_cmd || argc != misc_cmd->maxargs)
+ return CMD_RET_USAGE;
+
+ ret = misc_cmd->cmd(misc_cmd, flag, argc, argv);
+
+ return cmd_process_error(misc_cmd, ret);
+}
+
+U_BOOT_CMD(
+ misc, 6, 1, do_misc,
+ "Access miscellaneous devices with MISC uclass driver APIs",
+ "list - list all miscellaneous devices\n"
+ "misc read name offset addr len - read `len' bytes starting at\n"
+ " `offset' of device `name'\n"
+ " to memory at `addr'\n"
+ "misc write name offset addr len - write `len' bytes starting at\n"
+ " `offset' of device `name'\n"
+ " from memory at `addr'"
+);
diff --git a/roms/u-boot/cmd/mmc.c b/roms/u-boot/cmd/mmc.c
new file mode 100644
index 000000000..b942576b5
--- /dev/null
+++ b/roms/u-boot/cmd/mmc.c
@@ -0,0 +1,1092 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2003
+ * Kyle Harris, kharris@nexus-tech.net
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <command.h>
+#include <console.h>
+#include <memalign.h>
+#include <mmc.h>
+#include <part.h>
+#include <sparse_format.h>
+#include <image-sparse.h>
+
+static int curr_device = -1;
+
+static void print_mmcinfo(struct mmc *mmc)
+{
+ int i;
+
+ printf("Device: %s\n", mmc->cfg->name);
+ printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24);
+ printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff);
+ printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff,
+ (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
+ (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
+
+ printf("Bus Speed: %d\n", mmc->clock);
+#if CONFIG_IS_ENABLED(MMC_VERBOSE)
+ printf("Mode: %s\n", mmc_mode_name(mmc->selected_mode));
+ mmc_dump_capabilities("card capabilities", mmc->card_caps);
+ mmc_dump_capabilities("host capabilities", mmc->host_caps);
+#endif
+ printf("Rd Block Len: %d\n", mmc->read_bl_len);
+
+ printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC",
+ EXTRACT_SDMMC_MAJOR_VERSION(mmc->version),
+ EXTRACT_SDMMC_MINOR_VERSION(mmc->version));
+ if (EXTRACT_SDMMC_CHANGE_VERSION(mmc->version) != 0)
+ printf(".%d", EXTRACT_SDMMC_CHANGE_VERSION(mmc->version));
+ printf("\n");
+
+ printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
+ puts("Capacity: ");
+ print_size(mmc->capacity, "\n");
+
+ printf("Bus Width: %d-bit%s\n", mmc->bus_width,
+ mmc->ddr_mode ? " DDR" : "");
+
+#if CONFIG_IS_ENABLED(MMC_WRITE)
+ puts("Erase Group Size: ");
+ print_size(((u64)mmc->erase_grp_size) << 9, "\n");
+#endif
+
+ if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4_41) {
+ bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0;
+ bool usr_enh = has_enh && (mmc->part_attr & EXT_CSD_ENH_USR);
+ ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
+ u8 wp;
+ int ret;
+
+#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
+ puts("HC WP Group Size: ");
+ print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n");
+#endif
+
+ puts("User Capacity: ");
+ print_size(mmc->capacity_user, usr_enh ? " ENH" : "");
+ if (mmc->wr_rel_set & EXT_CSD_WR_DATA_REL_USR)
+ puts(" WRREL\n");
+ else
+ putc('\n');
+ if (usr_enh) {
+ puts("User Enhanced Start: ");
+ print_size(mmc->enh_user_start, "\n");
+ puts("User Enhanced Size: ");
+ print_size(mmc->enh_user_size, "\n");
+ }
+ puts("Boot Capacity: ");
+ print_size(mmc->capacity_boot, has_enh ? " ENH\n" : "\n");
+ puts("RPMB Capacity: ");
+ print_size(mmc->capacity_rpmb, has_enh ? " ENH\n" : "\n");
+
+ for (i = 0; i < ARRAY_SIZE(mmc->capacity_gp); i++) {
+ bool is_enh = has_enh &&
+ (mmc->part_attr & EXT_CSD_ENH_GP(i));
+ if (mmc->capacity_gp[i]) {
+ printf("GP%i Capacity: ", i+1);
+ print_size(mmc->capacity_gp[i],
+ is_enh ? " ENH" : "");
+ if (mmc->wr_rel_set & EXT_CSD_WR_DATA_REL_GP(i))
+ puts(" WRREL\n");
+ else
+ putc('\n');
+ }
+ }
+ ret = mmc_send_ext_csd(mmc, ext_csd);
+ if (ret)
+ return;
+ wp = ext_csd[EXT_CSD_BOOT_WP_STATUS];
+ for (i = 0; i < 2; ++i) {
+ printf("Boot area %d is ", i);
+ switch (wp & 3) {
+ case 0:
+ printf("not write protected\n");
+ break;
+ case 1:
+ printf("power on protected\n");
+ break;
+ case 2:
+ printf("permanently protected\n");
+ break;
+ default:
+ printf("in reserved protection state\n");
+ break;
+ }
+ wp >>= 2;
+ }
+ }
+}
+static struct mmc *init_mmc_device(int dev, bool force_init)
+{
+ struct mmc *mmc;
+ mmc = find_mmc_device(dev);
+ if (!mmc) {
+ printf("no mmc device at slot %x\n", dev);
+ return NULL;
+ }
+
+ if (!mmc_getcd(mmc))
+ force_init = true;
+
+ if (force_init)
+ mmc->has_init = 0;
+ if (mmc_init(mmc))
+ return NULL;
+
+#ifdef CONFIG_BLOCK_CACHE
+ struct blk_desc *bd = mmc_get_blk_desc(mmc);
+ blkcache_invalidate(bd->if_type, bd->devnum);
+#endif
+
+ return mmc;
+}
+
+static int do_mmcinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct mmc *mmc;
+
+ if (curr_device < 0) {
+ if (get_mmc_num() > 0)
+ curr_device = 0;
+ else {
+ puts("No MMC device available\n");
+ return 1;
+ }
+ }
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ print_mmcinfo(mmc);
+ return CMD_RET_SUCCESS;
+}
+
+#if CONFIG_IS_ENABLED(CMD_MMC_RPMB)
+static int confirm_key_prog(void)
+{
+ puts("Warning: Programming authentication key can be done only once !\n"
+ " Use this command only if you are sure of what you are doing,\n"
+ "Really perform the key programming? <y/N> ");
+ if (confirm_yesno())
+ return 1;
+
+ puts("Authentication key programming aborted\n");
+ return 0;
+}
+
+static int do_mmcrpmb_key(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ void *key_addr;
+ struct mmc *mmc = find_mmc_device(curr_device);
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ key_addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ if (!confirm_key_prog())
+ return CMD_RET_FAILURE;
+ if (mmc_rpmb_set_key(mmc, key_addr)) {
+ printf("ERROR - Key already programmed ?\n");
+ return CMD_RET_FAILURE;
+ }
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mmcrpmb_read(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ u16 blk, cnt;
+ void *addr;
+ int n;
+ void *key_addr = NULL;
+ struct mmc *mmc = find_mmc_device(curr_device);
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+ cnt = simple_strtoul(argv[3], NULL, 16);
+
+ if (argc == 5)
+ key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
+
+ printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
+ n = mmc_rpmb_read(mmc, addr, blk, cnt, key_addr);
+
+ printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+ if (n != cnt)
+ return CMD_RET_FAILURE;
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mmcrpmb_write(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ u16 blk, cnt;
+ void *addr;
+ int n;
+ void *key_addr;
+ struct mmc *mmc = find_mmc_device(curr_device);
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+ cnt = simple_strtoul(argv[3], NULL, 16);
+ key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
+
+ printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
+ n = mmc_rpmb_write(mmc, addr, blk, cnt, key_addr);
+
+ printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+ if (n != cnt)
+ return CMD_RET_FAILURE;
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mmcrpmb_counter(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ unsigned long counter;
+ struct mmc *mmc = find_mmc_device(curr_device);
+
+ if (mmc_rpmb_get_counter(mmc, &counter))
+ return CMD_RET_FAILURE;
+ printf("RPMB Write counter= %lx\n", counter);
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_rpmb[] = {
+ U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""),
+ U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""),
+ U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""),
+ U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""),
+};
+
+static int do_mmcrpmb(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct cmd_tbl *cp;
+ struct mmc *mmc;
+ char original_part;
+ int ret;
+
+ cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb));
+
+ /* Drop the rpmb subcommand */
+ argc--;
+ argv++;
+
+ if (cp == NULL || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+ if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+ return CMD_RET_SUCCESS;
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ if (!(mmc->version & MMC_VERSION_MMC)) {
+ printf("It is not an eMMC device\n");
+ return CMD_RET_FAILURE;
+ }
+ if (mmc->version < MMC_VERSION_4_41) {
+ printf("RPMB not supported before version 4.41\n");
+ return CMD_RET_FAILURE;
+ }
+ /* Switch to the RPMB partition */
+#ifndef CONFIG_BLK
+ original_part = mmc->block_dev.hwpart;
+#else
+ original_part = mmc_get_blk_desc(mmc)->hwpart;
+#endif
+ if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) !=
+ 0)
+ return CMD_RET_FAILURE;
+ ret = cp->cmd(cmdtp, flag, argc, argv);
+
+ /* Return to original partition */
+ if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) !=
+ 0)
+ return CMD_RET_FAILURE;
+ return ret;
+}
+#endif
+
+static int do_mmc_read(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct mmc *mmc;
+ u32 blk, cnt, n;
+ void *addr;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+ cnt = simple_strtoul(argv[3], NULL, 16);
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ printf("\nMMC read: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
+
+ n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
+ printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+
+ return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+
+#if CONFIG_IS_ENABLED(CMD_MMC_SWRITE)
+static lbaint_t mmc_sparse_write(struct sparse_storage *info, lbaint_t blk,
+ lbaint_t blkcnt, const void *buffer)
+{
+ struct blk_desc *dev_desc = info->priv;
+
+ return blk_dwrite(dev_desc, blk, blkcnt, buffer);
+}
+
+static lbaint_t mmc_sparse_reserve(struct sparse_storage *info,
+ lbaint_t blk, lbaint_t blkcnt)
+{
+ return blkcnt;
+}
+
+static int do_mmc_sparse_write(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct sparse_storage sparse;
+ struct blk_desc *dev_desc;
+ struct mmc *mmc;
+ char dest[11];
+ void *addr;
+ u32 blk;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+
+ if (!is_sparse_image(addr)) {
+ printf("Not a sparse image\n");
+ return CMD_RET_FAILURE;
+ }
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ printf("\nMMC Sparse write: dev # %d, block # %d ... ",
+ curr_device, blk);
+
+ if (mmc_getwp(mmc) == 1) {
+ printf("Error: card is write protected!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ dev_desc = mmc_get_blk_desc(mmc);
+ sparse.priv = dev_desc;
+ sparse.blksz = 512;
+ sparse.start = blk;
+ sparse.size = dev_desc->lba - blk;
+ sparse.write = mmc_sparse_write;
+ sparse.reserve = mmc_sparse_reserve;
+ sparse.mssg = NULL;
+ sprintf(dest, "0x" LBAF, sparse.start * sparse.blksz);
+
+ if (write_sparse_image(&sparse, dest, addr, NULL))
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(MMC_WRITE)
+static int do_mmc_write(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct mmc *mmc;
+ u32 blk, cnt, n;
+ void *addr;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ blk = simple_strtoul(argv[2], NULL, 16);
+ cnt = simple_strtoul(argv[3], NULL, 16);
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ printf("\nMMC write: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
+
+ if (mmc_getwp(mmc) == 1) {
+ printf("Error: card is write protected!\n");
+ return CMD_RET_FAILURE;
+ }
+ n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
+ printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+
+ return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+
+static int do_mmc_erase(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct mmc *mmc;
+ u32 blk, cnt, n;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ blk = simple_strtoul(argv[1], NULL, 16);
+ cnt = simple_strtoul(argv[2], NULL, 16);
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ printf("\nMMC erase: dev # %d, block # %d, count %d ... ",
+ curr_device, blk, cnt);
+
+ if (mmc_getwp(mmc) == 1) {
+ printf("Error: card is write protected!\n");
+ return CMD_RET_FAILURE;
+ }
+ n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
+ printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
+
+ return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+#endif
+
+static int do_mmc_rescan(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct mmc *mmc;
+
+ mmc = init_mmc_device(curr_device, true);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mmc_part(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct blk_desc *mmc_dev;
+ struct mmc *mmc;
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device);
+ if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
+ part_print(mmc_dev);
+ return CMD_RET_SUCCESS;
+ }
+
+ puts("get mmc type error!\n");
+ return CMD_RET_FAILURE;
+}
+
+static int do_mmc_dev(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int dev, part = 0, ret;
+ struct mmc *mmc;
+
+ if (argc == 1) {
+ dev = curr_device;
+ } else if (argc == 2) {
+ dev = simple_strtoul(argv[1], NULL, 10);
+ } else if (argc == 3) {
+ dev = (int)simple_strtoul(argv[1], NULL, 10);
+ part = (int)simple_strtoul(argv[2], NULL, 10);
+ if (part > PART_ACCESS_MASK) {
+ printf("#part_num shouldn't be larger than %d\n",
+ PART_ACCESS_MASK);
+ return CMD_RET_FAILURE;
+ }
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ mmc = init_mmc_device(dev, true);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part);
+ printf("switch to partitions #%d, %s\n",
+ part, (!ret) ? "OK" : "ERROR");
+ if (ret)
+ return 1;
+
+ curr_device = dev;
+ if (mmc->part_config == MMCPART_NOAVAILABLE)
+ printf("mmc%d is current device\n", curr_device);
+ else
+ printf("mmc%d(part %d) is current device\n",
+ curr_device, mmc_get_blk_desc(mmc)->hwpart);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mmc_list(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ print_mmc_devices('\n');
+ return CMD_RET_SUCCESS;
+}
+
+#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
+static int parse_hwpart_user(struct mmc_hwpart_conf *pconf,
+ int argc, char *const argv[])
+{
+ int i = 0;
+
+ memset(&pconf->user, 0, sizeof(pconf->user));
+
+ while (i < argc) {
+ if (!strcmp(argv[i], "enh")) {
+ if (i + 2 >= argc)
+ return -1;
+ pconf->user.enh_start =
+ simple_strtoul(argv[i+1], NULL, 10);
+ pconf->user.enh_size =
+ simple_strtoul(argv[i+2], NULL, 10);
+ i += 3;
+ } else if (!strcmp(argv[i], "wrrel")) {
+ if (i + 1 >= argc)
+ return -1;
+ pconf->user.wr_rel_change = 1;
+ if (!strcmp(argv[i+1], "on"))
+ pconf->user.wr_rel_set = 1;
+ else if (!strcmp(argv[i+1], "off"))
+ pconf->user.wr_rel_set = 0;
+ else
+ return -1;
+ i += 2;
+ } else {
+ break;
+ }
+ }
+ return i;
+}
+
+static int parse_hwpart_gp(struct mmc_hwpart_conf *pconf, int pidx,
+ int argc, char *const argv[])
+{
+ int i;
+
+ memset(&pconf->gp_part[pidx], 0, sizeof(pconf->gp_part[pidx]));
+
+ if (1 >= argc)
+ return -1;
+ pconf->gp_part[pidx].size = simple_strtoul(argv[0], NULL, 10);
+
+ i = 1;
+ while (i < argc) {
+ if (!strcmp(argv[i], "enh")) {
+ pconf->gp_part[pidx].enhanced = 1;
+ i += 1;
+ } else if (!strcmp(argv[i], "wrrel")) {
+ if (i + 1 >= argc)
+ return -1;
+ pconf->gp_part[pidx].wr_rel_change = 1;
+ if (!strcmp(argv[i+1], "on"))
+ pconf->gp_part[pidx].wr_rel_set = 1;
+ else if (!strcmp(argv[i+1], "off"))
+ pconf->gp_part[pidx].wr_rel_set = 0;
+ else
+ return -1;
+ i += 2;
+ } else {
+ break;
+ }
+ }
+ return i;
+}
+
+static int do_mmc_hwpartition(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct mmc *mmc;
+ struct mmc_hwpart_conf pconf = { };
+ enum mmc_hwpart_conf_mode mode = MMC_HWPART_CONF_CHECK;
+ int i, r, pidx;
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ if (argc < 1)
+ return CMD_RET_USAGE;
+ i = 1;
+ while (i < argc) {
+ if (!strcmp(argv[i], "user")) {
+ i++;
+ r = parse_hwpart_user(&pconf, argc-i, &argv[i]);
+ if (r < 0)
+ return CMD_RET_USAGE;
+ i += r;
+ } else if (!strncmp(argv[i], "gp", 2) &&
+ strlen(argv[i]) == 3 &&
+ argv[i][2] >= '1' && argv[i][2] <= '4') {
+ pidx = argv[i][2] - '1';
+ i++;
+ r = parse_hwpart_gp(&pconf, pidx, argc-i, &argv[i]);
+ if (r < 0)
+ return CMD_RET_USAGE;
+ i += r;
+ } else if (!strcmp(argv[i], "check")) {
+ mode = MMC_HWPART_CONF_CHECK;
+ i++;
+ } else if (!strcmp(argv[i], "set")) {
+ mode = MMC_HWPART_CONF_SET;
+ i++;
+ } else if (!strcmp(argv[i], "complete")) {
+ mode = MMC_HWPART_CONF_COMPLETE;
+ i++;
+ } else {
+ return CMD_RET_USAGE;
+ }
+ }
+
+ puts("Partition configuration:\n");
+ if (pconf.user.enh_size) {
+ puts("\tUser Enhanced Start: ");
+ print_size(((u64)pconf.user.enh_start) << 9, "\n");
+ puts("\tUser Enhanced Size: ");
+ print_size(((u64)pconf.user.enh_size) << 9, "\n");
+ } else {
+ puts("\tNo enhanced user data area\n");
+ }
+ if (pconf.user.wr_rel_change)
+ printf("\tUser partition write reliability: %s\n",
+ pconf.user.wr_rel_set ? "on" : "off");
+ for (pidx = 0; pidx < 4; pidx++) {
+ if (pconf.gp_part[pidx].size) {
+ printf("\tGP%i Capacity: ", pidx+1);
+ print_size(((u64)pconf.gp_part[pidx].size) << 9,
+ pconf.gp_part[pidx].enhanced ?
+ " ENH\n" : "\n");
+ } else {
+ printf("\tNo GP%i partition\n", pidx+1);
+ }
+ if (pconf.gp_part[pidx].wr_rel_change)
+ printf("\tGP%i write reliability: %s\n", pidx+1,
+ pconf.gp_part[pidx].wr_rel_set ? "on" : "off");
+ }
+
+ if (!mmc_hwpart_config(mmc, &pconf, mode)) {
+ if (mode == MMC_HWPART_CONF_COMPLETE)
+ puts("Partitioning successful, "
+ "power-cycle to make effective\n");
+ return CMD_RET_SUCCESS;
+ } else {
+ puts("Failed!\n");
+ return CMD_RET_FAILURE;
+ }
+}
+#endif
+
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int do_mmc_bootbus(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+ u8 width, reset, mode;
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+ dev = simple_strtoul(argv[1], NULL, 10);
+ width = simple_strtoul(argv[2], NULL, 10);
+ reset = simple_strtoul(argv[3], NULL, 10);
+ mode = simple_strtoul(argv[4], NULL, 10);
+
+ mmc = init_mmc_device(dev, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ if (IS_SD(mmc)) {
+ puts("BOOT_BUS_WIDTH only exists on eMMC\n");
+ return CMD_RET_FAILURE;
+ }
+
+ /*
+ * BOOT_BUS_CONDITIONS[177]
+ * BOOT_MODE[4:3]
+ * 0x0 : Use SDR + Backward compatible timing in boot operation
+ * 0x1 : Use SDR + High Speed Timing in boot operation mode
+ * 0x2 : Use DDR in boot operation
+ * RESET_BOOT_BUS_CONDITIONS
+ * 0x0 : Reset bus width to x1, SDR, Backward compatible
+ * 0x1 : Retain BOOT_BUS_WIDTH and BOOT_MODE
+ * BOOT_BUS_WIDTH
+ * 0x0 : x1(sdr) or x4 (ddr) buswidth
+ * 0x1 : x4(sdr/ddr) buswith
+ * 0x2 : x8(sdr/ddr) buswith
+ *
+ */
+ if (width >= 0x3) {
+ printf("boot_bus_width %d is invalid\n", width);
+ return CMD_RET_FAILURE;
+ }
+
+ if (reset >= 0x2) {
+ printf("reset_boot_bus_width %d is invalid\n", reset);
+ return CMD_RET_FAILURE;
+ }
+
+ if (mode >= 0x3) {
+ printf("reset_boot_bus_width %d is invalid\n", mode);
+ return CMD_RET_FAILURE;
+ }
+
+ /* acknowledge to be sent during boot operation */
+ if (mmc_set_boot_bus_width(mmc, width, reset, mode)) {
+ puts("BOOT_BUS_WIDTH is failed to change.\n");
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Set to BOOT_BUS_WIDTH = 0x%x, RESET = 0x%x, BOOT_MODE = 0x%x\n",
+ width, reset, mode);
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mmc_boot_resize(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+ u32 bootsize, rpmbsize;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+ dev = simple_strtoul(argv[1], NULL, 10);
+ bootsize = simple_strtoul(argv[2], NULL, 10);
+ rpmbsize = simple_strtoul(argv[3], NULL, 10);
+
+ mmc = init_mmc_device(dev, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ if (IS_SD(mmc)) {
+ printf("It is not an eMMC device\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) {
+ printf("EMMC boot partition Size change Failed.\n");
+ return CMD_RET_FAILURE;
+ }
+
+ printf("EMMC boot partition Size %d MB\n", bootsize);
+ printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
+ return CMD_RET_SUCCESS;
+}
+
+static int mmc_partconf_print(struct mmc *mmc, const char *varname)
+{
+ u8 ack, access, part;
+
+ if (mmc->part_config == MMCPART_NOAVAILABLE) {
+ printf("No part_config info for ver. 0x%x\n", mmc->version);
+ return CMD_RET_FAILURE;
+ }
+
+ access = EXT_CSD_EXTRACT_PARTITION_ACCESS(mmc->part_config);
+ ack = EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config);
+ part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
+
+ if(varname)
+ env_set_hex(varname, part);
+
+ printf("EXT_CSD[179], PARTITION_CONFIG:\n"
+ "BOOT_ACK: 0x%x\n"
+ "BOOT_PARTITION_ENABLE: 0x%x\n"
+ "PARTITION_ACCESS: 0x%x\n", ack, part, access);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mmc_partconf(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+ u8 ack, part_num, access;
+
+ if (argc != 2 && argc != 3 && argc != 5)
+ return CMD_RET_USAGE;
+
+ dev = simple_strtoul(argv[1], NULL, 10);
+
+ mmc = init_mmc_device(dev, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ if (IS_SD(mmc)) {
+ puts("PARTITION_CONFIG only exists on eMMC\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc == 2 || argc == 3)
+ return mmc_partconf_print(mmc, argc == 3 ? argv[2] : NULL);
+
+ ack = simple_strtoul(argv[2], NULL, 10);
+ part_num = simple_strtoul(argv[3], NULL, 10);
+ access = simple_strtoul(argv[4], NULL, 10);
+
+ /* acknowledge to be sent during boot operation */
+ return mmc_set_part_conf(mmc, ack, part_num, access);
+}
+
+static int do_mmc_rst_func(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+ u8 enable;
+
+ /*
+ * Set the RST_n_ENABLE bit of RST_n_FUNCTION
+ * The only valid values are 0x0, 0x1 and 0x2 and writing
+ * a value of 0x1 or 0x2 sets the value permanently.
+ */
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ dev = simple_strtoul(argv[1], NULL, 10);
+ enable = simple_strtoul(argv[2], NULL, 10);
+
+ if (enable > 2) {
+ puts("Invalid RST_n_ENABLE value\n");
+ return CMD_RET_USAGE;
+ }
+
+ mmc = init_mmc_device(dev, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ if (IS_SD(mmc)) {
+ puts("RST_n_FUNCTION only exists on eMMC\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return mmc_set_rst_n_function(mmc, enable);
+}
+#endif
+static int do_mmc_setdsr(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct mmc *mmc;
+ u32 val;
+ int ret;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ val = simple_strtoul(argv[1], NULL, 16);
+
+ mmc = find_mmc_device(curr_device);
+ if (!mmc) {
+ printf("no mmc device at slot %x\n", curr_device);
+ return CMD_RET_FAILURE;
+ }
+ ret = mmc_set_dsr(mmc, val);
+ printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
+ if (!ret) {
+ mmc->has_init = 0;
+ if (mmc_init(mmc))
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+ }
+ return ret;
+}
+
+#ifdef CONFIG_CMD_BKOPS_ENABLE
+static int do_mmc_bkops_enable(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ dev = simple_strtoul(argv[1], NULL, 10);
+
+ mmc = init_mmc_device(dev, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+
+ if (IS_SD(mmc)) {
+ puts("BKOPS_EN only exists on eMMC\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return mmc_set_bkops_enable(mmc);
+}
+#endif
+
+static int do_mmc_boot_wp(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ int err;
+ struct mmc *mmc;
+
+ mmc = init_mmc_device(curr_device, false);
+ if (!mmc)
+ return CMD_RET_FAILURE;
+ if (IS_SD(mmc)) {
+ printf("It is not an eMMC device\n");
+ return CMD_RET_FAILURE;
+ }
+ err = mmc_boot_wp(mmc);
+ if (err)
+ return CMD_RET_FAILURE;
+ printf("boot areas protected\n");
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_mmc[] = {
+ U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
+ U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
+ U_BOOT_CMD_MKENT(wp, 1, 0, do_mmc_boot_wp, "", ""),
+#if CONFIG_IS_ENABLED(MMC_WRITE)
+ U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
+ U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
+#endif
+#if CONFIG_IS_ENABLED(CMD_MMC_SWRITE)
+ U_BOOT_CMD_MKENT(swrite, 3, 0, do_mmc_sparse_write, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
+ U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""),
+ U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
+ U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
+#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
+ U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""),
+#endif
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+ U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
+ U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""),
+ U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""),
+ U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""),
+#endif
+#if CONFIG_IS_ENABLED(CMD_MMC_RPMB)
+ U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""),
+#ifdef CONFIG_CMD_BKOPS_ENABLE
+ U_BOOT_CMD_MKENT(bkops-enable, 2, 0, do_mmc_bkops_enable, "", ""),
+#endif
+};
+
+static int do_mmcops(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc));
+
+ /* Drop the mmc command */
+ argc--;
+ argv++;
+
+ if (cp == NULL || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+ if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+ return CMD_RET_SUCCESS;
+
+ if (curr_device < 0) {
+ if (get_mmc_num() > 0) {
+ curr_device = 0;
+ } else {
+ puts("No MMC device available\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ mmc, 29, 1, do_mmcops,
+ "MMC sub system",
+ "info - display info of the current MMC device\n"
+ "mmc read addr blk# cnt\n"
+ "mmc write addr blk# cnt\n"
+#if CONFIG_IS_ENABLED(CMD_MMC_SWRITE)
+ "mmc swrite addr blk#\n"
+#endif
+ "mmc erase blk# cnt\n"
+ "mmc rescan\n"
+ "mmc part - lists available partition on current mmc device\n"
+ "mmc dev [dev] [part] - show or set current mmc device [partition]\n"
+ "mmc list - lists available devices\n"
+ "mmc wp - power on write protect boot partitions\n"
+#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
+ "mmc hwpartition <USER> <GP> <MODE> - does hardware partitioning\n"
+ " arguments (sizes in 512-byte blocks):\n"
+ " USER - <user> <enh> <start> <cnt> <wrrel> <{on|off}>\n"
+ " : sets user data area attributes\n"
+ " GP - <{gp1|gp2|gp3|gp4}> <cnt> <enh> <wrrel> <{on|off}>\n"
+ " : general purpose partition\n"
+ " MODE - <{check|set|complete}>\n"
+ " : mode, complete set partitioning completed\n"
+ " WARNING: Partitioning is a write-once setting once it is set to complete.\n"
+ " Power cycling is required to initialize partitions after set to complete.\n"
+#endif
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+ "mmc bootbus <dev> <boot_bus_width> <reset_boot_bus_width> <boot_mode>\n"
+ " - Set the BOOT_BUS_WIDTH field of the specified device\n"
+ "mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
+ " - Change sizes of boot and RPMB partitions of specified device\n"
+ "mmc partconf <dev> [[varname] | [<boot_ack> <boot_partition> <partition_access>]]\n"
+ " - Show or change the bits of the PARTITION_CONFIG field of the specified device\n"
+ " If showing the bits, optionally store the boot_partition field into varname\n"
+ "mmc rst-function <dev> <value>\n"
+ " - Change the RST_n_FUNCTION field of the specified device\n"
+ " WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
+#endif
+#if CONFIG_IS_ENABLED(CMD_MMC_RPMB)
+ "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n"
+ "mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n"
+ "mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n"
+ "mmc rpmb counter - read the value of the write counter\n"
+#endif
+ "mmc setdsr <value> - set DSR register value\n"
+#ifdef CONFIG_CMD_BKOPS_ENABLE
+ "mmc bkops-enable <dev> - enable background operations handshake on device\n"
+ " WARNING: This is a write-once setting.\n"
+#endif
+ );
+
+/* Old command kept for compatibility. Same as 'mmc info' */
+U_BOOT_CMD(
+ mmcinfo, 1, 0, do_mmcinfo,
+ "display MMC info",
+ "- display info of the current MMC device"
+);
diff --git a/roms/u-boot/cmd/mp.c b/roms/u-boot/cmd/mp.c
new file mode 100644
index 000000000..c2b5235a3
--- /dev/null
+++ b/roms/u-boot/cmd/mp.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cpu_func.h>
+
+static int cpu_status_all(void)
+{
+ unsigned long cpuid;
+
+ for (cpuid = 0; ; cpuid++) {
+ if (!is_core_valid(cpuid)) {
+ if (cpuid == 0) {
+ printf("Core num: %lu is not valid\n", cpuid);
+ return 1;
+ }
+ break;
+ }
+ cpu_status(cpuid);
+ }
+
+ return 0;
+}
+
+static int
+cpu_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned long cpuid;
+
+ if (argc == 2 && strncmp(argv[1], "status", 6) == 0)
+ return cpu_status_all();
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ cpuid = simple_strtoul(argv[1], NULL, 10);
+ if (!is_core_valid(cpuid)) {
+ printf ("Core num: %lu is not valid\n", cpuid);
+ return 1;
+ }
+
+
+ if (argc == 3) {
+ if (strncmp(argv[2], "reset", 5) == 0)
+ cpu_reset(cpuid);
+ else if (strncmp(argv[2], "status", 6) == 0)
+ cpu_status(cpuid);
+ else if (strncmp(argv[2], "disable", 7) == 0)
+ return cpu_disable(cpuid);
+ else
+ return CMD_RET_USAGE;
+
+ return 0;
+ }
+
+ /* 4 or greater, make sure its release */
+ if (strncmp(argv[2], "release", 7) != 0)
+ return CMD_RET_USAGE;
+
+ if (cpu_release(cpuid, argc - 3, argv + 3))
+ return CMD_RET_USAGE;
+
+ return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char cpu_help_text[] =
+ "<num> reset - Reset cpu <num>\n"
+ "cpu status - Status of all cpus\n"
+ "cpu <num> status - Status of cpu <num>\n"
+ "cpu <num> disable - Disable cpu <num>\n"
+ "cpu <num> release <addr> [args] - Release cpu <num> at <addr> with [args]"
+#ifdef CONFIG_PPC
+ "\n"
+ " [args] : <pir> <r3> <r6>\n" \
+ " pir - processor id (if writeable)\n" \
+ " r3 - value for gpr 3\n" \
+ " r6 - value for gpr 6\n" \
+ "\n" \
+ " Use '-' for any arg if you want the default value.\n" \
+ " Default for r3 is <num> and r6 is 0\n" \
+ "\n" \
+ " When cpu <num> is released r4 and r5 = 0.\n" \
+ " r7 will contain the size of the initial mapped area"
+#endif
+ "";
+#endif
+
+U_BOOT_CMD(
+ cpu, CONFIG_SYS_MAXARGS, 1, cpu_cmd,
+ "Multiprocessor CPU boot manipulation and release", cpu_help_text
+);
diff --git a/roms/u-boot/cmd/mtd.c b/roms/u-boot/cmd/mtd.c
new file mode 100644
index 000000000..485a963bd
--- /dev/null
+++ b/roms/u-boot/cmd/mtd.c
@@ -0,0 +1,561 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * mtd.c
+ *
+ * Generic command to handle basic operations on any memory device.
+ *
+ * Copyright: Bootlin, 2018
+ * Author: Miquèl Raynal <miquel.raynal@bootlin.com>
+ */
+
+#include <command.h>
+#include <common.h>
+#include <console.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <mtd.h>
+#include <dm/devres.h>
+#include <linux/err.h>
+
+#include <linux/ctype.h>
+
+static struct mtd_info *get_mtd_by_name(const char *name)
+{
+ struct mtd_info *mtd;
+
+ mtd_probe_devices();
+
+ mtd = get_mtd_device_nm(name);
+ if (IS_ERR_OR_NULL(mtd))
+ printf("MTD device %s not found, ret %ld\n", name,
+ PTR_ERR(mtd));
+
+ return mtd;
+}
+
+static uint mtd_len_to_pages(struct mtd_info *mtd, u64 len)
+{
+ do_div(len, mtd->writesize);
+
+ return len;
+}
+
+static bool mtd_is_aligned_with_min_io_size(struct mtd_info *mtd, u64 size)
+{
+ return !do_div(size, mtd->writesize);
+}
+
+static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size)
+{
+ return !do_div(size, mtd->erasesize);
+}
+
+static void mtd_dump_buf(const u8 *buf, uint len, uint offset)
+{
+ int i, j;
+
+ for (i = 0; i < len; ) {
+ printf("0x%08x:\t", offset + i);
+ for (j = 0; j < 8; j++)
+ printf("%02x ", buf[i + j]);
+ printf(" ");
+ i += 8;
+ for (j = 0; j < 8; j++)
+ printf("%02x ", buf[i + j]);
+ printf("\n");
+ i += 8;
+ }
+}
+
+static void mtd_dump_device_buf(struct mtd_info *mtd, u64 start_off,
+ const u8 *buf, u64 len, bool woob)
+{
+ bool has_pages = mtd->type == MTD_NANDFLASH ||
+ mtd->type == MTD_MLCNANDFLASH;
+ int npages = mtd_len_to_pages(mtd, len);
+ uint page;
+
+ if (has_pages) {
+ for (page = 0; page < npages; page++) {
+ u64 data_off = page * mtd->writesize;
+
+ printf("\nDump %d data bytes from 0x%08llx:\n",
+ mtd->writesize, start_off + data_off);
+ mtd_dump_buf(&buf[data_off],
+ mtd->writesize, start_off + data_off);
+
+ if (woob) {
+ u64 oob_off = page * mtd->oobsize;
+
+ printf("Dump %d OOB bytes from page at 0x%08llx:\n",
+ mtd->oobsize, start_off + data_off);
+ mtd_dump_buf(&buf[len + oob_off],
+ mtd->oobsize, 0);
+ }
+ }
+ } else {
+ printf("\nDump %lld data bytes from 0x%llx:\n",
+ len, start_off);
+ mtd_dump_buf(buf, len, start_off);
+ }
+}
+
+static void mtd_show_parts(struct mtd_info *mtd, int level)
+{
+ struct mtd_info *part;
+ int i;
+
+ list_for_each_entry(part, &mtd->partitions, node) {
+ for (i = 0; i < level; i++)
+ printf("\t");
+ printf(" - 0x%012llx-0x%012llx : \"%s\"\n",
+ part->offset, part->offset + part->size, part->name);
+
+ mtd_show_parts(part, level + 1);
+ }
+}
+
+static void mtd_show_device(struct mtd_info *mtd)
+{
+ /* Device */
+ printf("* %s\n", mtd->name);
+#if defined(CONFIG_DM)
+ if (mtd->dev) {
+ printf(" - device: %s\n", mtd->dev->name);
+ printf(" - parent: %s\n", mtd->dev->parent->name);
+ printf(" - driver: %s\n", mtd->dev->driver->name);
+ }
+#endif
+
+ /* MTD device information */
+ printf(" - type: ");
+ switch (mtd->type) {
+ case MTD_RAM:
+ printf("RAM\n");
+ break;
+ case MTD_ROM:
+ printf("ROM\n");
+ break;
+ case MTD_NORFLASH:
+ printf("NOR flash\n");
+ break;
+ case MTD_NANDFLASH:
+ printf("NAND flash\n");
+ break;
+ case MTD_DATAFLASH:
+ printf("Data flash\n");
+ break;
+ case MTD_UBIVOLUME:
+ printf("UBI volume\n");
+ break;
+ case MTD_MLCNANDFLASH:
+ printf("MLC NAND flash\n");
+ break;
+ case MTD_ABSENT:
+ default:
+ printf("Unknown\n");
+ break;
+ }
+
+ printf(" - block size: 0x%x bytes\n", mtd->erasesize);
+ printf(" - min I/O: 0x%x bytes\n", mtd->writesize);
+
+ if (mtd->oobsize) {
+ printf(" - OOB size: %u bytes\n", mtd->oobsize);
+ printf(" - OOB available: %u bytes\n", mtd->oobavail);
+ }
+
+ if (mtd->ecc_strength) {
+ printf(" - ECC strength: %u bits\n", mtd->ecc_strength);
+ printf(" - ECC step size: %u bytes\n", mtd->ecc_step_size);
+ printf(" - bitflip threshold: %u bits\n",
+ mtd->bitflip_threshold);
+ }
+
+ printf(" - 0x%012llx-0x%012llx : \"%s\"\n",
+ mtd->offset, mtd->offset + mtd->size, mtd->name);
+
+ /* MTD partitions, if any */
+ mtd_show_parts(mtd, 1);
+}
+
+/* Logic taken from fs/ubifs/recovery.c:is_empty() */
+static bool mtd_oob_write_is_empty(struct mtd_oob_ops *op)
+{
+ int i;
+
+ for (i = 0; i < op->len; i++)
+ if (op->datbuf[i] != 0xff)
+ return false;
+
+ for (i = 0; i < op->ooblen; i++)
+ if (op->oobbuf[i] != 0xff)
+ return false;
+
+ return true;
+}
+
+static int do_mtd_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct mtd_info *mtd;
+ int dev_nb = 0;
+
+ /* Ensure all devices (and their partitions) are probed */
+ mtd_probe_devices();
+
+ printf("List of MTD devices:\n");
+ mtd_for_each_device(mtd) {
+ if (!mtd_is_partition(mtd))
+ mtd_show_device(mtd);
+
+ dev_nb++;
+ }
+
+ if (!dev_nb) {
+ printf("No MTD device found\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int mtd_special_write_oob(struct mtd_info *mtd, u64 off,
+ struct mtd_oob_ops *io_op,
+ bool write_empty_pages, bool woob)
+{
+ int ret = 0;
+
+ /*
+ * By default, do not write an empty page.
+ * Skip it by simulating a successful write.
+ */
+ if (!write_empty_pages && mtd_oob_write_is_empty(io_op)) {
+ io_op->retlen = mtd->writesize;
+ io_op->oobretlen = woob ? mtd->oobsize : 0;
+ } else {
+ ret = mtd_write_oob(mtd, off, io_op);
+ }
+
+ return ret;
+}
+
+static int do_mtd_io(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bool dump, read, raw, woob, write_empty_pages, has_pages = false;
+ u64 start_off, off, len, remaining, default_len;
+ struct mtd_oob_ops io_op = {};
+ uint user_addr = 0, npages;
+ const char *cmd = argv[0];
+ struct mtd_info *mtd;
+ u32 oob_len;
+ u8 *buf;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ mtd = get_mtd_by_name(argv[1]);
+ if (IS_ERR_OR_NULL(mtd))
+ return CMD_RET_FAILURE;
+
+ if (mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH)
+ has_pages = true;
+
+ dump = !strncmp(cmd, "dump", 4);
+ read = dump || !strncmp(cmd, "read", 4);
+ raw = strstr(cmd, ".raw");
+ woob = strstr(cmd, ".oob");
+ write_empty_pages = !has_pages || strstr(cmd, ".dontskipff");
+
+ argc -= 2;
+ argv += 2;
+
+ if (!dump) {
+ if (!argc) {
+ ret = CMD_RET_USAGE;
+ goto out_put_mtd;
+ }
+
+ user_addr = simple_strtoul(argv[0], NULL, 16);
+ argc--;
+ argv++;
+ }
+
+ start_off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
+ if (!mtd_is_aligned_with_min_io_size(mtd, start_off)) {
+ printf("Offset not aligned with a page (0x%x)\n",
+ mtd->writesize);
+ ret = CMD_RET_FAILURE;
+ goto out_put_mtd;
+ }
+
+ default_len = dump ? mtd->writesize : mtd->size;
+ len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : default_len;
+ if (!mtd_is_aligned_with_min_io_size(mtd, len)) {
+ len = round_up(len, mtd->writesize);
+ printf("Size not on a page boundary (0x%x), rounding to 0x%llx\n",
+ mtd->writesize, len);
+ }
+
+ remaining = len;
+ npages = mtd_len_to_pages(mtd, len);
+ oob_len = woob ? npages * mtd->oobsize : 0;
+
+ if (dump)
+ buf = kmalloc(len + oob_len, GFP_KERNEL);
+ else
+ buf = map_sysmem(user_addr, 0);
+
+ if (!buf) {
+ printf("Could not map/allocate the user buffer\n");
+ ret = CMD_RET_FAILURE;
+ goto out_put_mtd;
+ }
+
+ if (has_pages)
+ printf("%s %lld byte(s) (%d page(s)) at offset 0x%08llx%s%s%s\n",
+ read ? "Reading" : "Writing", len, npages, start_off,
+ raw ? " [raw]" : "", woob ? " [oob]" : "",
+ !read && write_empty_pages ? " [dontskipff]" : "");
+ else
+ printf("%s %lld byte(s) at offset 0x%08llx\n",
+ read ? "Reading" : "Writing", len, start_off);
+
+ io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_AUTO_OOB;
+ io_op.len = has_pages ? mtd->writesize : len;
+ io_op.ooblen = woob ? mtd->oobsize : 0;
+ io_op.datbuf = buf;
+ io_op.oobbuf = woob ? &buf[len] : NULL;
+
+ /* Search for the first good block after the given offset */
+ off = start_off;
+ while (mtd_block_isbad(mtd, off))
+ off += mtd->erasesize;
+
+ /* Loop over the pages to do the actual read/write */
+ while (remaining) {
+ /* Skip the block if it is bad */
+ if (mtd_is_aligned_with_block_size(mtd, off) &&
+ mtd_block_isbad(mtd, off)) {
+ off += mtd->erasesize;
+ continue;
+ }
+
+ if (read)
+ ret = mtd_read_oob(mtd, off, &io_op);
+ else
+ ret = mtd_special_write_oob(mtd, off, &io_op,
+ write_empty_pages, woob);
+
+ if (ret) {
+ printf("Failure while %s at offset 0x%llx\n",
+ read ? "reading" : "writing", off);
+ break;
+ }
+
+ off += io_op.retlen;
+ remaining -= io_op.retlen;
+ io_op.datbuf += io_op.retlen;
+ io_op.oobbuf += io_op.oobretlen;
+ }
+
+ if (!ret && dump)
+ mtd_dump_device_buf(mtd, start_off, buf, len, woob);
+
+ if (dump)
+ kfree(buf);
+ else
+ unmap_sysmem(buf);
+
+ if (ret) {
+ printf("%s on %s failed with error %d\n",
+ read ? "Read" : "Write", mtd->name, ret);
+ ret = CMD_RET_FAILURE;
+ } else {
+ ret = CMD_RET_SUCCESS;
+ }
+
+out_put_mtd:
+ put_mtd_device(mtd);
+
+ return ret;
+}
+
+static int do_mtd_erase(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct erase_info erase_op = {};
+ struct mtd_info *mtd;
+ u64 off, len;
+ bool scrub;
+ int ret = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ mtd = get_mtd_by_name(argv[1]);
+ if (IS_ERR_OR_NULL(mtd))
+ return CMD_RET_FAILURE;
+
+ scrub = strstr(argv[0], ".dontskipbad");
+
+ argc -= 2;
+ argv += 2;
+
+ off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0;
+ len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : mtd->size;
+
+ if (!mtd_is_aligned_with_block_size(mtd, off)) {
+ printf("Offset not aligned with a block (0x%x)\n",
+ mtd->erasesize);
+ ret = CMD_RET_FAILURE;
+ goto out_put_mtd;
+ }
+
+ if (!mtd_is_aligned_with_block_size(mtd, len)) {
+ printf("Size not a multiple of a block (0x%x)\n",
+ mtd->erasesize);
+ ret = CMD_RET_FAILURE;
+ goto out_put_mtd;
+ }
+
+ printf("Erasing 0x%08llx ... 0x%08llx (%d eraseblock(s))\n",
+ off, off + len - 1, mtd_div_by_eb(len, mtd));
+
+ erase_op.mtd = mtd;
+ erase_op.addr = off;
+ erase_op.len = mtd->erasesize;
+ erase_op.scrub = scrub;
+
+ while (len) {
+ ret = mtd_erase(mtd, &erase_op);
+
+ if (ret) {
+ /* Abort if its not a bad block error */
+ if (ret != -EIO)
+ break;
+ printf("Skipping bad block at 0x%08llx\n",
+ erase_op.addr);
+ }
+
+ len -= mtd->erasesize;
+ erase_op.addr += mtd->erasesize;
+ }
+
+ if (ret && ret != -EIO)
+ ret = CMD_RET_FAILURE;
+ else
+ ret = CMD_RET_SUCCESS;
+
+out_put_mtd:
+ put_mtd_device(mtd);
+
+ return ret;
+}
+
+static int do_mtd_bad(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct mtd_info *mtd;
+ loff_t off;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ mtd = get_mtd_by_name(argv[1]);
+ if (IS_ERR_OR_NULL(mtd))
+ return CMD_RET_FAILURE;
+
+ if (!mtd_can_have_bb(mtd)) {
+ printf("Only NAND-based devices can have bad blocks\n");
+ goto out_put_mtd;
+ }
+
+ printf("MTD device %s bad blocks list:\n", mtd->name);
+ for (off = 0; off < mtd->size; off += mtd->erasesize) {
+ if (mtd_block_isbad(mtd, off))
+ printf("\t0x%08llx\n", off);
+ }
+
+out_put_mtd:
+ put_mtd_device(mtd);
+
+ return CMD_RET_SUCCESS;
+}
+
+#ifdef CONFIG_AUTO_COMPLETE
+static int mtd_name_complete(int argc, char *const argv[], char last_char,
+ int maxv, char *cmdv[])
+{
+ int len = 0, n_found = 0;
+ struct mtd_info *mtd;
+
+ argc--;
+ argv++;
+
+ if (argc > 1 ||
+ (argc == 1 && (last_char == '\0' || isblank(last_char))))
+ return 0;
+
+ if (argc)
+ len = strlen(argv[0]);
+
+ mtd_for_each_device(mtd) {
+ if (argc &&
+ (len > strlen(mtd->name) ||
+ strncmp(argv[0], mtd->name, len)))
+ continue;
+
+ if (n_found >= maxv - 2) {
+ cmdv[n_found++] = "...";
+ break;
+ }
+
+ cmdv[n_found++] = mtd->name;
+ }
+
+ cmdv[n_found] = NULL;
+
+ return n_found;
+}
+#endif /* CONFIG_AUTO_COMPLETE */
+
+#ifdef CONFIG_SYS_LONGHELP
+static char mtd_help_text[] =
+ "- generic operations on memory technology devices\n\n"
+ "mtd list\n"
+ "mtd read[.raw][.oob] <name> <addr> [<off> [<size>]]\n"
+ "mtd dump[.raw][.oob] <name> [<off> [<size>]]\n"
+ "mtd write[.raw][.oob][.dontskipff] <name> <addr> [<off> [<size>]]\n"
+ "mtd erase[.dontskipbad] <name> [<off> [<size>]]\n"
+ "\n"
+ "Specific functions:\n"
+ "mtd bad <name>\n"
+ "\n"
+ "With:\n"
+ "\t<name>: NAND partition/chip name\n"
+ "\t<addr>: user address from/to which data will be retrieved/stored\n"
+ "\t<off>: offset in <name> in bytes (default: start of the part)\n"
+ "\t\t* must be block-aligned for erase\n"
+ "\t\t* must be page-aligned otherwise\n"
+ "\t<size>: length of the operation in bytes (default: the entire device)\n"
+ "\t\t* must be a multiple of a block for erase\n"
+ "\t\t* must be a multiple of a page otherwise (special case: default is a page with dump)\n"
+ "\n"
+ "The .dontskipff option forces writing empty pages, don't use it if unsure.\n";
+#endif
+
+U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
+ U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list),
+ U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io,
+ mtd_name_complete),
+ U_BOOT_SUBCMD_MKENT_COMPLETE(write, 5, 0, do_mtd_io,
+ mtd_name_complete),
+ U_BOOT_SUBCMD_MKENT_COMPLETE(dump, 4, 0, do_mtd_io,
+ mtd_name_complete),
+ U_BOOT_SUBCMD_MKENT_COMPLETE(erase, 4, 0, do_mtd_erase,
+ mtd_name_complete),
+ U_BOOT_SUBCMD_MKENT_COMPLETE(bad, 2, 1, do_mtd_bad,
+ mtd_name_complete));
diff --git a/roms/u-boot/cmd/mtdparts.c b/roms/u-boot/cmd/mtdparts.c
new file mode 100644
index 000000000..ed373a8c4
--- /dev/null
+++ b/roms/u-boot/cmd/mtdparts.c
@@ -0,0 +1,2135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>
+ *
+ * (C) Copyright 2003
+ * Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.de>
+ *
+ * (C) Copyright 2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Added support for reading flash partition table from environment.
+ * Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4
+ * kernel tree.
+ *
+ * (C) Copyright 2008
+ * Harald Welte, OpenMoko, Inc., Harald Welte <laforge@openmoko.org>
+ *
+ * $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $
+ * Copyright 2002 SYSGO Real-Time Solutions GmbH
+ */
+
+/*
+ * Three environment variables are used by the parsing routines:
+ *
+ * 'partition' - keeps current partition identifier
+ *
+ * partition := <part-id>
+ * <part-id> := <dev-id>,part_num
+ *
+ *
+ * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping
+ *
+ * mtdids=<idmap>[,<idmap>,...]
+ *
+ * <idmap> := <dev-id>=<mtd-id>
+ * <dev-id> := 'nand'|'nor'|'onenand'|'spi-nand'<dev-num>
+ * <dev-num> := mtd device number, 0...
+ * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)
+ *
+ *
+ * 'mtdparts' - partition list
+ *
+ * mtdparts=[mtdparts=]<mtd-def>[;<mtd-def>...]
+ *
+ * <mtd-def> := <mtd-id>:<part-def>[,<part-def>...]
+ * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)
+ * <part-def> := <size>[@<offset>][<name>][<ro-flag>]
+ * <size> := standard linux memsize OR '-' to denote all remaining space
+ * <offset> := partition start offset within the device
+ * <name> := '(' NAME ')'
+ * <ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)
+ *
+ * Notes:
+ * - each <mtd-id> used in mtdparts must albo exist in 'mtddis' mapping
+ * - if the above variables are not set defaults for a given target are used
+ *
+ * Examples:
+ *
+ * 1 NOR Flash, with 1 single writable partition:
+ * mtdids=nor0=edb7312-nor
+ * mtdparts=[mtdparts=]edb7312-nor:-
+ *
+ * 1 NOR Flash with 2 partitions, 1 NAND with one
+ * mtdids=nor0=edb7312-nor,nand0=edb7312-nand
+ * mtdparts=[mtdparts=]edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+#include <jffs2/load_kernel.h>
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+
+#if defined(CONFIG_CMD_NAND)
+#include <linux/mtd/rawnand.h>
+#include <nand.h>
+#endif
+
+#if defined(CONFIG_CMD_ONENAND)
+#include <linux/mtd/onenand.h>
+#include <onenand_uboot.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* special size referring to all the remaining space in a partition */
+#define SIZE_REMAINING (~0llu)
+
+/* special offset value, it is used when not provided by user
+ *
+ * this value is used temporarily during parsing, later such offests
+ * are recalculated */
+#define OFFSET_NOT_SPECIFIED (~0llu)
+
+/* minimum partition size */
+#define MIN_PART_SIZE 4096
+
+/* this flag needs to be set in part_info struct mask_flags
+ * field for read-only partitions */
+#define MTD_WRITEABLE_CMD 1
+
+/* default values for mtdids and mtdparts variables */
+#if !defined(MTDIDS_DEFAULT)
+#ifdef CONFIG_MTDIDS_DEFAULT
+#define MTDIDS_DEFAULT CONFIG_MTDIDS_DEFAULT
+#else
+#define MTDIDS_DEFAULT NULL
+#endif
+#endif
+#if !defined(MTDPARTS_DEFAULT)
+#ifdef CONFIG_MTDPARTS_DEFAULT
+#define MTDPARTS_DEFAULT CONFIG_MTDPARTS_DEFAULT
+#else
+#define MTDPARTS_DEFAULT NULL
+#endif
+#endif
+#if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
+extern void board_mtdparts_default(const char **mtdids, const char **mtdparts);
+#endif
+static const char *mtdids_default = MTDIDS_DEFAULT;
+static const char *mtdparts_default = MTDPARTS_DEFAULT;
+
+/* copies of last seen 'mtdids', 'mtdparts' and 'partition' env variables */
+#define MTDIDS_MAXLEN 128
+#define MTDPARTS_MAXLEN 512
+#define PARTITION_MAXLEN 16
+static char last_ids[MTDIDS_MAXLEN + 1];
+static char last_parts[MTDPARTS_MAXLEN + 1];
+static char last_partition[PARTITION_MAXLEN + 1];
+
+/* low level jffs2 cache cleaning routine */
+extern void jffs2_free_cache(struct part_info *part);
+
+/* mtdids mapping list, filled by parse_ids() */
+static struct list_head mtdids;
+
+/* device/partition list, parse_cmdline() parses into here */
+static struct list_head devices;
+
+/* current active device and partition number */
+struct mtd_device *current_mtd_dev = NULL;
+u8 current_mtd_partnum = 0;
+
+u8 use_defaults;
+
+static struct part_info* mtd_part_info(struct mtd_device *dev, unsigned int part_num);
+
+/* command line only routines */
+static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_len);
+static int device_del(struct mtd_device *dev);
+
+/**
+ * Parses a string into a number. The number stored at ptr is
+ * potentially suffixed with K (for kilobytes, or 1024 bytes),
+ * M (for megabytes, or 1048576 bytes), or G (for gigabytes, or
+ * 1073741824). If the number is suffixed with K, M, or G, then
+ * the return value is the number multiplied by one kilobyte, one
+ * megabyte, or one gigabyte, respectively.
+ *
+ * @param ptr where parse begins
+ * @param retptr output pointer to next char after parse completes (output)
+ * @return resulting unsigned int
+ */
+static u64 memsize_parse (const char *const ptr, const char **retptr)
+{
+ u64 ret = simple_strtoull(ptr, (char **)retptr, 0);
+
+ switch (**retptr) {
+ case 'G':
+ case 'g':
+ ret <<= 10;
+ /* Fallthrough */
+ case 'M':
+ case 'm':
+ ret <<= 10;
+ /* Fallthrough */
+ case 'K':
+ case 'k':
+ ret <<= 10;
+ (*retptr)++;
+ /* Fallthrough */
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Format string describing supplied size. This routine does the opposite job
+ * to memsize_parse(). Size in bytes is converted to string and if possible
+ * shortened by using k (kilobytes), m (megabytes) or g (gigabytes) suffix.
+ *
+ * Note, that this routine does not check for buffer overflow, it's the caller
+ * who must assure enough space.
+ *
+ * @param buf output buffer
+ * @param size size to be converted to string
+ */
+static void memsize_format(char *buf, u64 size)
+{
+#define SIZE_GB ((u32)1024*1024*1024)
+#define SIZE_MB ((u32)1024*1024)
+#define SIZE_KB ((u32)1024)
+
+ if ((size % SIZE_GB) == 0)
+ sprintf(buf, "%llug", size/SIZE_GB);
+ else if ((size % SIZE_MB) == 0)
+ sprintf(buf, "%llum", size/SIZE_MB);
+ else if (size % SIZE_KB == 0)
+ sprintf(buf, "%lluk", size/SIZE_KB);
+ else
+ sprintf(buf, "%llu", size);
+}
+
+/**
+ * This routine does global indexing of all partitions. Resulting index for
+ * current partition is saved in 'mtddevnum'. Current partition name in
+ * 'mtddevname'.
+ */
+static void index_partitions(void)
+{
+ u16 mtddevnum;
+ struct part_info *part;
+ struct list_head *dentry;
+ struct mtd_device *dev;
+
+ debug("--- index partitions ---\n");
+
+ if (current_mtd_dev) {
+ mtddevnum = 0;
+ list_for_each(dentry, &devices) {
+ dev = list_entry(dentry, struct mtd_device, link);
+ if (dev == current_mtd_dev) {
+ mtddevnum += current_mtd_partnum;
+ env_set_ulong("mtddevnum", mtddevnum);
+ debug("=> mtddevnum %d,\n", mtddevnum);
+ break;
+ }
+ mtddevnum += dev->num_parts;
+ }
+
+ part = mtd_part_info(current_mtd_dev, current_mtd_partnum);
+ if (part) {
+ env_set("mtddevname", part->name);
+
+ debug("=> mtddevname %s\n", part->name);
+ } else {
+ env_set("mtddevname", NULL);
+
+ debug("=> mtddevname NULL\n");
+ }
+ } else {
+ env_set("mtddevnum", NULL);
+ env_set("mtddevname", NULL);
+
+ debug("=> mtddevnum NULL\n=> mtddevname NULL\n");
+ }
+}
+
+/**
+ * Save current device and partition in environment variable 'partition'.
+ */
+static void current_save(void)
+{
+ char buf[16];
+
+ debug("--- current_save ---\n");
+
+ if (current_mtd_dev) {
+ sprintf(buf, "%s%d,%d", MTD_DEV_TYPE(current_mtd_dev->id->type),
+ current_mtd_dev->id->num, current_mtd_partnum);
+
+ env_set("partition", buf);
+ strncpy(last_partition, buf, 16);
+
+ debug("=> partition %s\n", buf);
+ } else {
+ env_set("partition", NULL);
+ last_partition[0] = '\0';
+
+ debug("=> partition NULL\n");
+ }
+ index_partitions();
+}
+
+
+/**
+ * Produce a mtd_info given a type and num.
+ *
+ * @param type mtd type
+ * @param num mtd number
+ * @param mtd a pointer to an mtd_info instance (output)
+ * @return 0 if device is valid, 1 otherwise
+ */
+static int get_mtd_info(u8 type, u8 num, struct mtd_info **mtd)
+{
+ char mtd_dev[16];
+
+ sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(type), num);
+ *mtd = get_mtd_device_nm(mtd_dev);
+ if (IS_ERR(*mtd)) {
+ printf("Device %s not found!\n", mtd_dev);
+ return 1;
+ }
+ put_mtd_device(*mtd);
+
+ return 0;
+}
+
+/**
+ * Performs sanity check for supplied flash partition.
+ * Table of existing MTD flash devices is searched and partition device
+ * is located. Alignment with the granularity of nand erasesize is verified.
+ *
+ * @param id of the parent device
+ * @param part partition to validate
+ * @return 0 if partition is valid, 1 otherwise
+ */
+static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
+{
+ struct mtd_info *mtd = NULL;
+ int i, j;
+ ulong start;
+ u64 offset, size;
+
+ if (get_mtd_info(id->type, id->num, &mtd))
+ return 1;
+
+ part->sector_size = mtd->erasesize;
+
+ if (!mtd->numeraseregions) {
+ /*
+ * Only one eraseregion (NAND, SPI-NAND, OneNAND or uniform NOR),
+ * checking for alignment is easy here
+ */
+ offset = part->offset;
+ if (do_div(offset, mtd->erasesize)) {
+ printf("%s%d: partition (%s) start offset"
+ "alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
+
+ size = part->size;
+ if (do_div(size, mtd->erasesize)) {
+ printf("%s%d: partition (%s) size alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
+ } else {
+ /*
+ * Multiple eraseregions (non-uniform NOR),
+ * checking for alignment is more complex here
+ */
+
+ /* Check start alignment */
+ for (i = 0; i < mtd->numeraseregions; i++) {
+ start = mtd->eraseregions[i].offset;
+ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
+ if (part->offset == start)
+ goto start_ok;
+ start += mtd->eraseregions[i].erasesize;
+ }
+ }
+
+ printf("%s%d: partition (%s) start offset alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+
+ start_ok:
+
+ /* Check end/size alignment */
+ for (i = 0; i < mtd->numeraseregions; i++) {
+ start = mtd->eraseregions[i].offset;
+ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) {
+ if ((part->offset + part->size) == start)
+ goto end_ok;
+ start += mtd->eraseregions[i].erasesize;
+ }
+ }
+ /* Check last sector alignment */
+ if ((part->offset + part->size) == start)
+ goto end_ok;
+
+ printf("%s%d: partition (%s) size alignment incorrect\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+
+ end_ok:
+ return 0;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Performs sanity check for supplied partition. Offset and size are
+ * verified to be within valid range. Partition type is checked and
+ * part_validate_eraseblock() is called with the argument of part.
+ *
+ * @param id of the parent device
+ * @param part partition to validate
+ * @return 0 if partition is valid, 1 otherwise
+ */
+static int part_validate(struct mtdids *id, struct part_info *part)
+{
+ if (part->size == SIZE_REMAINING)
+ part->size = id->size - part->offset;
+
+ if (part->offset > id->size) {
+ printf("%s: offset %08llx beyond flash size %08llx\n",
+ id->mtd_id, part->offset, id->size);
+ return 1;
+ }
+
+ if ((part->offset + part->size) <= part->offset) {
+ printf("%s%d: partition (%s) size too big\n",
+ MTD_DEV_TYPE(id->type), id->num, part->name);
+ return 1;
+ }
+
+ if (part->offset + part->size > id->size) {
+ printf("%s: partitioning exceeds flash size\n", id->mtd_id);
+ return 1;
+ }
+
+ /*
+ * Now we need to check if the partition starts and ends on
+ * sector (eraseblock) regions
+ */
+ return part_validate_eraseblock(id, part);
+}
+
+/**
+ * Delete selected partition from the partition list of the specified device.
+ *
+ * @param dev device to delete partition from
+ * @param part partition to delete
+ * @return 0 on success, 1 otherwise
+ */
+static int part_del(struct mtd_device *dev, struct part_info *part)
+{
+ u8 current_save_needed = 0;
+
+ /* if there is only one partition, remove whole device */
+ if (dev->num_parts == 1)
+ return device_del(dev);
+
+ /* otherwise just delete this partition */
+
+ if (dev == current_mtd_dev) {
+ /* we are modyfing partitions for the current device,
+ * update current */
+ struct part_info *curr_pi;
+ curr_pi = mtd_part_info(current_mtd_dev, current_mtd_partnum);
+
+ if (curr_pi) {
+ if (curr_pi == part) {
+ printf("current partition deleted, resetting current to 0\n");
+ current_mtd_partnum = 0;
+ } else if (part->offset <= curr_pi->offset) {
+ current_mtd_partnum--;
+ }
+ current_save_needed = 1;
+ }
+ }
+
+ list_del(&part->link);
+ free(part);
+ dev->num_parts--;
+
+ if (current_save_needed > 0)
+ current_save();
+ else
+ index_partitions();
+
+ return 0;
+}
+
+/**
+ * Delete all partitions from parts head list, free memory.
+ *
+ * @param head list of partitions to delete
+ */
+static void part_delall(struct list_head *head)
+{
+ struct list_head *entry, *n;
+ struct part_info *part_tmp;
+
+ /* clean tmp_list and free allocated memory */
+ list_for_each_safe(entry, n, head) {
+ part_tmp = list_entry(entry, struct part_info, link);
+
+ list_del(entry);
+ free(part_tmp);
+ }
+}
+
+/**
+ * Add new partition to the supplied partition list. Make sure partitions are
+ * sorted by offset in ascending order.
+ *
+ * @param head list this partition is to be added to
+ * @param new partition to be added
+ */
+static int part_sort_add(struct mtd_device *dev, struct part_info *part)
+{
+ struct list_head *entry;
+ struct part_info *new_pi, *curr_pi;
+
+ /* link partition to parrent dev */
+ part->dev = dev;
+
+ if (list_empty(&dev->parts)) {
+ debug("part_sort_add: list empty\n");
+ list_add(&part->link, &dev->parts);
+ dev->num_parts++;
+ index_partitions();
+ return 0;
+ }
+
+ new_pi = list_entry(&part->link, struct part_info, link);
+
+ /* get current partition info if we are updating current device */
+ curr_pi = NULL;
+ if (dev == current_mtd_dev)
+ curr_pi = mtd_part_info(current_mtd_dev, current_mtd_partnum);
+
+ list_for_each(entry, &dev->parts) {
+ struct part_info *pi;
+
+ pi = list_entry(entry, struct part_info, link);
+
+ /* be compliant with kernel cmdline, allow only one partition at offset zero */
+ if ((new_pi->offset == pi->offset) && (pi->offset == 0)) {
+ printf("cannot add second partition at offset 0\n");
+ return 1;
+ }
+
+ if (new_pi->offset <= pi->offset) {
+ list_add_tail(&part->link, entry);
+ dev->num_parts++;
+
+ if (curr_pi && (pi->offset <= curr_pi->offset)) {
+ /* we are modyfing partitions for the current
+ * device, update current */
+ current_mtd_partnum++;
+ current_save();
+ } else {
+ index_partitions();
+ }
+ return 0;
+ }
+ }
+
+ list_add_tail(&part->link, &dev->parts);
+ dev->num_parts++;
+ index_partitions();
+ return 0;
+}
+
+/**
+ * Add provided partition to the partition list of a given device.
+ *
+ * @param dev device to which partition is added
+ * @param part partition to be added
+ * @return 0 on success, 1 otherwise
+ */
+static int part_add(struct mtd_device *dev, struct part_info *part)
+{
+ /* verify alignment and size */
+ if (part_validate(dev->id, part) != 0)
+ return 1;
+
+ /* partition is ok, add it to the list */
+ if (part_sort_add(dev, part) != 0)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Parse one partition definition, allocate memory and return pointer to this
+ * location in retpart.
+ *
+ * @param partdef pointer to the partition definition string i.e. <part-def>
+ * @param ret output pointer to next char after parse completes (output)
+ * @param retpart pointer to the allocated partition (output)
+ * @return 0 on success, 1 otherwise
+ */
+static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart)
+{
+ struct part_info *part;
+ u64 size;
+ u64 offset;
+ const char *name;
+ int name_len;
+ unsigned int mask_flags;
+ const char *p;
+
+ p = partdef;
+ *retpart = NULL;
+ *ret = NULL;
+
+ /* fetch the partition size */
+ if (*p == '-') {
+ /* assign all remaining space to this partition */
+ debug("'-': remaining size assigned\n");
+ size = SIZE_REMAINING;
+ p++;
+ } else {
+ size = memsize_parse(p, &p);
+ if (size < MIN_PART_SIZE) {
+ printf("partition size too small (%llx)\n", size);
+ return 1;
+ }
+ }
+
+ /* check for offset */
+ offset = OFFSET_NOT_SPECIFIED;
+ if (*p == '@') {
+ p++;
+ offset = memsize_parse(p, &p);
+ }
+
+ /* now look for the name */
+ if (*p == '(') {
+ name = ++p;
+ if ((p = strchr(name, ')')) == NULL) {
+ printf("no closing ) found in partition name\n");
+ return 1;
+ }
+ name_len = p - name + 1;
+ if ((name_len - 1) == 0) {
+ printf("empty partition name\n");
+ return 1;
+ }
+ p++;
+ } else {
+ /* 0x00000000@0x00000000 */
+ name_len = 22;
+ name = NULL;
+ }
+
+ /* test for options */
+ mask_flags = 0;
+ if (strncmp(p, "ro", 2) == 0) {
+ mask_flags |= MTD_WRITEABLE_CMD;
+ p += 2;
+ }
+
+ /* check for next partition definition */
+ if (*p == ',') {
+ if (size == SIZE_REMAINING) {
+ *ret = NULL;
+ printf("no partitions allowed after a fill-up partition\n");
+ return 1;
+ }
+ *ret = ++p;
+ } else if ((*p == ';') || (*p == '\0')) {
+ *ret = p;
+ } else {
+ printf("unexpected character '%c' at the end of partition\n", *p);
+ *ret = NULL;
+ return 1;
+ }
+
+ /* allocate memory */
+ part = (struct part_info *)malloc(sizeof(struct part_info) + name_len);
+ if (!part) {
+ printf("out of memory\n");
+ return 1;
+ }
+ memset(part, 0, sizeof(struct part_info) + name_len);
+ part->size = size;
+ part->offset = offset;
+ part->mask_flags = mask_flags;
+ part->name = (char *)(part + 1);
+
+ if (name) {
+ /* copy user provided name */
+ strncpy(part->name, name, name_len - 1);
+ part->auto_name = 0;
+ } else {
+ /* auto generated name in form of size@offset */
+ snprintf(part->name, name_len, "0x%08llx@0x%08llx", size, offset);
+ part->auto_name = 1;
+ }
+
+ part->name[name_len - 1] = '\0';
+ INIT_LIST_HEAD(&part->link);
+
+ debug("+ partition: name %-22s size 0x%08llx offset 0x%08llx mask flags %d\n",
+ part->name, part->size,
+ part->offset, part->mask_flags);
+
+ *retpart = part;
+ return 0;
+}
+
+/**
+ * Check device number to be within valid range for given device type.
+ *
+ * @param type mtd type
+ * @param num mtd number
+ * @param size a pointer to the size of the mtd device (output)
+ * @return 0 if device is valid, 1 otherwise
+ */
+static int mtd_device_validate(u8 type, u8 num, u64 *size)
+{
+ struct mtd_info *mtd = NULL;
+
+ if (get_mtd_info(type, num, &mtd))
+ return 1;
+
+ *size = mtd->size;
+
+ return 0;
+}
+
+/**
+ * Delete all mtd devices from a supplied devices list, free memory allocated for
+ * each device and delete all device partitions.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+static int device_delall(struct list_head *head)
+{
+ struct list_head *entry, *n;
+ struct mtd_device *dev_tmp;
+
+ /* clean devices list */
+ list_for_each_safe(entry, n, head) {
+ dev_tmp = list_entry(entry, struct mtd_device, link);
+ list_del(entry);
+ part_delall(&dev_tmp->parts);
+ free(dev_tmp);
+ }
+ INIT_LIST_HEAD(&devices);
+
+ return 0;
+}
+
+/**
+ * If provided device exists it's partitions are deleted, device is removed
+ * from device list and device memory is freed.
+ *
+ * @param dev device to be deleted
+ * @return 0 on success, 1 otherwise
+ */
+static int device_del(struct mtd_device *dev)
+{
+ part_delall(&dev->parts);
+ list_del(&dev->link);
+ free(dev);
+
+ if (dev == current_mtd_dev) {
+ /* we just deleted current device */
+ if (list_empty(&devices)) {
+ current_mtd_dev = NULL;
+ } else {
+ /* reset first partition from first dev from the
+ * devices list as current */
+ current_mtd_dev = list_entry(devices.next, struct mtd_device, link);
+ current_mtd_partnum = 0;
+ }
+ current_save();
+ return 0;
+ }
+
+ index_partitions();
+ return 0;
+}
+
+/**
+ * Search global device list and return pointer to the device of type and num
+ * specified.
+ *
+ * @param type device type
+ * @param num device number
+ * @return NULL if requested device does not exist
+ */
+struct mtd_device *device_find(u8 type, u8 num)
+{
+ struct list_head *entry;
+ struct mtd_device *dev_tmp;
+
+ list_for_each(entry, &devices) {
+ dev_tmp = list_entry(entry, struct mtd_device, link);
+
+ if ((dev_tmp->id->type == type) && (dev_tmp->id->num == num))
+ return dev_tmp;
+ }
+
+ return NULL;
+}
+
+/**
+ * Add specified device to the global device list.
+ *
+ * @param dev device to be added
+ */
+static void device_add(struct mtd_device *dev)
+{
+ u8 current_save_needed = 0;
+
+ if (list_empty(&devices)) {
+ current_mtd_dev = dev;
+ current_mtd_partnum = 0;
+ current_save_needed = 1;
+ }
+
+ list_add_tail(&dev->link, &devices);
+
+ if (current_save_needed > 0)
+ current_save();
+ else
+ index_partitions();
+}
+
+/**
+ * Parse device type, name and mtd-id. If syntax is ok allocate memory and
+ * return pointer to the device structure.
+ *
+ * @param mtd_dev pointer to the device definition string i.e. <mtd-dev>
+ * @param ret output pointer to next char after parse completes (output)
+ * @param retdev pointer to the allocated device (output)
+ * @return 0 on success, 1 otherwise
+ */
+static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_device **retdev)
+{
+ struct mtd_device *dev;
+ struct part_info *part;
+ struct mtdids *id;
+ const char *mtd_id;
+ unsigned int mtd_id_len;
+ const char *p;
+ const char *pend;
+ LIST_HEAD(tmp_list);
+ struct list_head *entry, *n;
+ u16 num_parts;
+ u64 offset;
+ int err = 1;
+
+ debug("===device_parse===\n");
+
+ assert(retdev);
+ *retdev = NULL;
+
+ if (ret)
+ *ret = NULL;
+
+ /* fetch <mtd-id> */
+ mtd_id = p = mtd_dev;
+ if (!(p = strchr(mtd_id, ':'))) {
+ printf("no <mtd-id> identifier\n");
+ return 1;
+ }
+ mtd_id_len = p - mtd_id + 1;
+ p++;
+
+ /* verify if we have a valid device specified */
+ if ((id = id_find_by_mtd_id(mtd_id, mtd_id_len - 1)) == NULL) {
+ printf("invalid mtd device '%.*s'\n", mtd_id_len - 1, mtd_id);
+ return 1;
+ }
+
+ pend = strchr(p, ';');
+ debug("dev type = %d (%s), dev num = %d, mtd-id = %s\n",
+ id->type, MTD_DEV_TYPE(id->type),
+ id->num, id->mtd_id);
+ debug("parsing partitions %.*s\n", (int)(pend ? pend - p : strlen(p)), p);
+
+ /* parse partitions */
+ num_parts = 0;
+
+ offset = 0;
+ if ((dev = device_find(id->type, id->num)) != NULL) {
+ /* if device already exists start at the end of the last partition */
+ part = list_entry(dev->parts.prev, struct part_info, link);
+ offset = part->offset + part->size;
+ }
+
+ while (p && (*p != '\0') && (*p != ';')) {
+ err = 1;
+ if ((part_parse(p, &p, &part) != 0) || (!part))
+ break;
+
+ /* calculate offset when not specified */
+ if (part->offset == OFFSET_NOT_SPECIFIED)
+ part->offset = offset;
+ else
+ offset = part->offset;
+
+ /* verify alignment and size */
+ if (part_validate(id, part) != 0)
+ break;
+
+ offset += part->size;
+
+ /* partition is ok, add it to the list */
+ list_add_tail(&part->link, &tmp_list);
+ num_parts++;
+ err = 0;
+ }
+ if (err == 1) {
+ part_delall(&tmp_list);
+ return 1;
+ }
+
+ debug("\ntotal partitions: %d\n", num_parts);
+
+ /* check for next device presence */
+ if (p) {
+ if (*p == ';') {
+ if (ret)
+ *ret = ++p;
+ } else if (*p == '\0') {
+ if (ret)
+ *ret = p;
+ } else {
+ printf("unexpected character '%c' at the end of device\n", *p);
+ if (ret)
+ *ret = NULL;
+ return 1;
+ }
+ }
+
+ /* allocate memory for mtd_device structure */
+ if ((dev = (struct mtd_device *)malloc(sizeof(struct mtd_device))) == NULL) {
+ printf("out of memory\n");
+ return 1;
+ }
+ memset(dev, 0, sizeof(struct mtd_device));
+ dev->id = id;
+ dev->num_parts = 0; /* part_sort_add increments num_parts */
+ INIT_LIST_HEAD(&dev->parts);
+ INIT_LIST_HEAD(&dev->link);
+
+ /* move partitions from tmp_list to dev->parts */
+ list_for_each_safe(entry, n, &tmp_list) {
+ part = list_entry(entry, struct part_info, link);
+ list_del(entry);
+ if (part_sort_add(dev, part) != 0) {
+ device_del(dev);
+ return 1;
+ }
+ }
+
+ *retdev = dev;
+
+ debug("===\n\n");
+ return 0;
+}
+
+/**
+ * Initialize global device list.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+static int mtd_devices_init(void)
+{
+ last_parts[0] = '\0';
+ current_mtd_dev = NULL;
+ current_save();
+
+ return device_delall(&devices);
+}
+
+/*
+ * Search global mtdids list and find id of requested type and number.
+ *
+ * @return pointer to the id if it exists, NULL otherwise
+ */
+static struct mtdids* id_find(u8 type, u8 num)
+{
+ struct list_head *entry;
+ struct mtdids *id;
+
+ list_for_each(entry, &mtdids) {
+ id = list_entry(entry, struct mtdids, link);
+
+ if ((id->type == type) && (id->num == num))
+ return id;
+ }
+
+ return NULL;
+}
+
+/**
+ * Search global mtdids list and find id of a requested mtd_id.
+ *
+ * Note: first argument is not null terminated.
+ *
+ * @param mtd_id string containing requested mtd_id
+ * @param mtd_id_len length of supplied mtd_id
+ * @return pointer to the id if it exists, NULL otherwise
+ */
+static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_len)
+{
+ struct list_head *entry;
+ struct mtdids *id;
+
+ debug("--- id_find_by_mtd_id: '%.*s' (len = %d)\n",
+ mtd_id_len, mtd_id, mtd_id_len);
+
+ list_for_each(entry, &mtdids) {
+ id = list_entry(entry, struct mtdids, link);
+
+ debug("entry: '%s' (len = %zu)\n",
+ id->mtd_id, strlen(id->mtd_id));
+
+ if (mtd_id_len != strlen(id->mtd_id))
+ continue;
+ if (strncmp(id->mtd_id, mtd_id, mtd_id_len) == 0)
+ return id;
+ }
+
+ return NULL;
+}
+
+/**
+ * Parse device id string <dev-id> := 'nand'|'nor'|'onenand'|'spi-nand'<dev-num>,
+ * return device type and number.
+ *
+ * @param id string describing device id
+ * @param ret_id output pointer to next char after parse completes (output)
+ * @param dev_type parsed device type (output)
+ * @param dev_num parsed device number (output)
+ * @return 0 on success, 1 otherwise
+ */
+int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type,
+ u8 *dev_num)
+{
+ const char *p = id;
+
+ *dev_type = 0;
+ if (strncmp(p, "nand", 4) == 0) {
+ *dev_type = MTD_DEV_TYPE_NAND;
+ p += 4;
+ } else if (strncmp(p, "nor", 3) == 0) {
+ *dev_type = MTD_DEV_TYPE_NOR;
+ p += 3;
+ } else if (strncmp(p, "onenand", 7) == 0) {
+ *dev_type = MTD_DEV_TYPE_ONENAND;
+ p += 7;
+ } else if (strncmp(p, "spi-nand", 8) == 0) {
+ *dev_type = MTD_DEV_TYPE_SPINAND;
+ p += 8;
+ } else {
+ printf("incorrect device type in %s\n", id);
+ return 1;
+ }
+
+ if (!isdigit(*p)) {
+ printf("incorrect device number in %s\n", id);
+ return 1;
+ }
+
+ *dev_num = simple_strtoul(p, (char **)&p, 0);
+ if (ret_id)
+ *ret_id = p;
+ return 0;
+}
+
+/**
+ * Process all devices and generate corresponding mtdparts string describing
+ * all partitions on all devices.
+ *
+ * @param buf output buffer holding generated mtdparts string (output)
+ * @param buflen buffer size
+ * @return 0 on success, 1 otherwise
+ */
+static int generate_mtdparts(char *buf, u32 buflen)
+{
+ struct list_head *pentry, *dentry;
+ struct mtd_device *dev;
+ struct part_info *part, *prev_part;
+ char *p = buf;
+ char tmpbuf[32];
+ u64 size, offset;
+ u32 len, part_cnt;
+ u32 maxlen = buflen - 1;
+
+ debug("--- generate_mtdparts ---\n");
+
+ if (list_empty(&devices)) {
+ buf[0] = '\0';
+ return 0;
+ }
+
+ list_for_each(dentry, &devices) {
+ dev = list_entry(dentry, struct mtd_device, link);
+
+ /* copy mtd_id */
+ len = strlen(dev->id->mtd_id) + 1;
+ if (len > maxlen)
+ goto cleanup;
+ memcpy(p, dev->id->mtd_id, len - 1);
+ p += len - 1;
+ *(p++) = ':';
+ maxlen -= len;
+
+ /* format partitions */
+ prev_part = NULL;
+ part_cnt = 0;
+ list_for_each(pentry, &dev->parts) {
+ part = list_entry(pentry, struct part_info, link);
+ size = part->size;
+ offset = part->offset;
+ part_cnt++;
+
+ /* partition size */
+ memsize_format(tmpbuf, size);
+ len = strlen(tmpbuf);
+ if (len > maxlen)
+ goto cleanup;
+ memcpy(p, tmpbuf, len);
+ p += len;
+ maxlen -= len;
+
+
+ /* add offset only when there is a gap between
+ * partitions */
+ if ((!prev_part && (offset != 0)) ||
+ (prev_part && ((prev_part->offset + prev_part->size) != part->offset))) {
+
+ memsize_format(tmpbuf, offset);
+ len = strlen(tmpbuf) + 1;
+ if (len > maxlen)
+ goto cleanup;
+ *(p++) = '@';
+ memcpy(p, tmpbuf, len - 1);
+ p += len - 1;
+ maxlen -= len;
+ }
+
+ /* copy name only if user supplied */
+ if(!part->auto_name) {
+ len = strlen(part->name) + 2;
+ if (len > maxlen)
+ goto cleanup;
+
+ *(p++) = '(';
+ memcpy(p, part->name, len - 2);
+ p += len - 2;
+ *(p++) = ')';
+ maxlen -= len;
+ }
+
+ /* ro mask flag */
+ if (part->mask_flags && MTD_WRITEABLE_CMD) {
+ len = 2;
+ if (len > maxlen)
+ goto cleanup;
+ *(p++) = 'r';
+ *(p++) = 'o';
+ maxlen -= 2;
+ }
+
+ /* print ',' separator if there are other partitions
+ * following */
+ if (dev->num_parts > part_cnt) {
+ if (1 > maxlen)
+ goto cleanup;
+ *(p++) = ',';
+ maxlen--;
+ }
+ prev_part = part;
+ }
+ /* print ';' separator if there are other devices following */
+ if (dentry->next != &devices) {
+ if (1 > maxlen)
+ goto cleanup;
+ *(p++) = ';';
+ maxlen--;
+ }
+ }
+
+ /* we still have at least one char left, as we decremented maxlen at
+ * the begining */
+ *p = '\0';
+
+ return 0;
+
+cleanup:
+ last_parts[0] = '\0';
+ return 1;
+}
+
+/**
+ * Call generate_mtdparts to process all devices and generate corresponding
+ * mtdparts string, save it in mtdparts environment variable.
+ *
+ * @param buf output buffer holding generated mtdparts string (output)
+ * @param buflen buffer size
+ * @return 0 on success, 1 otherwise
+ */
+static int generate_mtdparts_save(char *buf, u32 buflen)
+{
+ int ret;
+
+ ret = generate_mtdparts(buf, buflen);
+
+ if ((buf[0] != '\0') && (ret == 0))
+ env_set("mtdparts", buf);
+ else
+ env_set("mtdparts", NULL);
+
+ return ret;
+}
+
+#if defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES)
+/**
+ * Get the net size (w/o bad blocks) of the given partition.
+ *
+ * @param mtd the mtd info
+ * @param part the partition
+ * @return the calculated net size of this partition
+ */
+static uint64_t net_part_size(struct mtd_info *mtd, struct part_info *part)
+{
+ uint64_t i, net_size = 0;
+
+ if (!mtd->_block_isbad)
+ return part->size;
+
+ for (i = 0; i < part->size; i += mtd->erasesize) {
+ if (!mtd->_block_isbad(mtd, part->offset + i))
+ net_size += mtd->erasesize;
+ }
+
+ return net_size;
+}
+#endif
+
+static void print_partition_table(void)
+{
+ struct list_head *dentry, *pentry;
+ struct part_info *part;
+ struct mtd_device *dev;
+ int part_num;
+
+ list_for_each(dentry, &devices) {
+ dev = list_entry(dentry, struct mtd_device, link);
+ /* list partitions for given device */
+ part_num = 0;
+#if defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES)
+ struct mtd_info *mtd;
+
+ if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+ return;
+
+ printf("\ndevice %s%d <%s>, # parts = %d\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num,
+ dev->id->mtd_id, dev->num_parts);
+ printf(" #: name\t\tsize\t\tnet size\toffset\t\tmask_flags\n");
+
+ list_for_each(pentry, &dev->parts) {
+ u32 net_size;
+ char *size_note;
+
+ part = list_entry(pentry, struct part_info, link);
+ net_size = net_part_size(mtd, part);
+ size_note = part->size == net_size ? " " : " (!)";
+ printf("%2d: %-20s0x%08llx\t0x%08x%s\t0x%08llx\t%d\n",
+ part_num, part->name, part->size,
+ net_size, size_note, part->offset,
+ part->mask_flags);
+#else /* !defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
+ printf("\ndevice %s%d <%s>, # parts = %d\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num,
+ dev->id->mtd_id, dev->num_parts);
+ printf(" #: name\t\tsize\t\toffset\t\tmask_flags\n");
+
+ list_for_each(pentry, &dev->parts) {
+ part = list_entry(pentry, struct part_info, link);
+ printf("%2d: %-20s0x%08llx\t0x%08llx\t%d\n",
+ part_num, part->name, part->size,
+ part->offset, part->mask_flags);
+#endif /* defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
+ part_num++;
+ }
+ }
+
+ if (list_empty(&devices))
+ printf("no partitions defined\n");
+}
+
+/**
+ * Format and print out a partition list for each device from global device
+ * list.
+ */
+static void list_partitions(void)
+{
+ struct part_info *part;
+
+ debug("\n---list_partitions---\n");
+ print_partition_table();
+
+ /* current_mtd_dev is not NULL only when we have non empty device list */
+ if (current_mtd_dev) {
+ part = mtd_part_info(current_mtd_dev, current_mtd_partnum);
+ if (part) {
+ printf("\nactive partition: %s%d,%d - (%s) 0x%08llx @ 0x%08llx\n",
+ MTD_DEV_TYPE(current_mtd_dev->id->type),
+ current_mtd_dev->id->num, current_mtd_partnum,
+ part->name, part->size, part->offset);
+ } else {
+ printf("could not get current partition info\n\n");
+ }
+ }
+
+ printf("\ndefaults:\n");
+ printf("mtdids : %s\n",
+ mtdids_default ? mtdids_default : "none");
+ /*
+ * Using printf() here results in printbuffer overflow
+ * if default mtdparts string is greater than console
+ * printbuffer. Use puts() to prevent system crashes.
+ */
+ puts("mtdparts: ");
+ puts(mtdparts_default ? mtdparts_default : "none");
+ puts("\n");
+}
+
+/**
+ * Given partition identifier in form of <dev_type><dev_num>,<part_num> find
+ * corresponding device and verify partition number.
+ *
+ * @param id string describing device and partition or partition name
+ * @param dev pointer to the requested device (output)
+ * @param part_num verified partition number (output)
+ * @param part pointer to requested partition (output)
+ * @return 0 on success, 1 otherwise
+ */
+int find_dev_and_part(const char *id, struct mtd_device **dev,
+ u8 *part_num, struct part_info **part)
+{
+ struct list_head *dentry, *pentry;
+ u8 type, dnum, pnum;
+ const char *p;
+
+ debug("--- find_dev_and_part ---\nid = %s\n", id);
+
+ list_for_each(dentry, &devices) {
+ *part_num = 0;
+ *dev = list_entry(dentry, struct mtd_device, link);
+ list_for_each(pentry, &(*dev)->parts) {
+ *part = list_entry(pentry, struct part_info, link);
+ if (strcmp((*part)->name, id) == 0)
+ return 0;
+ (*part_num)++;
+ }
+ }
+
+ p = id;
+ *dev = NULL;
+ *part = NULL;
+ *part_num = 0;
+
+ if (mtd_id_parse(p, &p, &type, &dnum) != 0)
+ return 1;
+
+ if ((*p++ != ',') || (*p == '\0')) {
+ printf("no partition number specified\n");
+ return 1;
+ }
+ pnum = simple_strtoul(p, (char **)&p, 0);
+ if (*p != '\0') {
+ printf("unexpected trailing character '%c'\n", *p);
+ return 1;
+ }
+
+ if ((*dev = device_find(type, dnum)) == NULL) {
+ printf("no such device %s%d\n", MTD_DEV_TYPE(type), dnum);
+ return 1;
+ }
+
+ if ((*part = mtd_part_info(*dev, pnum)) == NULL) {
+ printf("no such partition\n");
+ *dev = NULL;
+ return 1;
+ }
+
+ *part_num = pnum;
+
+ return 0;
+}
+
+/**
+ * Find and delete partition. For partition id format see find_dev_and_part().
+ *
+ * @param id string describing device and partition
+ * @return 0 on success, 1 otherwise
+ */
+static int delete_partition(const char *id)
+{
+ u8 pnum;
+ struct mtd_device *dev;
+ struct part_info *part;
+
+ if (find_dev_and_part(id, &dev, &pnum, &part) == 0) {
+
+ debug("delete_partition: device = %s%d, partition %d = (%s) 0x%08llx@0x%08llx\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum,
+ part->name, part->size, part->offset);
+
+ if (part_del(dev, part) != 0)
+ return 1;
+
+ if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+ printf("generated mtdparts too long, resetting to null\n");
+ return 1;
+ }
+ return 0;
+ }
+
+ printf("partition %s not found\n", id);
+ return 1;
+}
+
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+/**
+ * Increase the size of the given partition so that it's net size is at least
+ * as large as the size member and such that the next partition would start on a
+ * good block if it were adjacent to this partition.
+ *
+ * @param mtd the mtd device
+ * @param part the partition
+ * @param next_offset pointer to the offset of the next partition after this
+ * partition's size has been modified (output)
+ */
+static void spread_partition(struct mtd_info *mtd, struct part_info *part,
+ uint64_t *next_offset)
+{
+ uint64_t net_size, padding_size = 0;
+ int truncated;
+
+ mtd_get_len_incl_bad(mtd, part->offset, part->size, &net_size,
+ &truncated);
+
+ /*
+ * Absorb bad blocks immediately following this
+ * partition also into the partition, such that
+ * the next partition starts with a good block.
+ */
+ if (!truncated) {
+ mtd_get_len_incl_bad(mtd, part->offset + net_size,
+ mtd->erasesize, &padding_size, &truncated);
+ if (truncated)
+ padding_size = 0;
+ else
+ padding_size -= mtd->erasesize;
+ }
+
+ if (truncated) {
+ printf("truncated partition %s to %lld bytes\n", part->name,
+ (uint64_t) net_size + padding_size);
+ }
+
+ part->size = net_size + padding_size;
+ *next_offset = part->offset + part->size;
+}
+
+/**
+ * Adjust all of the partition sizes, such that all partitions are at least
+ * as big as their mtdparts environment variable sizes and they each start
+ * on a good block.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+static int spread_partitions(void)
+{
+ struct list_head *dentry, *pentry;
+ struct mtd_device *dev;
+ struct part_info *part;
+ struct mtd_info *mtd;
+ int part_num;
+ uint64_t cur_offs;
+
+ list_for_each(dentry, &devices) {
+ dev = list_entry(dentry, struct mtd_device, link);
+
+ if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+ return 1;
+
+ part_num = 0;
+ cur_offs = 0;
+ list_for_each(pentry, &dev->parts) {
+ part = list_entry(pentry, struct part_info, link);
+
+ debug("spread_partitions: device = %s%d, partition %d ="
+ " (%s) 0x%08llx@0x%08llx\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num,
+ part_num, part->name, part->size,
+ part->offset);
+
+ if (cur_offs > part->offset)
+ part->offset = cur_offs;
+
+ spread_partition(mtd, part, &cur_offs);
+
+ part_num++;
+ }
+ }
+
+ index_partitions();
+
+ if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+ printf("generated mtdparts too long, resetting to null\n");
+ return 1;
+ }
+ return 0;
+}
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
+
+/**
+ * The mtdparts variable tends to be long. If we need to access it
+ * before the env is relocated, then we need to use our own stack
+ * buffer. gd->env_buf will be too small.
+ *
+ * @param buf temporary buffer pointer MTDPARTS_MAXLEN long
+ * @return mtdparts variable string, NULL if not found
+ */
+static const char *env_get_mtdparts(char *buf)
+{
+ if (gd->flags & GD_FLG_ENV_READY)
+ return env_get("mtdparts");
+ if (env_get_f("mtdparts", buf, MTDPARTS_MAXLEN) != -1)
+ return buf;
+ return NULL;
+}
+
+/**
+ * Accept character string describing mtd partitions and call device_parse()
+ * for each entry. Add created devices to the global devices list.
+ *
+ * @param mtdparts string specifing mtd partitions
+ * @return 0 on success, 1 otherwise
+ */
+static int parse_mtdparts(const char *const mtdparts)
+{
+ const char *p;
+ struct mtd_device *dev;
+ int err = 1;
+ char tmp_parts[MTDPARTS_MAXLEN];
+
+ debug("\n---parse_mtdparts---\nmtdparts = %s\n\n", mtdparts);
+
+ /* delete all devices and partitions */
+ if (mtd_devices_init() != 0) {
+ printf("could not initialise device list\n");
+ return err;
+ }
+
+ /* re-read 'mtdparts' variable, mtd_devices_init may be updating env */
+ p = env_get_mtdparts(tmp_parts);
+ if (!p)
+ p = mtdparts;
+
+ /* Skip the useless prefix, if any */
+ if (strncmp(p, "mtdparts=", 9) == 0)
+ p += 9;
+
+ while (*p != '\0') {
+ err = 1;
+ if ((device_parse(p, &p, &dev) != 0) || (!dev))
+ break;
+
+ debug("+ device: %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+
+ /* check if parsed device is already on the list */
+ if (device_find(dev->id->type, dev->id->num) != NULL) {
+ printf("device %s%d redefined, please correct mtdparts variable\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num);
+ break;
+ }
+
+ list_add_tail(&dev->link, &devices);
+ err = 0;
+ }
+ if (err == 1) {
+ free(dev);
+ device_delall(&devices);
+ }
+
+ return err;
+}
+
+/**
+ * Parse provided string describing mtdids mapping (see file header for mtdids
+ * variable format). Allocate memory for each entry and add all found entries
+ * to the global mtdids list.
+ *
+ * @param ids mapping string
+ * @return 0 on success, 1 otherwise
+ */
+static int parse_mtdids(const char *const ids)
+{
+ const char *p = ids;
+ const char *mtd_id;
+ int mtd_id_len;
+ struct mtdids *id;
+ struct list_head *entry, *n;
+ struct mtdids *id_tmp;
+ u8 type, num;
+ u64 size;
+ int ret = 1;
+
+ debug("\n---parse_mtdids---\nmtdids = %s\n\n", ids);
+
+ /* clean global mtdids list */
+ list_for_each_safe(entry, n, &mtdids) {
+ id_tmp = list_entry(entry, struct mtdids, link);
+ debug("mtdids del: %d %d\n", id_tmp->type, id_tmp->num);
+ list_del(entry);
+ free(id_tmp);
+ }
+ last_ids[0] = '\0';
+ INIT_LIST_HEAD(&mtdids);
+
+ while(p && (*p != '\0')) {
+
+ ret = 1;
+ /* parse 'nor'|'nand'|'onenand'|'spi-nand'<dev-num> */
+ if (mtd_id_parse(p, &p, &type, &num) != 0)
+ break;
+
+ if (*p != '=') {
+ printf("mtdids: incorrect <dev-num>\n");
+ break;
+ }
+ p++;
+
+ /* check if requested device exists */
+ if (mtd_device_validate(type, num, &size) != 0)
+ return 1;
+
+ /* locate <mtd-id> */
+ mtd_id = p;
+ if ((p = strchr(mtd_id, ',')) != NULL) {
+ mtd_id_len = p - mtd_id + 1;
+ p++;
+ } else {
+ mtd_id_len = strlen(mtd_id) + 1;
+ }
+ if (mtd_id_len == 0) {
+ printf("mtdids: no <mtd-id> identifier\n");
+ break;
+ }
+
+ /* check if this id is already on the list */
+ int double_entry = 0;
+ list_for_each(entry, &mtdids) {
+ id_tmp = list_entry(entry, struct mtdids, link);
+ if ((id_tmp->type == type) && (id_tmp->num == num)) {
+ double_entry = 1;
+ break;
+ }
+ }
+ if (double_entry) {
+ printf("device id %s%d redefined, please correct mtdids variable\n",
+ MTD_DEV_TYPE(type), num);
+ break;
+ }
+
+ /* allocate mtdids structure */
+ if (!(id = (struct mtdids *)malloc(sizeof(struct mtdids) + mtd_id_len))) {
+ printf("out of memory\n");
+ break;
+ }
+ memset(id, 0, sizeof(struct mtdids) + mtd_id_len);
+ id->num = num;
+ id->type = type;
+ id->size = size;
+ id->mtd_id = (char *)(id + 1);
+ strncpy(id->mtd_id, mtd_id, mtd_id_len - 1);
+ id->mtd_id[mtd_id_len - 1] = '\0';
+ INIT_LIST_HEAD(&id->link);
+
+ debug("+ id %s%d\t%16lld bytes\t%s\n",
+ MTD_DEV_TYPE(id->type), id->num,
+ id->size, id->mtd_id);
+
+ list_add_tail(&id->link, &mtdids);
+ ret = 0;
+ }
+ if (ret == 1) {
+ /* clean mtdids list and free allocated memory */
+ list_for_each_safe(entry, n, &mtdids) {
+ id_tmp = list_entry(entry, struct mtdids, link);
+ list_del(entry);
+ free(id_tmp);
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Parse and initialize global mtdids mapping and create global
+ * device/partition list.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+int mtdparts_init(void)
+{
+ static int initialized = 0;
+ const char *ids, *parts;
+ const char *current_partition;
+ int ids_changed;
+ char tmp_ep[PARTITION_MAXLEN + 1];
+ char tmp_parts[MTDPARTS_MAXLEN];
+
+ debug("\n---mtdparts_init---\n");
+ if (!initialized) {
+ INIT_LIST_HEAD(&mtdids);
+ INIT_LIST_HEAD(&devices);
+ memset(last_ids, 0, sizeof(last_ids));
+ memset(last_parts, 0, sizeof(last_parts));
+ memset(last_partition, 0, sizeof(last_partition));
+#if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
+ board_mtdparts_default(&mtdids_default, &mtdparts_default);
+#endif
+ use_defaults = 1;
+ initialized = 1;
+ }
+
+ /* get variables */
+ ids = env_get("mtdids");
+ parts = env_get_mtdparts(tmp_parts);
+ current_partition = env_get("partition");
+
+ /* save it for later parsing, cannot rely on current partition pointer
+ * as 'partition' variable may be updated during init */
+ memset(tmp_parts, 0, sizeof(tmp_parts));
+ memset(tmp_ep, 0, sizeof(tmp_ep));
+ if (current_partition)
+ strncpy(tmp_ep, current_partition, PARTITION_MAXLEN);
+
+ debug("last_ids : %s\n", last_ids);
+ debug("env_ids : %s\n", ids);
+ debug("last_parts: %s\n", last_parts);
+ debug("env_parts : %s\n\n", parts);
+
+ debug("last_partition : %s\n", last_partition);
+ debug("env_partition : %s\n", current_partition);
+
+ /* if mtdids variable is empty try to use defaults */
+ if (!ids) {
+ if (mtdids_default) {
+ debug("mtdids variable not defined, using default\n");
+ ids = mtdids_default;
+ env_set("mtdids", (char *)ids);
+ } else {
+ printf("mtdids not defined, no default present\n");
+ return 1;
+ }
+ }
+ if (strlen(ids) > MTDIDS_MAXLEN - 1) {
+ printf("mtdids too long (> %d)\n", MTDIDS_MAXLEN);
+ return 1;
+ }
+
+ /* use defaults when mtdparts variable is not defined
+ * once mtdparts is saved environment, drop use_defaults flag */
+ if (!parts) {
+ if (mtdparts_default && use_defaults) {
+ parts = mtdparts_default;
+ if (env_set("mtdparts", (char *)parts) == 0)
+ use_defaults = 0;
+ } else
+ printf("mtdparts variable not set, see 'help mtdparts'\n");
+ }
+
+ if (parts && (strlen(parts) > MTDPARTS_MAXLEN - 1)) {
+ printf("mtdparts too long (> %d)\n", MTDPARTS_MAXLEN);
+ return 1;
+ }
+
+ /* check if we have already parsed those mtdids */
+ if ((last_ids[0] != '\0') && (strcmp(last_ids, ids) == 0)) {
+ ids_changed = 0;
+ } else {
+ ids_changed = 1;
+
+ if (parse_mtdids(ids) != 0) {
+ mtd_devices_init();
+ return 1;
+ }
+
+ /* ok it's good, save new ids */
+ strncpy(last_ids, ids, MTDIDS_MAXLEN);
+ }
+
+ /* parse partitions if either mtdparts or mtdids were updated */
+ if (parts && ((last_parts[0] == '\0') || ((strcmp(last_parts, parts) != 0)) || ids_changed)) {
+ if (parse_mtdparts(parts) != 0)
+ return 1;
+
+ if (list_empty(&devices)) {
+ printf("mtdparts_init: no valid partitions\n");
+ return 1;
+ }
+
+ /* ok it's good, save new parts */
+ strncpy(last_parts, parts, MTDPARTS_MAXLEN);
+
+ /* reset first partition from first dev from the list as current */
+ current_mtd_dev = list_entry(devices.next, struct mtd_device, link);
+ current_mtd_partnum = 0;
+ current_save();
+
+ debug("mtdparts_init: current_mtd_dev = %s%d, current_mtd_partnum = %d\n",
+ MTD_DEV_TYPE(current_mtd_dev->id->type),
+ current_mtd_dev->id->num, current_mtd_partnum);
+ }
+
+ /* mtdparts variable was reset to NULL, delete all devices/partitions */
+ if (!parts && (last_parts[0] != '\0'))
+ return mtd_devices_init();
+
+ /* do not process current partition if mtdparts variable is null */
+ if (!parts)
+ return 0;
+
+ /* is current partition set in environment? if so, use it */
+ if ((tmp_ep[0] != '\0') && (strcmp(tmp_ep, last_partition) != 0)) {
+ struct part_info *p;
+ struct mtd_device *cdev;
+ u8 pnum;
+
+ debug("--- getting current partition: %s\n", tmp_ep);
+
+ if (find_dev_and_part(tmp_ep, &cdev, &pnum, &p) == 0) {
+ current_mtd_dev = cdev;
+ current_mtd_partnum = pnum;
+ current_save();
+ }
+ } else if (env_get("partition") == NULL) {
+ debug("no partition variable set, setting...\n");
+ current_save();
+ }
+
+ return 0;
+}
+
+/**
+ * Return pointer to the partition of a requested number from a requested
+ * device.
+ *
+ * @param dev device that is to be searched for a partition
+ * @param part_num requested partition number
+ * @return pointer to the part_info, NULL otherwise
+ */
+static struct part_info* mtd_part_info(struct mtd_device *dev, unsigned int part_num)
+{
+ struct list_head *entry;
+ struct part_info *part;
+ int num;
+
+ if (!dev)
+ return NULL;
+
+ debug("\n--- mtd_part_info: partition number %d for device %s%d (%s)\n",
+ part_num, MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+
+ if (part_num >= dev->num_parts) {
+ printf("invalid partition number %d for device %s%d (%s)\n",
+ part_num, MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+ return NULL;
+ }
+
+ /* locate partition number, return it */
+ num = 0;
+ list_for_each(entry, &dev->parts) {
+ part = list_entry(entry, struct part_info, link);
+
+ if (part_num == num++) {
+ return part;
+ }
+ }
+
+ return NULL;
+}
+
+/***************************************************/
+/* U-Boot commands */
+/***************************************************/
+/* command line only */
+/**
+ * Routine implementing u-boot chpart command. Sets new current partition based
+ * on the user supplied partition id. For partition id format see find_dev_and_part().
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+static int do_chpart(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+/* command line only */
+ struct mtd_device *dev;
+ struct part_info *part;
+ u8 pnum;
+
+ if (mtdparts_init() !=0)
+ return 1;
+
+ if (argc < 2) {
+ printf("no partition id specified\n");
+ return 1;
+ }
+
+ if (find_dev_and_part(argv[1], &dev, &pnum, &part) != 0)
+ return 1;
+
+ current_mtd_dev = dev;
+ current_mtd_partnum = pnum;
+ current_save();
+
+ printf("partition changed to %s%d,%d\n",
+ MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum);
+
+ return 0;
+}
+
+/**
+ * Routine implementing u-boot mtdparts command. Initialize/update default global
+ * partition list and process user partition request (list, add, del).
+ *
+ * @param cmdtp command internal data
+ * @param flag command flag
+ * @param argc number of arguments supplied to the command
+ * @param argv arguments list
+ * @return 0 on success, 1 otherwise
+ */
+static int do_mtdparts(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc == 2) {
+ if (strcmp(argv[1], "default") == 0) {
+ env_set("mtdids", NULL);
+ env_set("mtdparts", NULL);
+ env_set("partition", NULL);
+ use_defaults = 1;
+
+ mtdparts_init();
+ return 0;
+ } else if (strcmp(argv[1], "delall") == 0) {
+ /* this may be the first run, initialize lists if needed */
+ mtdparts_init();
+
+ env_set("mtdparts", NULL);
+
+ /* mtd_devices_init() calls current_save() */
+ return mtd_devices_init();
+ }
+ }
+
+ /* make sure we are in sync with env variables */
+ if (mtdparts_init() != 0)
+ return 1;
+
+ if (argc == 1) {
+ list_partitions();
+ return 0;
+ }
+
+ /* mtdparts add <mtd-dev> <size>[@<offset>] <name> [ro] */
+ if (((argc == 5) || (argc == 6)) && (strncmp(argv[1], "add", 3) == 0)) {
+#define PART_ADD_DESC_MAXLEN 64
+ char tmpbuf[PART_ADD_DESC_MAXLEN];
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+ struct mtd_info *mtd;
+ uint64_t next_offset;
+#endif
+ u8 type, num, len;
+ struct mtd_device *dev;
+ struct mtd_device *dev_tmp;
+ struct mtdids *id;
+ struct part_info *p;
+
+ if (mtd_id_parse(argv[2], NULL, &type, &num) != 0)
+ return 1;
+
+ if ((id = id_find(type, num)) == NULL) {
+ printf("no such device %s defined in mtdids variable\n", argv[2]);
+ return 1;
+ }
+
+ len = strlen(id->mtd_id) + 1; /* 'mtd_id:' */
+ len += strlen(argv[3]); /* size@offset */
+ len += strlen(argv[4]) + 2; /* '(' name ')' */
+ if (argv[5] && (strlen(argv[5]) == 2))
+ len += 2; /* 'ro' */
+
+ if (len >= PART_ADD_DESC_MAXLEN) {
+ printf("too long partition description\n");
+ return 1;
+ }
+ sprintf(tmpbuf, "%s:%s(%s)%s",
+ id->mtd_id, argv[3], argv[4], argv[5] ? argv[5] : "");
+ debug("add tmpbuf: %s\n", tmpbuf);
+
+ if ((device_parse(tmpbuf, NULL, &dev) != 0) || (!dev))
+ return 1;
+
+ debug("+ %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type),
+ dev->id->num, dev->id->mtd_id);
+
+ p = list_entry(dev->parts.next, struct part_info, link);
+
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+ if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+ return 1;
+
+ if (!strcmp(&argv[1][3], ".spread")) {
+ spread_partition(mtd, p, &next_offset);
+ debug("increased %s to %llu bytes\n", p->name, p->size);
+ }
+#endif
+
+ dev_tmp = device_find(dev->id->type, dev->id->num);
+ if (dev_tmp == NULL) {
+ device_add(dev);
+ } else if (part_add(dev_tmp, p) != 0) {
+ /* merge new partition with existing ones*/
+ device_del(dev);
+ return 1;
+ }
+
+ if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+ printf("generated mtdparts too long, resetting to null\n");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /* mtdparts del part-id */
+ if ((argc == 3) && (strcmp(argv[1], "del") == 0)) {
+ debug("del: part-id = %s\n", argv[2]);
+
+ return delete_partition(argv[2]);
+ }
+
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+ if ((argc == 2) && (strcmp(argv[1], "spread") == 0))
+ return spread_partitions();
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
+
+ return CMD_RET_USAGE;
+}
+
+/***************************************************/
+U_BOOT_CMD(
+ chpart, 2, 0, do_chpart,
+ "change active partition",
+ "part-id\n"
+ " - change active partition (e.g. part-id = nand0,1)"
+);
+
+#ifdef CONFIG_SYS_LONGHELP
+static char mtdparts_help_text[] =
+ "\n"
+ " - list partition table\n"
+ "mtdparts delall\n"
+ " - delete all partitions\n"
+ "mtdparts del part-id\n"
+ " - delete partition (e.g. part-id = nand0,1)\n"
+ "mtdparts add <mtd-dev> <size>[@<offset>] [<name>] [ro]\n"
+ " - add partition\n"
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+ "mtdparts add.spread <mtd-dev> <size>[@<offset>] [<name>] [ro]\n"
+ " - add partition, padding size by skipping bad blocks\n"
+#endif
+ "mtdparts default\n"
+ " - reset partition table to defaults\n"
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+ "mtdparts spread\n"
+ " - adjust the sizes of the partitions so they are\n"
+ " at least as big as the mtdparts variable specifies\n"
+ " and they each start on a good block\n\n"
+#else
+ "\n"
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
+ "-----\n\n"
+ "this command uses three environment variables:\n\n"
+ "'partition' - keeps current partition identifier\n\n"
+ "partition := <part-id>\n"
+ "<part-id> := <dev-id>,part_num\n\n"
+ "'mtdids' - linux kernel mtd device id <-> u-boot device id mapping\n\n"
+ "mtdids=<idmap>[,<idmap>,...]\n\n"
+ "<idmap> := <dev-id>=<mtd-id>\n"
+ "<dev-id> := 'nand'|'nor'|'onenand'|'spi-nand'<dev-num>\n"
+ "<dev-num> := mtd device number, 0...\n"
+ "<mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)\n\n"
+ "'mtdparts' - partition list\n\n"
+ "mtdparts=mtdparts=<mtd-def>[;<mtd-def>...]\n\n"
+ "<mtd-def> := <mtd-id>:<part-def>[,<part-def>...]\n"
+ "<mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)\n"
+ "<part-def> := <size>[@<offset>][<name>][<ro-flag>]\n"
+ "<size> := standard linux memsize OR '-' to denote all remaining space\n"
+ "<offset> := partition start offset within the device\n"
+ "<name> := '(' NAME ')'\n"
+ "<ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)";
+#endif
+
+U_BOOT_CMD(
+ mtdparts, 6, 0, do_mtdparts,
+ "define flash/nand partitions", mtdparts_help_text
+);
+/***************************************************/
diff --git a/roms/u-boot/cmd/mux.c b/roms/u-boot/cmd/mux.c
new file mode 100644
index 000000000..833266f08
--- /dev/null
+++ b/roms/u-boot/cmd/mux.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * List, select, and deselect mux controllers on the fly.
+ *
+ * Copyright (c) 2020 Texas Instruments Inc.
+ * Author: Pratyush Yadav <p.yadav@ti.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <mux.h>
+#include <mux-internal.h>
+#include <linux/err.h>
+#include <dt-bindings/mux/mux.h>
+
+#define COLUMN_SIZE 16
+
+/*
+ * Print a member of a column. The total size of the text printed, including
+ * trailing whitespace, will always be COLUMN_SIZE.
+ */
+#define PRINT_COLUMN(fmt, args...) do { \
+ char buf[COLUMN_SIZE + 1]; \
+ snprintf(buf, COLUMN_SIZE + 1, fmt, ##args); \
+ printf("%-*s", COLUMN_SIZE, buf); \
+} while (0)
+
+/*
+ * Find a mux based on its device name in argv[1] and index in the chip in
+ * argv[2].
+ */
+static struct mux_control *cmd_mux_find(char *const argv[])
+{
+ struct udevice *dev;
+ struct mux_chip *chip;
+ int ret;
+ unsigned long id;
+
+ ret = strict_strtoul(argv[2], 10, &id);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = uclass_get_device_by_name(UCLASS_MUX, argv[1], &dev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ chip = dev_get_uclass_priv(dev);
+ if (!chip)
+ return ERR_PTR(ret);
+
+ if (id >= chip->controllers)
+ return ERR_PTR(-EINVAL);
+
+ return &chip->mux[id];
+}
+
+/*
+ * Print the details of a mux. The columns printed correspond to: "Selected",
+ * "Current State", "Idle State", and "Num States".
+ */
+static void print_mux(struct mux_control *mux)
+{
+ PRINT_COLUMN("%s", mux->in_use ? "yes" : "no");
+
+ if (mux->cached_state == MUX_IDLE_AS_IS)
+ PRINT_COLUMN("%s", "unknown");
+ else
+ PRINT_COLUMN("0x%x", mux->cached_state);
+
+ if (mux->idle_state == MUX_IDLE_AS_IS)
+ PRINT_COLUMN("%s", "as-is");
+ else if (mux->idle_state == MUX_IDLE_DISCONNECT)
+ PRINT_COLUMN("%s", "disconnect");
+ else
+ PRINT_COLUMN("0x%x", mux->idle_state);
+
+ PRINT_COLUMN("0x%x", mux->states);
+
+ printf("\n");
+}
+
+static int do_mux_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct mux_chip *chip;
+ int j;
+
+ for (uclass_first_device(UCLASS_MUX, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ chip = dev_get_uclass_priv(dev);
+ if (!chip) {
+ dev_err(dev, "can't find mux chip\n");
+ continue;
+ }
+
+ printf("%s:\n", dev->name);
+
+ printf(" ");
+ PRINT_COLUMN("ID");
+ PRINT_COLUMN("Selected");
+ PRINT_COLUMN("Current State");
+ PRINT_COLUMN("Idle State");
+ PRINT_COLUMN("Num States");
+ printf("\n");
+ for (j = 0; j < chip->controllers; j++) {
+ printf(" ");
+ PRINT_COLUMN("%d", j);
+ print_mux(&chip->mux[j]);
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
+
+static int do_mux_select(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct mux_control *mux;
+ int ret;
+ unsigned long state;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ mux = cmd_mux_find(argv);
+ if (IS_ERR_OR_NULL(mux)) {
+ printf("Failed to find the specified mux\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = strict_strtoul(argv[3], 16, &state);
+ if (ret) {
+ printf("Invalid state\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = mux_control_select(mux, state);
+ if (ret) {
+ printf("Failed to select requested state\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mux_deselect(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct mux_control *mux;
+ int ret;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ mux = cmd_mux_find(argv);
+ if (IS_ERR_OR_NULL(mux)) {
+ printf("Failed to find the specified mux\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = mux_control_deselect(mux);
+ if (ret) {
+ printf("Failed to deselect mux\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static char mux_help_text[] =
+ "list - List all Muxes and their states\n"
+ "select <chip> <id> <state> - Select the given mux state\n"
+ "deselect <chip> <id> - Deselect the given mux and reset it to its idle state";
+
+U_BOOT_CMD_WITH_SUBCMDS(mux, "List, select, and deselect muxes", mux_help_text,
+ U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mux_list),
+ U_BOOT_SUBCMD_MKENT(select, 4, 0, do_mux_select),
+ U_BOOT_SUBCMD_MKENT(deselect, 3, 0, do_mux_deselect));
diff --git a/roms/u-boot/cmd/mvebu/Kconfig b/roms/u-boot/cmd/mvebu/Kconfig
new file mode 100644
index 000000000..7c42c75af
--- /dev/null
+++ b/roms/u-boot/cmd/mvebu/Kconfig
@@ -0,0 +1,58 @@
+menu "MVEBU commands"
+depends on ARCH_MVEBU
+
+config CMD_MVEBU_BUBT
+ bool "bubt"
+ default n
+ help
+ bubt - Burn a u-boot image to flash
+ For details about bubt command please see the documentation
+ in doc/mvebu/cmd/bubt.txt
+
+choice
+ prompt "Flash for image"
+ default MVEBU_SPI_BOOT
+
+config MVEBU_NAND_BOOT
+ bool "NAND flash boot"
+ depends on NAND_PXA3XX
+ help
+ Enable boot from NAND flash.
+ Allow usage of NAND flash as a target for "bubt" command
+ For details about bubt command please see the documentation
+ in doc/mvebu/cmd/bubt.txt
+
+config MVEBU_SPI_BOOT
+ bool "SPI flash boot"
+ depends on SPI_FLASH
+ help
+ Enable boot from SPI flash.
+ Allow usage of SPI flash as a target for "bubt" command
+ For details about bubt command please see the documentation
+ in doc/mvebu/cmd/bubt.txt
+
+config MVEBU_MMC_BOOT
+ bool "eMMC flash boot"
+ depends on MVEBU_MMC || MMC_SDHCI_XENON
+ help
+ Enable boot from eMMC boot partition
+ Allow usage of eMMC/SD device as a target for "bubt" command
+ For details about bubt command please see the documentation
+ in doc/mvebu/cmd/bubt.txt
+
+endchoice
+
+config MVEBU_UBOOT_DFLT_NAME
+ string "Default image name for bubt command"
+ default "flash-image.bin"
+ help
+ This option should contain a default file name to be used with
+ MVEBU "bubt" command if the source file name is omitted
+
+config CMD_MVEBU_COMPHY_RX_TRAINING
+ bool "mvebu_comphy_rx_training"
+ depends on ARMADA_8K
+ help
+ Perform COMPHY RX training sequence
+
+endmenu
diff --git a/roms/u-boot/cmd/mvebu/Makefile b/roms/u-boot/cmd/mvebu/Makefile
new file mode 100644
index 000000000..ca96ad01d
--- /dev/null
+++ b/roms/u-boot/cmd/mvebu/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2016 Marvell International Ltd.
+#
+# https://spdx.org/licenses
+
+obj-$(CONFIG_CMD_MVEBU_BUBT) += bubt.o
+obj-$(CONFIG_CMD_MVEBU_COMPHY_RX_TRAINING) += comphy_rx_training.o
diff --git a/roms/u-boot/cmd/mvebu/bubt.c b/roms/u-boot/cmd/mvebu/bubt.c
new file mode 100644
index 000000000..5cd520e46
--- /dev/null
+++ b/roms/u-boot/cmd/mvebu/bubt.c
@@ -0,0 +1,885 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ * https://spdx.org/licenses
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <flash.h>
+#include <image.h>
+#include <net.h>
+#include <vsprintf.h>
+#include <errno.h>
+#include <dm.h>
+
+#include <spi_flash.h>
+#include <spi.h>
+#include <nand.h>
+#include <usb.h>
+#include <fs.h>
+#include <mmc.h>
+#ifdef CONFIG_BLK
+#include <blk.h>
+#endif
+#include <u-boot/sha1.h>
+#include <u-boot/sha256.h>
+
+#if defined(CONFIG_ARMADA_8K)
+#define MAIN_HDR_MAGIC 0xB105B002
+
+struct mvebu_image_header {
+ u32 magic; /* 0-3 */
+ u32 prolog_size; /* 4-7 */
+ u32 prolog_checksum; /* 8-11 */
+ u32 boot_image_size; /* 12-15 */
+ u32 boot_image_checksum; /* 16-19 */
+ u32 rsrvd0; /* 20-23 */
+ u32 load_addr; /* 24-27 */
+ u32 exec_addr; /* 28-31 */
+ u8 uart_cfg; /* 32 */
+ u8 baudrate; /* 33 */
+ u8 ext_count; /* 34 */
+ u8 aux_flags; /* 35 */
+ u32 io_arg_0; /* 36-39 */
+ u32 io_arg_1; /* 40-43 */
+ u32 io_arg_2; /* 43-47 */
+ u32 io_arg_3; /* 48-51 */
+ u32 rsrvd1; /* 52-55 */
+ u32 rsrvd2; /* 56-59 */
+ u32 rsrvd3; /* 60-63 */
+};
+#elif defined(CONFIG_ARMADA_3700) /* A3700 */
+#define HASH_SUM_LEN 16
+#define IMAGE_VERSION_3_6_0 0x030600
+#define IMAGE_VERSION_3_5_0 0x030500
+
+struct common_tim_data {
+ u32 version;
+ u32 identifier;
+ u32 trusted;
+ u32 issue_date;
+ u32 oem_unique_id;
+ u32 reserved[5]; /* Reserve 20 bytes */
+ u32 boot_flash_sign;
+ u32 num_images;
+ u32 num_keys;
+ u32 size_of_reserved;
+};
+
+struct mvebu_image_info {
+ u32 image_id;
+ u32 next_image_id;
+ u32 flash_entry_addr;
+ u32 load_addr;
+ u32 image_size;
+ u32 image_size_to_hash;
+ u32 hash_algorithm_id;
+ u32 hash[HASH_SUM_LEN]; /* Reserve 512 bits for the hash */
+ u32 partition_number;
+ u32 enc_algorithm_id;
+ u32 encrypt_start_offset;
+ u32 encrypt_size;
+};
+#endif
+
+/* Structure of the main header, version 1 (Armada 370/38x/XP) */
+struct a38x_main_hdr_v1 {
+ u8 blockid; /* 0x0 */
+ u8 flags; /* 0x1 */
+ u16 reserved2; /* 0x2-0x3 */
+ u32 blocksize; /* 0x4-0x7 */
+ u8 version; /* 0x8 */
+ u8 headersz_msb; /* 0x9 */
+ u16 headersz_lsb; /* 0xA-0xB */
+ u32 srcaddr; /* 0xC-0xF */
+ u32 destaddr; /* 0x10-0x13 */
+ u32 execaddr; /* 0x14-0x17 */
+ u8 options; /* 0x18 */
+ u8 nandblocksize; /* 0x19 */
+ u8 nandbadblklocation; /* 0x1A */
+ u8 reserved4; /* 0x1B */
+ u16 reserved5; /* 0x1C-0x1D */
+ u8 ext; /* 0x1E */
+ u8 checksum; /* 0x1F */
+};
+
+struct a38x_boot_mode {
+ unsigned int id;
+ const char *name;
+};
+
+/* The blockid header field values used to indicate boot device of image */
+struct a38x_boot_mode a38x_boot_modes[] = {
+ { 0x4D, "i2c" },
+ { 0x5A, "spi" },
+ { 0x69, "uart" },
+ { 0x78, "sata" },
+ { 0x8B, "nand" },
+ { 0x9C, "pex" },
+ { 0xAE, "mmc" },
+ {},
+};
+
+struct bubt_dev {
+ char name[8];
+ size_t (*read)(const char *file_name);
+ int (*write)(size_t image_size);
+ int (*active)(void);
+};
+
+static ulong get_load_addr(void)
+{
+ const char *addr_str;
+ unsigned long addr;
+
+ addr_str = env_get("loadaddr");
+ if (addr_str)
+ addr = simple_strtoul(addr_str, NULL, 16);
+ else
+ addr = CONFIG_SYS_LOAD_ADDR;
+
+ return addr;
+}
+
+/********************************************************************
+ * eMMC services
+ ********************************************************************/
+#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(MMC_WRITE)
+static int mmc_burn_image(size_t image_size)
+{
+ struct mmc *mmc;
+ lbaint_t start_lba;
+ lbaint_t blk_count;
+ ulong blk_written;
+ int err;
+ const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
+#ifdef CONFIG_BLK
+ struct blk_desc *blk_desc;
+#endif
+ mmc = find_mmc_device(mmc_dev_num);
+ if (!mmc) {
+ printf("No SD/MMC/eMMC card found\n");
+ return -ENOMEDIUM;
+ }
+
+ err = mmc_init(mmc);
+ if (err) {
+ printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
+ mmc_dev_num);
+ return err;
+ }
+
+ /* SD reserves LBA-0 for MBR and boots from LBA-1,
+ * MMC/eMMC boots from LBA-0
+ */
+ start_lba = IS_SD(mmc) ? 1 : 0;
+#ifdef CONFIG_BLK
+ blk_count = image_size / mmc->write_bl_len;
+ if (image_size % mmc->write_bl_len)
+ blk_count += 1;
+
+ blk_desc = mmc_get_blk_desc(mmc);
+ if (!blk_desc) {
+ printf("Error - failed to obtain block descriptor\n");
+ return -ENODEV;
+ }
+ blk_written = blk_dwrite(blk_desc, start_lba, blk_count,
+ (void *)get_load_addr());
+#else
+ blk_count = image_size / mmc->block_dev.blksz;
+ if (image_size % mmc->block_dev.blksz)
+ blk_count += 1;
+
+ blk_written = mmc->block_dev.block_write(mmc_dev_num,
+ start_lba, blk_count,
+ (void *)get_load_addr());
+#endif /* CONFIG_BLK */
+ if (blk_written != blk_count) {
+ printf("Error - written %#lx blocks\n", blk_written);
+ return -ENOSPC;
+ }
+ printf("Done!\n");
+
+ return 0;
+}
+
+static size_t mmc_read_file(const char *file_name)
+{
+ loff_t act_read = 0;
+ int rc;
+ struct mmc *mmc;
+ const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
+
+ mmc = find_mmc_device(mmc_dev_num);
+ if (!mmc) {
+ printf("No SD/MMC/eMMC card found\n");
+ return 0;
+ }
+
+ if (mmc_init(mmc)) {
+ printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
+ mmc_dev_num);
+ return 0;
+ }
+
+ /* Load from data partition (0) */
+ if (fs_set_blk_dev("mmc", "0", FS_TYPE_ANY)) {
+ printf("Error: MMC 0 not found\n");
+ return 0;
+ }
+
+ /* Perfrom file read */
+ rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
+ if (rc)
+ return 0;
+
+ return act_read;
+}
+
+static int is_mmc_active(void)
+{
+ return 1;
+}
+#else /* CONFIG_DM_MMC */
+static int mmc_burn_image(size_t image_size)
+{
+ return -ENODEV;
+}
+
+static size_t mmc_read_file(const char *file_name)
+{
+ return 0;
+}
+
+static int is_mmc_active(void)
+{
+ return 0;
+}
+#endif /* CONFIG_DM_MMC */
+
+/********************************************************************
+ * SPI services
+ ********************************************************************/
+#ifdef CONFIG_SPI_FLASH
+static int spi_burn_image(size_t image_size)
+{
+ int ret;
+ struct spi_flash *flash;
+ u32 erase_bytes;
+
+ /* Probe the SPI bus to get the flash device */
+ flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
+ CONFIG_ENV_SPI_CS,
+ CONFIG_SF_DEFAULT_SPEED,
+ CONFIG_SF_DEFAULT_MODE);
+ if (!flash) {
+ printf("Failed to probe SPI Flash\n");
+ return -ENOMEDIUM;
+ }
+
+ erase_bytes = image_size +
+ (flash->erase_size - image_size % flash->erase_size);
+ printf("Erasing %d bytes (%d blocks) at offset 0 ...",
+ erase_bytes, erase_bytes / flash->erase_size);
+ ret = spi_flash_erase(flash, 0, erase_bytes);
+ if (ret)
+ printf("Error!\n");
+ else
+ printf("Done!\n");
+
+ printf("Writing %d bytes from 0x%lx to offset 0 ...",
+ (int)image_size, get_load_addr());
+ ret = spi_flash_write(flash, 0, image_size, (void *)get_load_addr());
+ if (ret)
+ printf("Error!\n");
+ else
+ printf("Done!\n");
+
+ return ret;
+}
+
+static int is_spi_active(void)
+{
+ return 1;
+}
+
+#else /* CONFIG_SPI_FLASH */
+static int spi_burn_image(size_t image_size)
+{
+ return -ENODEV;
+}
+
+static int is_spi_active(void)
+{
+ return 0;
+}
+#endif /* CONFIG_SPI_FLASH */
+
+/********************************************************************
+ * NAND services
+ ********************************************************************/
+#ifdef CONFIG_CMD_NAND
+static int nand_burn_image(size_t image_size)
+{
+ int ret;
+ uint32_t block_size;
+ struct mtd_info *mtd;
+
+ mtd = get_nand_dev_by_index(nand_curr_device);
+ if (!mtd) {
+ puts("\nno devices available\n");
+ return -ENOMEDIUM;
+ }
+ block_size = mtd->erasesize;
+
+ /* Align U-Boot size to currently used blocksize */
+ image_size = ((image_size + (block_size - 1)) & (~(block_size - 1)));
+
+ /* Erase the U-Boot image space */
+ printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size);
+ ret = nand_erase(mtd, 0, image_size);
+ if (ret) {
+ printf("Error!\n");
+ goto error;
+ }
+ printf("Done!\n");
+
+ /* Write the image to flash */
+ printf("Writing %d bytes from 0x%lx to offset 0 ... ",
+ (int)image_size, get_load_addr());
+ ret = nand_write(mtd, 0, &image_size, (void *)get_load_addr());
+ if (ret)
+ printf("Error!\n");
+ else
+ printf("Done!\n");
+
+error:
+ return ret;
+}
+
+static int is_nand_active(void)
+{
+ return 1;
+}
+
+#else /* CONFIG_CMD_NAND */
+static int nand_burn_image(size_t image_size)
+{
+ return -ENODEV;
+}
+
+static int is_nand_active(void)
+{
+ return 0;
+}
+#endif /* CONFIG_CMD_NAND */
+
+/********************************************************************
+ * USB services
+ ********************************************************************/
+#if defined(CONFIG_USB_STORAGE) && defined(CONFIG_BLK)
+static size_t usb_read_file(const char *file_name)
+{
+ loff_t act_read = 0;
+ struct udevice *dev;
+ int rc;
+
+ usb_stop();
+
+ if (usb_init() < 0) {
+ printf("Error: usb_init failed\n");
+ return 0;
+ }
+
+ /* Try to recognize storage devices immediately */
+ blk_first_device(IF_TYPE_USB, &dev);
+ if (!dev) {
+ printf("Error: USB storage device not found\n");
+ return 0;
+ }
+
+ /* Always load from usb 0 */
+ if (fs_set_blk_dev("usb", "0", FS_TYPE_ANY)) {
+ printf("Error: USB 0 not found\n");
+ return 0;
+ }
+
+ /* Perfrom file read */
+ rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
+ if (rc)
+ return 0;
+
+ return act_read;
+}
+
+static int is_usb_active(void)
+{
+ return 1;
+}
+
+#else /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
+static size_t usb_read_file(const char *file_name)
+{
+ return 0;
+}
+
+static int is_usb_active(void)
+{
+ return 0;
+}
+#endif /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
+
+/********************************************************************
+ * Network services
+ ********************************************************************/
+#ifdef CONFIG_CMD_NET
+static size_t tftp_read_file(const char *file_name)
+{
+ /*
+ * update global variable image_load_addr before tftp file from network
+ */
+ image_load_addr = get_load_addr();
+ return net_loop(TFTPGET);
+}
+
+static int is_tftp_active(void)
+{
+ return 1;
+}
+
+#else
+static size_t tftp_read_file(const char *file_name)
+{
+ return 0;
+}
+
+static int is_tftp_active(void)
+{
+ return 0;
+}
+#endif /* CONFIG_CMD_NET */
+
+enum bubt_devices {
+ BUBT_DEV_NET = 0,
+ BUBT_DEV_USB,
+ BUBT_DEV_MMC,
+ BUBT_DEV_SPI,
+ BUBT_DEV_NAND,
+
+ BUBT_MAX_DEV
+};
+
+struct bubt_dev bubt_devs[BUBT_MAX_DEV] = {
+ {"tftp", tftp_read_file, NULL, is_tftp_active},
+ {"usb", usb_read_file, NULL, is_usb_active},
+ {"mmc", mmc_read_file, mmc_burn_image, is_mmc_active},
+ {"spi", NULL, spi_burn_image, is_spi_active},
+ {"nand", NULL, nand_burn_image, is_nand_active},
+};
+
+static int bubt_write_file(struct bubt_dev *dst, size_t image_size)
+{
+ if (!dst->write) {
+ printf("Error: Write not supported on device %s\n", dst->name);
+ return -ENOTSUPP;
+ }
+
+ return dst->write(image_size);
+}
+
+#if defined(CONFIG_ARMADA_8K)
+u32 do_checksum32(u32 *start, int32_t len)
+{
+ u32 sum = 0;
+ u32 *startp = start;
+
+ do {
+ sum += *startp;
+ startp++;
+ len -= 4;
+ } while (len > 0);
+
+ return sum;
+}
+
+static int check_image_header(void)
+{
+ struct mvebu_image_header *hdr =
+ (struct mvebu_image_header *)get_load_addr();
+ u32 header_len = hdr->prolog_size;
+ u32 checksum;
+ u32 checksum_ref = hdr->prolog_checksum;
+
+ /*
+ * For now compare checksum, and magic. Later we can
+ * verify more stuff on the header like interface type, etc
+ */
+ if (hdr->magic != MAIN_HDR_MAGIC) {
+ printf("ERROR: Bad MAGIC 0x%08x != 0x%08x\n",
+ hdr->magic, MAIN_HDR_MAGIC);
+ return -ENOEXEC;
+ }
+
+ /* The checksum value is discarded from checksum calculation */
+ hdr->prolog_checksum = 0;
+
+ checksum = do_checksum32((u32 *)hdr, header_len);
+ if (checksum != checksum_ref) {
+ printf("Error: Bad Image checksum. 0x%x != 0x%x\n",
+ checksum, checksum_ref);
+ return -ENOEXEC;
+ }
+
+ /* Restore the checksum before writing */
+ hdr->prolog_checksum = checksum_ref;
+ printf("Image checksum...OK!\n");
+
+ return 0;
+}
+#elif defined(CONFIG_ARMADA_3700) /* Armada 3700 */
+static int check_image_header(void)
+{
+ struct common_tim_data *hdr = (struct common_tim_data *)get_load_addr();
+ int image_num;
+ u8 hash_160_output[SHA1_SUM_LEN];
+ u8 hash_256_output[SHA256_SUM_LEN];
+ sha1_context hash1_text;
+ sha256_context hash256_text;
+ u8 *hash_output;
+ u32 hash_algorithm_id;
+ u32 image_size_to_hash;
+ u32 flash_entry_addr;
+ u32 *hash_value;
+ u32 internal_hash[HASH_SUM_LEN];
+ const u8 *buff;
+ u32 num_of_image = hdr->num_images;
+ u32 version = hdr->version;
+ u32 trusted = hdr->trusted;
+
+ /* bubt checksum validation only supports nontrusted images */
+ if (trusted == 1) {
+ printf("bypass image validation, ");
+ printf("only untrusted image is supported now\n");
+ return 0;
+ }
+ /* only supports image version 3.5 and 3.6 */
+ if (version != IMAGE_VERSION_3_5_0 && version != IMAGE_VERSION_3_6_0) {
+ printf("Error: Unsupported Image version = 0x%08x\n", version);
+ return -ENOEXEC;
+ }
+ /* validate images hash value */
+ for (image_num = 0; image_num < num_of_image; image_num++) {
+ struct mvebu_image_info *info =
+ (struct mvebu_image_info *)(get_load_addr() +
+ sizeof(struct common_tim_data) +
+ image_num * sizeof(struct mvebu_image_info));
+ hash_algorithm_id = info->hash_algorithm_id;
+ image_size_to_hash = info->image_size_to_hash;
+ flash_entry_addr = info->flash_entry_addr;
+ hash_value = info->hash;
+ buff = (const u8 *)(get_load_addr() + flash_entry_addr);
+
+ if (image_num == 0) {
+ /*
+ * The first image includes hash values in its content.
+ * For hash calculation, we need to save the original
+ * hash values to a local variable that will be
+ * copied back for comparsion and set all zeros to
+ * the orignal hash values for calculating new value.
+ * First image original format :
+ * x...x (datum1) x...x(orig. hash values) x...x(datum2)
+ * Replaced first image format :
+ * x...x (datum1) 0...0(hash values) x...x(datum2)
+ */
+ memcpy(internal_hash, hash_value,
+ sizeof(internal_hash));
+ memset(hash_value, 0, sizeof(internal_hash));
+ }
+ if (image_size_to_hash == 0) {
+ printf("Warning: Image_%d hash checksum is disabled, ",
+ image_num);
+ printf("skip the image validation.\n");
+ continue;
+ }
+ switch (hash_algorithm_id) {
+ case SHA1_SUM_LEN:
+ sha1_starts(&hash1_text);
+ sha1_update(&hash1_text, buff, image_size_to_hash);
+ sha1_finish(&hash1_text, hash_160_output);
+ hash_output = hash_160_output;
+ break;
+ case SHA256_SUM_LEN:
+ sha256_starts(&hash256_text);
+ sha256_update(&hash256_text, buff, image_size_to_hash);
+ sha256_finish(&hash256_text, hash_256_output);
+ hash_output = hash_256_output;
+ break;
+ default:
+ printf("Error: Unsupported hash_algorithm_id = %d\n",
+ hash_algorithm_id);
+ return -ENOEXEC;
+ }
+ if (image_num == 0)
+ memcpy(hash_value, internal_hash,
+ sizeof(internal_hash));
+ if (memcmp(hash_value, hash_output, hash_algorithm_id) != 0) {
+ printf("Error: Image_%d checksum is not correct\n",
+ image_num);
+ return -ENOEXEC;
+ }
+ }
+ printf("Image checksum...OK!\n");
+
+ return 0;
+}
+#elif defined(CONFIG_ARMADA_38X)
+static size_t a38x_header_size(const struct a38x_main_hdr_v1 *h)
+{
+ if (h->version == 1)
+ return (h->headersz_msb << 16) | le16_to_cpu(h->headersz_lsb);
+
+ printf("Error: Invalid A38x image (header version 0x%x unknown)!\n",
+ h->version);
+ return 0;
+}
+
+static uint8_t image_checksum8(const void *start, size_t len)
+{
+ u8 csum = 0;
+ const u8 *p = start;
+
+ while (len) {
+ csum += *p;
+ ++p;
+ --len;
+ }
+
+ return csum;
+}
+
+static int check_image_header(void)
+{
+ u8 checksum;
+ const struct a38x_main_hdr_v1 *hdr =
+ (struct a38x_main_hdr_v1 *)get_load_addr();
+ const size_t image_size = a38x_header_size(hdr);
+
+ if (!image_size)
+ return -ENOEXEC;
+
+ checksum = image_checksum8(hdr, image_size);
+ checksum -= hdr->checksum;
+ if (checksum != hdr->checksum) {
+ printf("Error: Bad A38x image checksum. 0x%x != 0x%x\n",
+ checksum, hdr->checksum);
+ return -ENOEXEC;
+ }
+
+ printf("Image checksum...OK!\n");
+ return 0;
+}
+#else /* Not ARMADA? */
+static int check_image_header(void)
+{
+ printf("bubt cmd does not support this SoC device or family!\n");
+ return -ENOEXEC;
+}
+#endif
+
+static int bubt_check_boot_mode(const struct bubt_dev *dst)
+{
+ if (IS_ENABLED(CONFIG_ARMADA_38X)) {
+ int mode;
+ const struct a38x_main_hdr_v1 *hdr =
+ (struct a38x_main_hdr_v1 *)get_load_addr();
+
+ for (mode = 0; mode < ARRAY_SIZE(a38x_boot_modes); mode++) {
+ if (strcmp(a38x_boot_modes[mode].name, dst->name) == 0)
+ break;
+ }
+
+ if (a38x_boot_modes[mode].id == hdr->blockid)
+ return 0;
+
+ for (int i = 0; i < ARRAY_SIZE(a38x_boot_modes); i++) {
+ if (a38x_boot_modes[i].id == hdr->blockid) {
+ printf("Error: A38x image meant to be booted from "
+ "\"%s\", not \"%s\"!\n",
+ a38x_boot_modes[i].name, dst->name);
+ return -ENOEXEC;
+ }
+ }
+
+ printf("Error: unknown boot device in A38x image header: "
+ "0x%x\n", hdr->blockid);
+ return -ENOEXEC;
+ } else {
+ return 0;
+ }
+}
+
+static int bubt_verify(const struct bubt_dev *dst)
+{
+ int err;
+
+ /* Check a correct image header exists */
+ err = check_image_header();
+ if (err) {
+ printf("Error: Image header verification failed\n");
+ return err;
+ }
+
+ err = bubt_check_boot_mode(dst);
+ if (err) {
+ printf("Error: Image boot mode verification failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int bubt_read_file(struct bubt_dev *src)
+{
+ size_t image_size;
+
+ if (!src->read) {
+ printf("Error: Read not supported on device \"%s\"\n",
+ src->name);
+ return 0;
+ }
+
+ image_size = src->read(net_boot_file_name);
+ if (image_size <= 0) {
+ printf("Error: Failed to read file %s from %s\n",
+ net_boot_file_name, src->name);
+ return 0;
+ }
+
+ return image_size;
+}
+
+static int bubt_is_dev_active(struct bubt_dev *dev)
+{
+ if (!dev->active) {
+ printf("Device \"%s\" not supported by U-Boot image\n",
+ dev->name);
+ return 0;
+ }
+
+ if (!dev->active()) {
+ printf("Device \"%s\" is inactive\n", dev->name);
+ return 0;
+ }
+
+ return 1;
+}
+
+struct bubt_dev *find_bubt_dev(char *dev_name)
+{
+ int dev;
+
+ for (dev = 0; dev < BUBT_MAX_DEV; dev++) {
+ if (strcmp(bubt_devs[dev].name, dev_name) == 0)
+ return &bubt_devs[dev];
+ }
+
+ return 0;
+}
+
+#define DEFAULT_BUBT_SRC "tftp"
+
+#ifndef DEFAULT_BUBT_DST
+#ifdef CONFIG_MVEBU_SPI_BOOT
+#define DEFAULT_BUBT_DST "spi"
+#elif defined(CONFIG_MVEBU_NAND_BOOT)
+#define DEFAULT_BUBT_DST "nand"
+#elif defined(CONFIG_MVEBU_MMC_BOOT)
+#define DEFAULT_BUBT_DST "mmc"
+#else
+#define DEFAULT_BUBT_DST "error"
+#endif
+#endif /* DEFAULT_BUBT_DST */
+
+int do_bubt_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct bubt_dev *src, *dst;
+ size_t image_size;
+ char src_dev_name[8];
+ char dst_dev_name[8];
+ char *name;
+ int err;
+
+ if (argc < 2)
+ copy_filename(net_boot_file_name,
+ CONFIG_MVEBU_UBOOT_DFLT_NAME,
+ sizeof(net_boot_file_name));
+ else
+ copy_filename(net_boot_file_name, argv[1],
+ sizeof(net_boot_file_name));
+
+ if (argc >= 3) {
+ strncpy(dst_dev_name, argv[2], 8);
+ } else {
+ name = DEFAULT_BUBT_DST;
+ strncpy(dst_dev_name, name, 8);
+ }
+
+ if (argc >= 4)
+ strncpy(src_dev_name, argv[3], 8);
+ else
+ strncpy(src_dev_name, DEFAULT_BUBT_SRC, 8);
+
+ /* Figure out the destination device */
+ dst = find_bubt_dev(dst_dev_name);
+ if (!dst) {
+ printf("Error: Unknown destination \"%s\"\n", dst_dev_name);
+ return -EINVAL;
+ }
+
+ if (!bubt_is_dev_active(dst))
+ return -ENODEV;
+
+ /* Figure out the source device */
+ src = find_bubt_dev(src_dev_name);
+ if (!src) {
+ printf("Error: Unknown source \"%s\"\n", src_dev_name);
+ return 1;
+ }
+
+ if (!bubt_is_dev_active(src))
+ return -ENODEV;
+
+ printf("Burning U-Boot image \"%s\" from \"%s\" to \"%s\"\n",
+ net_boot_file_name, src->name, dst->name);
+
+ image_size = bubt_read_file(src);
+ if (!image_size)
+ return -EIO;
+
+ err = bubt_verify(dst);
+ if (err)
+ return err;
+
+ err = bubt_write_file(dst, image_size);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ bubt, 4, 0, do_bubt_cmd,
+ "Burn a u-boot image to flash",
+ "[file-name] [destination [source]]\n"
+ "\t-file-name The image file name to burn. Default = " CONFIG_MVEBU_UBOOT_DFLT_NAME "\n"
+ "\t-destination Flash to burn to [spi, nand, mmc]. Default = " DEFAULT_BUBT_DST "\n"
+ "\t-source The source to load image from [tftp, usb, mmc]. Default = " DEFAULT_BUBT_SRC "\n"
+ "Examples:\n"
+ "\tbubt - Burn flash-image.bin from tftp to active boot device\n"
+ "\tbubt flash-image-new.bin nand - Burn flash-image-new.bin from tftp to NAND flash\n"
+ "\tbubt backup-flash-image.bin mmc usb - Burn backup-flash-image.bin from usb to MMC\n"
+
+);
diff --git a/roms/u-boot/cmd/mvebu/comphy_rx_training.c b/roms/u-boot/cmd/mvebu/comphy_rx_training.c
new file mode 100644
index 000000000..0798decfa
--- /dev/null
+++ b/roms/u-boot/cmd/mvebu/comphy_rx_training.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <dm/device-internal.h>
+#include <mvebu/comphy.h>
+
+int mvebu_comphy_rx_training_cmd(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret, cp_index, comphy_index, i = 0;
+
+ if (argc != 3) {
+ printf("missing arguments\n");
+ return -1;
+ }
+
+ cp_index = simple_strtoul(argv[1], NULL, 16);
+ comphy_index = simple_strtoul(argv[2], NULL, 16);
+
+ ret = uclass_get(UCLASS_MISC, &uc);
+ if (ret) {
+ printf("Couldn't find UCLASS_MISC\n");
+ return ret;
+ }
+
+ uclass_foreach_dev(dev, uc) {
+ if (!(memcmp(dev->name, "comphy", 5))) {
+ if (i == cp_index) {
+ comphy_rx_training(dev, comphy_index);
+ return 0;
+ }
+
+ i++;
+ }
+ }
+
+ printf("Coudn't find comphy %d\n", cp_index);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ mvebu_comphy_rx_training, 3, 0, mvebu_comphy_rx_training_cmd,
+ "mvebu_comphy_rx_training <cp id> <comphy id>\n",
+ "\n\tRun COMPHY RX training sequence, the user must state CP index (0/1) and comphy ID (0/5)"
+);
diff --git a/roms/u-boot/cmd/nand.c b/roms/u-boot/cmd/nand.c
new file mode 100644
index 000000000..97e117a97
--- /dev/null
+++ b/roms/u-boot/cmd/nand.c
@@ -0,0 +1,1022 @@
+/*
+ * Driver for NAND support, Rick Bronson
+ * borrowed heavily from:
+ * (c) 1999 Machine Vision Holdings, Inc.
+ * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Ported 'dynenv' to 'nand env.oob' command
+ * (C) 2010 Nanometrics, Inc.
+ * 'dynenv' -- Dynamic environment offset in NAND OOB
+ * (C) Copyright 2006-2007 OpenMoko, Inc.
+ * Added 16-bit nand support
+ * (C) 2004 Texas Instruments
+ *
+ * Copyright 2010, 2012 Freescale Semiconductor
+ * The portions of this file whose copyright is held by Freescale and which
+ * are not considered a derived work of GPL v2-only code may be distributed
+ * and/or modified under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ */
+
+#include <common.h>
+#include <bootstage.h>
+#include <image.h>
+#include <asm/cache.h>
+#include <linux/mtd/mtd.h>
+#include <command.h>
+#include <console.h>
+#include <env.h>
+#include <watchdog.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <jffs2/jffs2.h>
+#include <nand.h>
+
+#include "legacy-mtd-utils.h"
+
+#if defined(CONFIG_CMD_MTDPARTS)
+
+/* partition handling routines */
+int mtdparts_init(void);
+int find_dev_and_part(const char *id, struct mtd_device **dev,
+ u8 *part_num, struct part_info **part);
+#endif
+
+static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
+ int repeat)
+{
+ int i;
+ u_char *datbuf, *oobbuf, *p;
+ static loff_t last;
+ int ret = 0;
+
+ if (repeat)
+ off = last + mtd->writesize;
+
+ last = off;
+
+ datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
+ if (!datbuf) {
+ puts("No memory for page buffer\n");
+ return 1;
+ }
+
+ oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
+ if (!oobbuf) {
+ puts("No memory for page buffer\n");
+ ret = 1;
+ goto free_dat;
+ }
+ off &= ~(mtd->writesize - 1);
+ loff_t addr = (loff_t) off;
+ struct mtd_oob_ops ops;
+ memset(&ops, 0, sizeof(ops));
+ ops.datbuf = datbuf;
+ ops.oobbuf = oobbuf;
+ ops.len = mtd->writesize;
+ ops.ooblen = mtd->oobsize;
+ ops.mode = MTD_OPS_RAW;
+ i = mtd_read_oob(mtd, addr, &ops);
+ if (i < 0) {
+ printf("Error (%d) reading page %08lx\n", i, off);
+ ret = 1;
+ goto free_all;
+ }
+ printf("Page %08lx dump:\n", off);
+
+ if (!only_oob) {
+ i = mtd->writesize >> 4;
+ p = datbuf;
+
+ while (i--) {
+ printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
+ " %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+ p[8], p[9], p[10], p[11], p[12], p[13], p[14],
+ p[15]);
+ p += 16;
+ }
+ }
+
+ puts("OOB:\n");
+ i = mtd->oobsize >> 3;
+ p = oobbuf;
+ while (i--) {
+ printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ p += 8;
+ }
+
+free_all:
+ free(oobbuf);
+free_dat:
+ free(datbuf);
+
+ return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int set_dev(int dev)
+{
+ struct mtd_info *mtd = get_nand_dev_by_index(dev);
+
+ if (!mtd)
+ return -ENODEV;
+
+ if (nand_curr_device == dev)
+ return 0;
+
+ printf("Device %d: %s", dev, mtd->name);
+ puts("... is now current device\n");
+ nand_curr_device = dev;
+
+#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
+ board_nand_select_device(mtd_to_nand(mtd), dev);
+#endif
+
+ return 0;
+}
+
+#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
+static void print_status(ulong start, ulong end, ulong erasesize, int status)
+{
+ /*
+ * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is
+ * not the same as others. Instead of bit 1 being lock, it is
+ * #lock_tight. To make the driver support either format, ignore bit 1
+ * and use only bit 0 and bit 2.
+ */
+ printf("%08lx - %08lx: %08lx blocks %s%s%s\n",
+ start,
+ end - 1,
+ (end - start) / erasesize,
+ ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
+ (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""),
+ ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
+}
+
+static void do_nand_status(struct mtd_info *mtd)
+{
+ ulong block_start = 0;
+ ulong off;
+ int last_status = -1;
+
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ /* check the WP bit */
+ nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+ printf("device is %swrite protected\n",
+ (nand_chip->read_byte(mtd) & 0x80 ?
+ "NOT " : ""));
+
+ for (off = 0; off < mtd->size; off += mtd->erasesize) {
+ int s = nand_get_lock_status(mtd, off);
+
+ /* print message only if status has changed */
+ if (s != last_status && off != 0) {
+ print_status(block_start, off, mtd->erasesize,
+ last_status);
+ block_start = off;
+ }
+ last_status = s;
+ }
+ /* Print the last block info */
+ print_status(block_start, off, mtd->erasesize, last_status);
+}
+#endif
+
+#ifdef CONFIG_ENV_OFFSET_OOB
+unsigned long nand_env_oob_offset;
+
+int do_nand_env_oob(struct cmd_tbl *cmdtp, int argc, char *const argv[])
+{
+ int ret;
+ uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
+ struct mtd_info *mtd = get_nand_dev_by_index(0);
+ char *cmd = argv[1];
+
+ if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
+ puts("no devices available\n");
+ return 1;
+ }
+
+ set_dev(0);
+
+ if (!strcmp(cmd, "get")) {
+ ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
+ if (ret)
+ return 1;
+
+ printf("0x%08lx\n", nand_env_oob_offset);
+ } else if (!strcmp(cmd, "set")) {
+ loff_t addr;
+ loff_t maxsize;
+ struct mtd_oob_ops ops;
+ int idx = 0;
+
+ if (argc < 3)
+ goto usage;
+
+ mtd = get_nand_dev_by_index(idx);
+ /* We don't care about size, or maxsize. */
+ if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
+ MTD_DEV_TYPE_NAND, mtd->size)) {
+ puts("Offset or partition name expected\n");
+ return 1;
+ }
+ if (set_dev(idx)) {
+ puts("Offset or partition name expected\n");
+ return 1;
+ }
+
+ if (idx != 0) {
+ puts("Partition not on first NAND device\n");
+ return 1;
+ }
+
+ if (mtd->oobavail < ENV_OFFSET_SIZE) {
+ printf("Insufficient available OOB bytes:\n"
+ "%d OOB bytes available but %d required for "
+ "env.oob support\n",
+ mtd->oobavail, ENV_OFFSET_SIZE);
+ return 1;
+ }
+
+ if ((addr & (mtd->erasesize - 1)) != 0) {
+ printf("Environment offset must be block-aligned\n");
+ return 1;
+ }
+
+ ops.datbuf = NULL;
+ ops.mode = MTD_OOB_AUTO;
+ ops.ooboffs = 0;
+ ops.ooblen = ENV_OFFSET_SIZE;
+ ops.oobbuf = (void *) oob_buf;
+
+ oob_buf[0] = ENV_OOB_MARKER;
+ oob_buf[1] = addr / mtd->erasesize;
+
+ ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
+ if (ret) {
+ printf("Error writing OOB block 0\n");
+ return ret;
+ }
+
+ ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
+ if (ret) {
+ printf("Error reading env offset in OOB\n");
+ return ret;
+ }
+
+ if (addr != nand_env_oob_offset) {
+ printf("Verification of env offset in OOB failed: "
+ "0x%08llx expected but got 0x%08lx\n",
+ (unsigned long long)addr, nand_env_oob_offset);
+ return 1;
+ }
+ } else {
+ goto usage;
+ }
+
+ return ret;
+
+usage:
+ return CMD_RET_USAGE;
+}
+
+#endif
+
+static void nand_print_and_set_info(int idx)
+{
+ struct mtd_info *mtd;
+ struct nand_chip *chip;
+
+ mtd = get_nand_dev_by_index(idx);
+ if (!mtd)
+ return;
+
+ chip = mtd_to_nand(mtd);
+ printf("Device %d: ", idx);
+ if (chip->numchips > 1)
+ printf("%dx ", chip->numchips);
+ printf("%s, sector size %u KiB\n",
+ mtd->name, mtd->erasesize >> 10);
+ printf(" Page size %8d b\n", mtd->writesize);
+ printf(" OOB size %8d b\n", mtd->oobsize);
+ printf(" Erase size %8d b\n", mtd->erasesize);
+ printf(" subpagesize %8d b\n", chip->subpagesize);
+ printf(" options 0x%08x\n", chip->options);
+ printf(" bbt options 0x%08x\n", chip->bbt_options);
+
+ /* Set geometry info */
+ env_set_hex("nand_writesize", mtd->writesize);
+ env_set_hex("nand_oobsize", mtd->oobsize);
+ env_set_hex("nand_erasesize", mtd->erasesize);
+}
+
+static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
+ ulong count, int read, int no_verify)
+{
+ int ret = 0;
+
+ while (count--) {
+ /* Raw access */
+ mtd_oob_ops_t ops = {
+ .datbuf = (u8 *)addr,
+ .oobbuf = ((u8 *)addr) + mtd->writesize,
+ .len = mtd->writesize,
+ .ooblen = mtd->oobsize,
+ .mode = MTD_OPS_RAW
+ };
+
+ if (read) {
+ ret = mtd_read_oob(mtd, off, &ops);
+ } else {
+ ret = mtd_write_oob(mtd, off, &ops);
+ if (!ret && !no_verify)
+ ret = nand_verify_page_oob(mtd, &ops, off);
+ }
+
+ if (ret) {
+ printf("%s: error at offset %llx, ret %d\n",
+ __func__, (long long)off, ret);
+ break;
+ }
+
+ addr += mtd->writesize + mtd->oobsize;
+ off += mtd->writesize;
+ }
+
+ return ret;
+}
+
+/* Adjust a chip/partition size down for bad blocks so we don't
+ * read/write past the end of a chip/partition by accident.
+ */
+static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
+{
+ /* We grab the nand info object here fresh because this is usually
+ * called after arg_off_size() which can change the value of dev.
+ */
+ struct mtd_info *mtd = get_nand_dev_by_index(dev);
+ loff_t maxoffset = offset + *size;
+ int badblocks = 0;
+
+ /* count badblocks in NAND from offset to offset + size */
+ for (; offset < maxoffset; offset += mtd->erasesize) {
+ if (nand_block_isbad(mtd, offset))
+ badblocks++;
+ }
+ /* adjust size if any bad blocks found */
+ if (badblocks) {
+ *size -= badblocks * mtd->erasesize;
+ printf("size adjusted to 0x%llx (%d bad blocks)\n",
+ (unsigned long long)*size, badblocks);
+ }
+}
+
+static int do_nand(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int i, ret = 0;
+ ulong addr;
+ loff_t off, size, maxsize;
+ char *cmd, *s;
+ struct mtd_info *mtd;
+#ifdef CONFIG_SYS_NAND_QUIET
+ int quiet = CONFIG_SYS_NAND_QUIET;
+#else
+ int quiet = 0;
+#endif
+ const char *quiet_str = env_get("quiet");
+ int dev = nand_curr_device;
+ int repeat = flag & CMD_FLAG_REPEAT;
+
+ /* at least two arguments please */
+ if (argc < 2)
+ goto usage;
+
+ if (quiet_str)
+ quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
+
+ cmd = argv[1];
+
+ /* Only "dump" is repeatable. */
+ if (repeat && strcmp(cmd, "dump"))
+ return 0;
+
+ if (strcmp(cmd, "info") == 0) {
+
+ putc('\n');
+ for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
+ nand_print_and_set_info(i);
+ return 0;
+ }
+
+ if (strcmp(cmd, "device") == 0) {
+ if (argc < 3) {
+ putc('\n');
+ if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
+ puts("no devices available\n");
+ else
+ nand_print_and_set_info(dev);
+ return 0;
+ }
+
+ dev = (int)simple_strtoul(argv[2], NULL, 10);
+ set_dev(dev);
+
+ return 0;
+ }
+
+#ifdef CONFIG_ENV_OFFSET_OOB
+ /* this command operates only on the first nand device */
+ if (strcmp(cmd, "env.oob") == 0)
+ return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
+#endif
+
+ /* The following commands operate on the current device, unless
+ * overridden by a partition specifier. Note that if somehow the
+ * current device is invalid, it will have to be changed to a valid
+ * one before these commands can run, even if a partition specifier
+ * for another device is to be used.
+ */
+ mtd = get_nand_dev_by_index(dev);
+ if (!mtd) {
+ puts("\nno devices available\n");
+ return 1;
+ }
+
+ if (strcmp(cmd, "bad") == 0) {
+ printf("\nDevice %d bad blocks:\n", dev);
+ for (off = 0; off < mtd->size; off += mtd->erasesize)
+ if (nand_block_isbad(mtd, off))
+ printf(" %08llx\n", (unsigned long long)off);
+ return 0;
+ }
+
+ /*
+ * Syntax is:
+ * 0 1 2 3 4
+ * nand erase [clean] [off size]
+ */
+ if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
+ nand_erase_options_t opts;
+ /* "clean" at index 2 means request to write cleanmarker */
+ int clean = argc > 2 && !strcmp("clean", argv[2]);
+ int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
+ int o = (clean || scrub_yes) ? 3 : 2;
+ int scrub = !strncmp(cmd, "scrub", 5);
+ int spread = 0;
+ int args = 2;
+ const char *scrub_warn =
+ "Warning: "
+ "scrub option will erase all factory set bad blocks!\n"
+ " "
+ "There is no reliable way to recover them.\n"
+ " "
+ "Use this command only for testing purposes if you\n"
+ " "
+ "are sure of what you are doing!\n"
+ "\nReally scrub this NAND flash? <y/N>\n";
+
+ if (cmd[5] != 0) {
+ if (!strcmp(&cmd[5], ".spread")) {
+ spread = 1;
+ } else if (!strcmp(&cmd[5], ".part")) {
+ args = 1;
+ } else if (!strcmp(&cmd[5], ".chip")) {
+ args = 0;
+ } else {
+ goto usage;
+ }
+ }
+
+ /*
+ * Don't allow missing arguments to cause full chip/partition
+ * erases -- easy to do accidentally, e.g. with a misspelled
+ * variable name.
+ */
+ if (argc != o + args)
+ goto usage;
+
+ printf("\nNAND %s: ", cmd);
+ /* skip first two or three arguments, look for offset and size */
+ if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
+ &maxsize, MTD_DEV_TYPE_NAND,
+ mtd->size) != 0)
+ return 1;
+
+ if (set_dev(dev))
+ return 1;
+
+ mtd = get_nand_dev_by_index(dev);
+
+ memset(&opts, 0, sizeof(opts));
+ opts.offset = off;
+ opts.length = size;
+ opts.jffs2 = clean;
+ opts.quiet = quiet;
+ opts.spread = spread;
+
+ if (scrub) {
+ if (scrub_yes) {
+ opts.scrub = 1;
+ } else {
+ puts(scrub_warn);
+ if (confirm_yesno()) {
+ opts.scrub = 1;
+ } else {
+ puts("scrub aborted\n");
+ return 1;
+ }
+ }
+ }
+ ret = nand_erase_opts(mtd, &opts);
+ printf("%s\n", ret ? "ERROR" : "OK");
+
+ return ret == 0 ? 0 : 1;
+ }
+
+ if (strncmp(cmd, "dump", 4) == 0) {
+ if (argc < 3)
+ goto usage;
+
+ off = (int)simple_strtoul(argv[2], NULL, 16);
+ ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
+
+ return ret == 0 ? 1 : 0;
+ }
+
+ if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
+ size_t rwsize;
+ ulong pagecount = 1;
+ int read;
+ int raw = 0;
+ int no_verify = 0;
+
+ if (argc < 4)
+ goto usage;
+
+ addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+
+ read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
+ printf("\nNAND %s: ", read ? "read" : "write");
+
+ s = strchr(cmd, '.');
+
+ if (s && !strncmp(s, ".raw", 4)) {
+ raw = 1;
+
+ if (!strcmp(s, ".raw.noverify"))
+ no_verify = 1;
+
+ if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
+ MTD_DEV_TYPE_NAND,
+ mtd->size))
+ return 1;
+
+ if (set_dev(dev))
+ return 1;
+
+ mtd = get_nand_dev_by_index(dev);
+
+ if (argc > 4 && !str2long(argv[4], &pagecount)) {
+ printf("'%s' is not a number\n", argv[4]);
+ return 1;
+ }
+
+ if (pagecount * mtd->writesize > size) {
+ puts("Size exceeds partition or device limit\n");
+ return -1;
+ }
+
+ rwsize = pagecount * (mtd->writesize + mtd->oobsize);
+ } else {
+ if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
+ &size, &maxsize,
+ MTD_DEV_TYPE_NAND,
+ mtd->size) != 0)
+ return 1;
+
+ if (set_dev(dev))
+ return 1;
+
+ /* size is unspecified */
+ if (argc < 5)
+ adjust_size_for_badblocks(&size, off, dev);
+ rwsize = size;
+ }
+
+ mtd = get_nand_dev_by_index(dev);
+
+ if (!s || !strcmp(s, ".jffs2") ||
+ !strcmp(s, ".e") || !strcmp(s, ".i")) {
+ if (read)
+ ret = nand_read_skip_bad(mtd, off, &rwsize,
+ NULL, maxsize,
+ (u_char *)addr);
+ else
+ ret = nand_write_skip_bad(mtd, off, &rwsize,
+ NULL, maxsize,
+ (u_char *)addr,
+ WITH_WR_VERIFY);
+#ifdef CONFIG_CMD_NAND_TRIMFFS
+ } else if (!strcmp(s, ".trimffs")) {
+ if (read) {
+ printf("Unknown nand command suffix '%s'\n", s);
+ return 1;
+ }
+ ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
+ maxsize, (u_char *)addr,
+ WITH_DROP_FFS | WITH_WR_VERIFY);
+#endif
+ } else if (!strcmp(s, ".oob")) {
+ /* out-of-band data */
+ mtd_oob_ops_t ops = {
+ .oobbuf = (u8 *)addr,
+ .ooblen = rwsize,
+ .mode = MTD_OPS_RAW
+ };
+
+ if (read)
+ ret = mtd_read_oob(mtd, off, &ops);
+ else
+ ret = mtd_write_oob(mtd, off, &ops);
+ } else if (raw) {
+ ret = raw_access(mtd, addr, off, pagecount, read,
+ no_verify);
+ } else {
+ printf("Unknown nand command suffix '%s'.\n", s);
+ return 1;
+ }
+
+ printf(" %zu bytes %s: %s\n", rwsize,
+ read ? "read" : "written", ret ? "ERROR" : "OK");
+
+ return ret == 0 ? 0 : 1;
+ }
+
+#ifdef CONFIG_CMD_NAND_TORTURE
+ if (strcmp(cmd, "torture") == 0) {
+ loff_t endoff;
+ unsigned int failed = 0, passed = 0;
+
+ if (argc < 3)
+ goto usage;
+
+ if (!str2off(argv[2], &off)) {
+ puts("Offset is not a valid number\n");
+ return 1;
+ }
+
+ size = mtd->erasesize;
+ if (argc > 3) {
+ if (!str2off(argv[3], &size)) {
+ puts("Size is not a valid number\n");
+ return 1;
+ }
+ }
+
+ endoff = off + size;
+ if (endoff > mtd->size) {
+ puts("Arguments beyond end of NAND\n");
+ return 1;
+ }
+
+ off = round_down(off, mtd->erasesize);
+ endoff = round_up(endoff, mtd->erasesize);
+ size = endoff - off;
+ printf("\nNAND torture: device %d offset 0x%llx size 0x%llx (block size 0x%x)\n",
+ dev, off, size, mtd->erasesize);
+ while (off < endoff) {
+ ret = nand_torture(mtd, off);
+ if (ret) {
+ failed++;
+ printf(" block at 0x%llx failed\n", off);
+ } else {
+ passed++;
+ }
+ off += mtd->erasesize;
+ }
+ printf(" Passed: %u, failed: %u\n", passed, failed);
+ return failed != 0;
+ }
+#endif
+
+ if (strcmp(cmd, "markbad") == 0) {
+ argc -= 2;
+ argv += 2;
+
+ if (argc <= 0)
+ goto usage;
+
+ while (argc > 0) {
+ addr = simple_strtoul(*argv, NULL, 16);
+
+ if (mtd_block_markbad(mtd, addr)) {
+ printf("block 0x%08lx NOT marked "
+ "as bad! ERROR %d\n",
+ addr, ret);
+ ret = 1;
+ } else {
+ printf("block 0x%08lx successfully "
+ "marked as bad\n",
+ addr);
+ }
+ --argc;
+ ++argv;
+ }
+ return ret;
+ }
+
+ if (strcmp(cmd, "biterr") == 0) {
+ /* todo */
+ return 1;
+ }
+
+#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
+ if (strcmp(cmd, "lock") == 0) {
+ int tight = 0;
+ int status = 0;
+ if (argc == 3) {
+ if (!strcmp("tight", argv[2]))
+ tight = 1;
+ if (!strcmp("status", argv[2]))
+ status = 1;
+ }
+ if (status) {
+ do_nand_status(mtd);
+ } else {
+ if (!nand_lock(mtd, tight)) {
+ puts("NAND flash successfully locked\n");
+ } else {
+ puts("Error locking NAND flash\n");
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ if (strncmp(cmd, "unlock", 5) == 0) {
+ int allexcept = 0;
+
+ s = strchr(cmd, '.');
+
+ if (s && !strcmp(s, ".allexcept"))
+ allexcept = 1;
+
+ if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
+ &maxsize, MTD_DEV_TYPE_NAND,
+ mtd->size) < 0)
+ return 1;
+
+ if (set_dev(dev))
+ return 1;
+
+ mtd = get_nand_dev_by_index(dev);
+
+ if (!nand_unlock(mtd, off, size, allexcept)) {
+ puts("NAND flash successfully unlocked\n");
+ } else {
+ puts("Error unlocking NAND flash, "
+ "write and erase will probably fail\n");
+ return 1;
+ }
+ return 0;
+ }
+#endif
+
+usage:
+ return CMD_RET_USAGE;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char nand_help_text[] =
+ "info - show available NAND devices\n"
+ "nand device [dev] - show or set current device\n"
+ "nand read - addr off|partition size\n"
+ "nand write - addr off|partition size\n"
+ " read/write 'size' bytes starting at offset 'off'\n"
+ " to/from memory address 'addr', skipping bad blocks.\n"
+ "nand read.raw - addr off|partition [count]\n"
+ "nand write.raw[.noverify] - addr off|partition [count]\n"
+ " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
+#ifdef CONFIG_CMD_NAND_TRIMFFS
+ "nand write.trimffs - addr off|partition size\n"
+ " write 'size' bytes starting at offset 'off' from memory address\n"
+ " 'addr', skipping bad blocks and dropping any pages at the end\n"
+ " of eraseblocks that contain only 0xFF\n"
+#endif
+ "nand erase[.spread] [clean] off size - erase 'size' bytes "
+ "from offset 'off'\n"
+ " With '.spread', erase enough for given file size, otherwise,\n"
+ " 'size' includes skipped bad blocks.\n"
+ "nand erase.part [clean] partition - erase entire mtd partition'\n"
+ "nand erase.chip [clean] - erase entire chip'\n"
+ "nand bad - show bad blocks\n"
+ "nand dump[.oob] off - dump page\n"
+#ifdef CONFIG_CMD_NAND_TORTURE
+ "nand torture off - torture one block at offset\n"
+ "nand torture off [size] - torture blocks from off to off+size\n"
+#endif
+ "nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
+ " really clean NAND erasing bad blocks (UNSAFE)\n"
+ "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
+ "nand biterr off - make a bit error at offset (UNSAFE)"
+#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
+ "\n"
+ "nand lock [tight] [status]\n"
+ " bring nand to lock state or display locked pages\n"
+ "nand unlock[.allexcept] [offset] [size] - unlock section"
+#endif
+#ifdef CONFIG_ENV_OFFSET_OOB
+ "\n"
+ "nand env.oob - environment offset in OOB of block 0 of"
+ " first device.\n"
+ "nand env.oob set off|partition - set enviromnent offset\n"
+ "nand env.oob get - get environment offset"
+#endif
+ "";
+#endif
+
+U_BOOT_CMD(
+ nand, CONFIG_SYS_MAXARGS, 1, do_nand,
+ "NAND sub-system", nand_help_text
+);
+
+static int nand_load_image(struct cmd_tbl *cmdtp, struct mtd_info *mtd,
+ ulong offset, ulong addr, char *cmd)
+{
+ int r;
+ char *s;
+ size_t cnt;
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ image_header_t *hdr;
+#endif
+#if defined(CONFIG_FIT)
+ const void *fit_hdr = NULL;
+#endif
+
+ s = strchr(cmd, '.');
+ if (s != NULL &&
+ (strcmp(s, ".jffs2") && strcmp(s, ".e") && strcmp(s, ".i"))) {
+ printf("Unknown nand load suffix '%s'\n", s);
+ bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
+ return 1;
+ }
+
+ printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
+
+ cnt = mtd->writesize;
+ r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
+ (u_char *)addr);
+ if (r) {
+ puts("** Read error\n");
+ bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NAND_HDR_READ);
+
+ switch (genimg_get_format ((void *)addr)) {
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ case IMAGE_FORMAT_LEGACY:
+ hdr = (image_header_t *)addr;
+
+ bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
+ image_print_contents (hdr);
+
+ cnt = image_get_image_size (hdr);
+ break;
+#endif
+#if defined(CONFIG_FIT)
+ case IMAGE_FORMAT_FIT:
+ fit_hdr = (const void *)addr;
+ puts ("Fit image detected...\n");
+
+ cnt = fit_get_size (fit_hdr);
+ break;
+#endif
+ default:
+ bootstage_error(BOOTSTAGE_ID_NAND_TYPE);
+ puts ("** Unknown image type\n");
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
+
+ r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
+ (u_char *)addr);
+ if (r) {
+ puts("** Read error\n");
+ bootstage_error(BOOTSTAGE_ID_NAND_READ);
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NAND_READ);
+
+#if defined(CONFIG_FIT)
+ /* This cannot be done earlier, we need complete FIT image in RAM first */
+ if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) {
+ if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
+ bootstage_error(BOOTSTAGE_ID_NAND_FIT_READ);
+ puts ("** Bad FIT image format\n");
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NAND_FIT_READ_OK);
+ fit_print_contents (fit_hdr);
+ }
+#endif
+
+ /* Loading ok, update default load address */
+
+ image_load_addr = addr;
+
+ return bootm_maybe_autostart(cmdtp, cmd);
+}
+
+static int do_nandboot(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *boot_device = NULL;
+ int idx;
+ ulong addr, offset = 0;
+ struct mtd_info *mtd;
+#if defined(CONFIG_CMD_MTDPARTS)
+ struct mtd_device *dev;
+ struct part_info *part;
+ u8 pnum;
+
+ if (argc >= 2) {
+ char *p = (argc == 2) ? argv[1] : argv[2];
+ if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
+ (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
+ if (dev->id->type != MTD_DEV_TYPE_NAND) {
+ puts("Not a NAND device\n");
+ return 1;
+ }
+ if (argc > 3)
+ goto usage;
+ if (argc == 3)
+ addr = simple_strtoul(argv[1], NULL, 16);
+ else
+ addr = CONFIG_SYS_LOAD_ADDR;
+
+ mtd = get_nand_dev_by_index(dev->id->num);
+ return nand_load_image(cmdtp, mtd, part->offset,
+ addr, argv[0]);
+ }
+ }
+#endif
+
+ bootstage_mark(BOOTSTAGE_ID_NAND_PART);
+ switch (argc) {
+ case 1:
+ addr = CONFIG_SYS_LOAD_ADDR;
+ boot_device = env_get("bootdevice");
+ break;
+ case 2:
+ addr = simple_strtoul(argv[1], NULL, 16);
+ boot_device = env_get("bootdevice");
+ break;
+ case 3:
+ addr = simple_strtoul(argv[1], NULL, 16);
+ boot_device = argv[2];
+ break;
+ case 4:
+ addr = simple_strtoul(argv[1], NULL, 16);
+ boot_device = argv[2];
+ offset = simple_strtoul(argv[3], NULL, 16);
+ break;
+ default:
+#if defined(CONFIG_CMD_MTDPARTS)
+usage:
+#endif
+ bootstage_error(BOOTSTAGE_ID_NAND_SUFFIX);
+ return CMD_RET_USAGE;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NAND_SUFFIX);
+
+ if (!boot_device) {
+ puts("\n** No boot device **\n");
+ bootstage_error(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NAND_BOOT_DEVICE);
+
+ idx = simple_strtoul(boot_device, NULL, 16);
+
+ mtd = get_nand_dev_by_index(idx);
+ if (!mtd) {
+ printf("\n** Device %d not available\n", idx);
+ bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
+ return 1;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
+
+ return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
+}
+
+U_BOOT_CMD(nboot, 4, 1, do_nandboot,
+ "boot from NAND device",
+ "[partition] | [[[loadAddr] dev] offset]"
+);
diff --git a/roms/u-boot/cmd/net.c b/roms/u-boot/cmd/net.c
new file mode 100644
index 000000000..beb2877df
--- /dev/null
+++ b/roms/u-boot/cmd/net.c
@@ -0,0 +1,482 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <bootstage.h>
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <net.h>
+#include <net/udp.h>
+#include <net/sntp.h>
+
+static int netboot_common(enum proto_t, struct cmd_tbl *, int, char * const []);
+
+#ifdef CONFIG_CMD_BOOTP
+static int do_bootp(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return netboot_common(BOOTP, cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+ bootp, 3, 1, do_bootp,
+ "boot image via network using BOOTP/TFTP protocol",
+ "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
+
+#ifdef CONFIG_CMD_TFTPBOOT
+int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int ret;
+
+ bootstage_mark_name(BOOTSTAGE_KERNELREAD_START, "tftp_start");
+ ret = netboot_common(TFTPGET, cmdtp, argc, argv);
+ bootstage_mark_name(BOOTSTAGE_KERNELREAD_STOP, "tftp_done");
+ return ret;
+}
+
+U_BOOT_CMD(
+ tftpboot, 3, 1, do_tftpb,
+ "boot image via network using TFTP protocol",
+ "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
+
+#ifdef CONFIG_CMD_TFTPPUT
+static int do_tftpput(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return netboot_common(TFTPPUT, cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+ tftpput, 4, 1, do_tftpput,
+ "TFTP put command, for uploading files to a server",
+ "Address Size [[hostIPaddr:]filename]"
+);
+#endif
+
+#ifdef CONFIG_CMD_TFTPSRV
+static int do_tftpsrv(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return netboot_common(TFTPSRV, cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+ tftpsrv, 2, 1, do_tftpsrv,
+ "act as a TFTP server and boot the first received file",
+ "[loadAddress]\n"
+ "Listen for an incoming TFTP transfer, receive a file and boot it.\n"
+ "The transfer is aborted if a transfer has not been started after\n"
+ "about 50 seconds or if Ctrl-C is pressed."
+);
+#endif
+
+
+#ifdef CONFIG_CMD_RARP
+int do_rarpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return netboot_common(RARP, cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+ rarpboot, 3, 1, do_rarpb,
+ "boot image via network using RARP/TFTP protocol",
+ "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
+
+#if defined(CONFIG_CMD_DHCP)
+static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return netboot_common(DHCP, cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+ dhcp, 3, 1, do_dhcp,
+ "boot image via network using DHCP/TFTP protocol",
+ "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
+
+#if defined(CONFIG_CMD_NFS)
+static int do_nfs(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return netboot_common(NFS, cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+ nfs, 3, 1, do_nfs,
+ "boot image via network using NFS protocol",
+ "[loadAddress] [[hostIPaddr:]bootfilename]"
+);
+#endif
+
+static void netboot_update_env(void)
+{
+ char tmp[22];
+
+ if (net_gateway.s_addr) {
+ ip_to_string(net_gateway, tmp);
+ env_set("gatewayip", tmp);
+ }
+
+ if (net_netmask.s_addr) {
+ ip_to_string(net_netmask, tmp);
+ env_set("netmask", tmp);
+ }
+
+#ifdef CONFIG_CMD_BOOTP
+ if (net_hostname[0])
+ env_set("hostname", net_hostname);
+#endif
+
+#ifdef CONFIG_CMD_BOOTP
+ if (net_root_path[0])
+ env_set("rootpath", net_root_path);
+#endif
+
+ if (net_ip.s_addr) {
+ ip_to_string(net_ip, tmp);
+ env_set("ipaddr", tmp);
+ }
+#if !defined(CONFIG_BOOTP_SERVERIP)
+ /*
+ * Only attempt to change serverip if net/bootp.c:store_net_params()
+ * could have set it
+ */
+ if (net_server_ip.s_addr) {
+ ip_to_string(net_server_ip, tmp);
+ env_set("serverip", tmp);
+ }
+#endif
+ if (net_dns_server.s_addr) {
+ ip_to_string(net_dns_server, tmp);
+ env_set("dnsip", tmp);
+ }
+#if defined(CONFIG_BOOTP_DNS2)
+ if (net_dns_server2.s_addr) {
+ ip_to_string(net_dns_server2, tmp);
+ env_set("dnsip2", tmp);
+ }
+#endif
+#ifdef CONFIG_CMD_BOOTP
+ if (net_nis_domain[0])
+ env_set("domain", net_nis_domain);
+#endif
+
+#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET)
+ if (net_ntp_time_offset) {
+ sprintf(tmp, "%d", net_ntp_time_offset);
+ env_set("timeoffset", tmp);
+ }
+#endif
+#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_NTPSERVER)
+ if (net_ntp_server.s_addr) {
+ ip_to_string(net_ntp_server, tmp);
+ env_set("ntpserverip", tmp);
+ }
+#endif
+}
+
+static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc,
+ char *const argv[])
+{
+ char *s;
+ char *end;
+ int rcode = 0;
+ int size;
+ ulong addr;
+
+ net_boot_file_name_explicit = false;
+
+ /* pre-set image_load_addr */
+ s = env_get("loadaddr");
+ if (s != NULL)
+ image_load_addr = simple_strtoul(s, NULL, 16);
+
+ switch (argc) {
+ case 1:
+ /* refresh bootfile name from env */
+ copy_filename(net_boot_file_name, env_get("bootfile"),
+ sizeof(net_boot_file_name));
+ break;
+
+ case 2: /*
+ * Only one arg - accept two forms:
+ * Just load address, or just boot file name. The latter
+ * form must be written in a format which can not be
+ * mis-interpreted as a valid number.
+ */
+ addr = simple_strtoul(argv[1], &end, 16);
+ if (end == (argv[1] + strlen(argv[1]))) {
+ image_load_addr = addr;
+ /* refresh bootfile name from env */
+ copy_filename(net_boot_file_name, env_get("bootfile"),
+ sizeof(net_boot_file_name));
+ } else {
+ net_boot_file_name_explicit = true;
+ copy_filename(net_boot_file_name, argv[1],
+ sizeof(net_boot_file_name));
+ }
+ break;
+
+ case 3:
+ image_load_addr = simple_strtoul(argv[1], NULL, 16);
+ net_boot_file_name_explicit = true;
+ copy_filename(net_boot_file_name, argv[2],
+ sizeof(net_boot_file_name));
+
+ break;
+
+#ifdef CONFIG_CMD_TFTPPUT
+ case 4:
+ if (strict_strtoul(argv[1], 16, &image_save_addr) < 0 ||
+ strict_strtoul(argv[2], 16, &image_save_size) < 0) {
+ printf("Invalid address/size\n");
+ return CMD_RET_USAGE;
+ }
+ net_boot_file_name_explicit = true;
+ copy_filename(net_boot_file_name, argv[3],
+ sizeof(net_boot_file_name));
+ break;
+#endif
+ default:
+ bootstage_error(BOOTSTAGE_ID_NET_START);
+ return CMD_RET_USAGE;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NET_START);
+
+ size = net_loop(proto);
+ if (size < 0) {
+ bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
+ return CMD_RET_FAILURE;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
+
+ /* net_loop ok, update environment */
+ netboot_update_env();
+
+ /* done if no file was loaded (no errors though) */
+ if (size == 0) {
+ bootstage_error(BOOTSTAGE_ID_NET_LOADED);
+ return CMD_RET_SUCCESS;
+ }
+
+ bootstage_mark(BOOTSTAGE_ID_NET_LOADED);
+
+ rcode = bootm_maybe_autostart(cmdtp, argv[0]);
+
+ if (rcode == CMD_RET_SUCCESS)
+ bootstage_mark(BOOTSTAGE_ID_NET_DONE);
+ else
+ bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
+ return rcode;
+}
+
+#if defined(CONFIG_CMD_PING)
+static int do_ping(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ net_ping_ip = string_to_ip(argv[1]);
+ if (net_ping_ip.s_addr == 0)
+ return CMD_RET_USAGE;
+
+ if (net_loop(PING) < 0) {
+ printf("ping failed; host %s is not alive\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("host %s is alive\n", argv[1]);
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ ping, 2, 1, do_ping,
+ "send ICMP ECHO_REQUEST to network host",
+ "pingAddress"
+);
+#endif
+
+#if defined(CONFIG_CMD_CDP)
+
+static void cdp_update_env(void)
+{
+ char tmp[16];
+
+ if (cdp_appliance_vlan != htons(-1)) {
+ printf("CDP offered appliance VLAN %d\n",
+ ntohs(cdp_appliance_vlan));
+ vlan_to_string(cdp_appliance_vlan, tmp);
+ env_set("vlan", tmp);
+ net_our_vlan = cdp_appliance_vlan;
+ }
+
+ if (cdp_native_vlan != htons(-1)) {
+ printf("CDP offered native VLAN %d\n", ntohs(cdp_native_vlan));
+ vlan_to_string(cdp_native_vlan, tmp);
+ env_set("nvlan", tmp);
+ net_native_vlan = cdp_native_vlan;
+ }
+}
+
+int do_cdp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int r;
+
+ r = net_loop(CDP);
+ if (r < 0) {
+ printf("cdp failed; perhaps not a CISCO switch?\n");
+ return CMD_RET_FAILURE;
+ }
+
+ cdp_update_env();
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ cdp, 1, 1, do_cdp,
+ "Perform CDP network configuration",
+ "\n"
+);
+#endif
+
+#if defined(CONFIG_CMD_SNTP)
+static struct udp_ops sntp_ops = {
+ .prereq = sntp_prereq,
+ .start = sntp_start,
+ .data = NULL,
+};
+
+int do_sntp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *toff;
+
+ if (argc < 2) {
+ net_ntp_server = env_get_ip("ntpserverip");
+ if (net_ntp_server.s_addr == 0) {
+ printf("ntpserverip not set\n");
+ return CMD_RET_FAILURE;
+ }
+ } else {
+ net_ntp_server = string_to_ip(argv[1]);
+ if (net_ntp_server.s_addr == 0) {
+ printf("Bad NTP server IP address\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ toff = env_get("timeoffset");
+ if (toff == NULL)
+ net_ntp_time_offset = 0;
+ else
+ net_ntp_time_offset = simple_strtol(toff, NULL, 10);
+
+ if (udp_loop(&sntp_ops) < 0) {
+ printf("SNTP failed: host %pI4 not responding\n",
+ &net_ntp_server);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ sntp, 2, 1, do_sntp,
+ "synchronize RTC via network",
+ "[NTP server IP]\n"
+);
+#endif
+
+#if defined(CONFIG_CMD_DNS)
+int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc == 1)
+ return CMD_RET_USAGE;
+
+ /*
+ * We should check for a valid hostname:
+ * - Each label must be between 1 and 63 characters long
+ * - the entire hostname has a maximum of 255 characters
+ * - only the ASCII letters 'a' through 'z' (case-insensitive),
+ * the digits '0' through '9', and the hyphen
+ * - cannot begin or end with a hyphen
+ * - no other symbols, punctuation characters, or blank spaces are
+ * permitted
+ * but hey - this is a minimalist implmentation, so only check length
+ * and let the name server deal with things.
+ */
+ if (strlen(argv[1]) >= 255) {
+ printf("dns error: hostname too long\n");
+ return CMD_RET_FAILURE;
+ }
+
+ net_dns_resolve = argv[1];
+
+ if (argc == 3)
+ net_dns_env_var = argv[2];
+ else
+ net_dns_env_var = NULL;
+
+ if (net_loop(DNS) < 0) {
+ printf("dns lookup of %s failed, check setup\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ dns, 3, 1, do_dns,
+ "lookup the IP of a hostname",
+ "hostname [envvar]"
+);
+
+#endif /* CONFIG_CMD_DNS */
+
+#if defined(CONFIG_CMD_LINK_LOCAL)
+static int do_link_local(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char tmp[22];
+
+ if (net_loop(LINKLOCAL) < 0)
+ return CMD_RET_FAILURE;
+
+ net_gateway.s_addr = 0;
+ ip_to_string(net_gateway, tmp);
+ env_set("gatewayip", tmp);
+
+ ip_to_string(net_netmask, tmp);
+ env_set("netmask", tmp);
+
+ ip_to_string(net_ip, tmp);
+ env_set("ipaddr", tmp);
+ env_set("llipaddr", tmp); /* store this for next time */
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ linklocal, 1, 1, do_link_local,
+ "acquire a network IP address using the link-local protocol",
+ ""
+);
+
+#endif /* CONFIG_CMD_LINK_LOCAL */
diff --git a/roms/u-boot/cmd/nvedit.c b/roms/u-boot/cmd/nvedit.c
new file mode 100644
index 000000000..d14ba10ce
--- /dev/null
+++ b/roms/u-boot/cmd/nvedit.c
@@ -0,0 +1,1585 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2013
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ */
+
+/*
+ * Support for persistent environment data
+ *
+ * The "environment" is stored on external storage as a list of '\0'
+ * terminated "name=value" strings. The end of the list is marked by
+ * a double '\0'. The environment is preceded by a 32 bit CRC over
+ * the data part and, in case of redundant environment, a byte of
+ * flags.
+ *
+ * This linearized representation will also be used before
+ * relocation, i. e. as long as we don't have a full C runtime
+ * environment. After that, we use a hash table.
+ */
+
+#include <common.h>
+#include <cli.h>
+#include <command.h>
+#include <console.h>
+#include <env.h>
+#include <env_internal.h>
+#include <log.h>
+#include <net.h>
+#include <search.h>
+#include <errno.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <asm/global_data.h>
+#include <linux/bitops.h>
+#include <u-boot/crc.h>
+#include <watchdog.h>
+#include <linux/stddef.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_ENV_IS_IN_EEPROM) || \
+ defined(CONFIG_ENV_IS_IN_FLASH) || \
+ defined(CONFIG_ENV_IS_IN_MMC) || \
+ defined(CONFIG_ENV_IS_IN_FAT) || \
+ defined(CONFIG_ENV_IS_IN_EXT4) || \
+ defined(CONFIG_ENV_IS_IN_NAND) || \
+ defined(CONFIG_ENV_IS_IN_NVRAM) || \
+ defined(CONFIG_ENV_IS_IN_ONENAND) || \
+ defined(CONFIG_ENV_IS_IN_SATA) || \
+ defined(CONFIG_ENV_IS_IN_SPI_FLASH) || \
+ defined(CONFIG_ENV_IS_IN_REMOTE) || \
+ defined(CONFIG_ENV_IS_IN_UBI)
+
+#define ENV_IS_IN_DEVICE
+
+#endif
+
+#if !defined(ENV_IS_IN_DEVICE) && \
+ !defined(CONFIG_ENV_IS_NOWHERE)
+# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|MMC|FAT|EXT4|\
+NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE
+#endif
+
+/*
+ * Maximum expected input data size for import command
+ */
+#define MAX_ENV_SIZE (1 << 20) /* 1 MiB */
+
+/*
+ * This variable is incremented on each do_env_set(), so it can
+ * be used via env_get_id() as an indication, if the environment
+ * has changed or not. So it is possible to reread an environment
+ * variable only if the environment was changed ... done so for
+ * example in NetInitLoop()
+ */
+static int env_id = 1;
+
+int env_get_id(void)
+{
+ return env_id;
+}
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ * Command interface: print one or all environment variables
+ *
+ * Returns 0 in case of error, or length of printed string
+ */
+static int env_print(char *name, int flag)
+{
+ char *res = NULL;
+ ssize_t len;
+
+ if (name) { /* print a single name */
+ struct env_entry e, *ep;
+
+ e.key = name;
+ e.data = NULL;
+ hsearch_r(e, ENV_FIND, &ep, &env_htab, flag);
+ if (ep == NULL)
+ return 0;
+ len = printf("%s=%s\n", ep->key, ep->data);
+ return len;
+ }
+
+ /* print whole list */
+ len = hexport_r(&env_htab, '\n', flag, &res, 0, 0, NULL);
+
+ if (len > 0) {
+ puts(res);
+ free(res);
+ return len;
+ }
+
+ /* should never happen */
+ printf("## Error: cannot export environment\n");
+ return 0;
+}
+
+static int do_env_print(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int i;
+ int rcode = 0;
+ int env_flag = H_HIDE_DOT;
+
+#if defined(CONFIG_CMD_NVEDIT_EFI)
+ if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e')
+ return do_env_print_efi(cmdtp, flag, --argc, ++argv);
+#endif
+
+ if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'a') {
+ argc--;
+ argv++;
+ env_flag &= ~H_HIDE_DOT;
+ }
+
+ if (argc == 1) {
+ /* print all env vars */
+ rcode = env_print(NULL, env_flag);
+ if (!rcode)
+ return 1;
+ printf("\nEnvironment size: %d/%ld bytes\n",
+ rcode, (ulong)ENV_SIZE);
+ return 0;
+ }
+
+ /* print selected env vars */
+ env_flag &= ~H_HIDE_DOT;
+ for (i = 1; i < argc; ++i) {
+ int rc = env_print(argv[i], env_flag);
+ if (!rc) {
+ printf("## Error: \"%s\" not defined\n", argv[i]);
+ ++rcode;
+ }
+ }
+
+ return rcode;
+}
+
+#ifdef CONFIG_CMD_GREPENV
+static int do_env_grep(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ char *res = NULL;
+ int len, grep_how, grep_what;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ grep_how = H_MATCH_SUBSTR; /* default: substring search */
+ grep_what = H_MATCH_BOTH; /* default: grep names and values */
+
+ while (--argc > 0 && **++argv == '-') {
+ char *arg = *argv;
+ while (*++arg) {
+ switch (*arg) {
+#ifdef CONFIG_REGEX
+ case 'e': /* use regex matching */
+ grep_how = H_MATCH_REGEX;
+ break;
+#endif
+ case 'n': /* grep for name */
+ grep_what = H_MATCH_KEY;
+ break;
+ case 'v': /* grep for value */
+ grep_what = H_MATCH_DATA;
+ break;
+ case 'b': /* grep for both */
+ grep_what = H_MATCH_BOTH;
+ break;
+ case '-':
+ goto DONE;
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+ }
+
+DONE:
+ len = hexport_r(&env_htab, '\n',
+ flag | grep_what | grep_how,
+ &res, 0, argc, argv);
+
+ if (len > 0) {
+ puts(res);
+ free(res);
+ }
+
+ if (len < 2)
+ return 1;
+
+ return 0;
+}
+#endif
+#endif /* CONFIG_SPL_BUILD */
+
+/*
+ * Set a new environment variable,
+ * or replace or delete an existing one.
+ */
+static int _do_env_set(int flag, int argc, char *const argv[], int env_flag)
+{
+ int i, len;
+ char *name, *value, *s;
+ struct env_entry e, *ep;
+
+ debug("Initial value for argc=%d\n", argc);
+
+#if CONFIG_IS_ENABLED(CMD_NVEDIT_EFI)
+ if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e')
+ return do_env_set_efi(NULL, flag, --argc, ++argv);
+#endif
+
+ while (argc > 1 && **(argv + 1) == '-') {
+ char *arg = *++argv;
+
+ --argc;
+ while (*++arg) {
+ switch (*arg) {
+ case 'f': /* force */
+ env_flag |= H_FORCE;
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+ }
+ debug("Final value for argc=%d\n", argc);
+ name = argv[1];
+
+ if (strchr(name, '=')) {
+ printf("## Error: illegal character '='"
+ "in variable name \"%s\"\n", name);
+ return 1;
+ }
+
+ env_id++;
+
+ /* Delete only ? */
+ if (argc < 3 || argv[2] == NULL) {
+ int rc = hdelete_r(name, &env_htab, env_flag);
+
+ /* If the variable didn't exist, don't report an error */
+ return rc && rc != -ENOENT ? 1 : 0;
+ }
+
+ /*
+ * Insert / replace new value
+ */
+ for (i = 2, len = 0; i < argc; ++i)
+ len += strlen(argv[i]) + 1;
+
+ value = malloc(len);
+ if (value == NULL) {
+ printf("## Can't malloc %d bytes\n", len);
+ return 1;
+ }
+ for (i = 2, s = value; i < argc; ++i) {
+ char *v = argv[i];
+
+ while ((*s++ = *v++) != '\0')
+ ;
+ *(s - 1) = ' ';
+ }
+ if (s != value)
+ *--s = '\0';
+
+ e.key = name;
+ e.data = value;
+ hsearch_r(e, ENV_ENTER, &ep, &env_htab, env_flag);
+ free(value);
+ if (!ep) {
+ printf("## Error inserting \"%s\" variable, errno=%d\n",
+ name, errno);
+ return 1;
+ }
+
+ return 0;
+}
+
+int env_set(const char *varname, const char *varvalue)
+{
+ const char * const argv[4] = { "setenv", varname, varvalue, NULL };
+
+ /* before import into hashtable */
+ if (!(gd->flags & GD_FLG_ENV_READY))
+ return 1;
+
+ if (varvalue == NULL || varvalue[0] == '\0')
+ return _do_env_set(0, 2, (char * const *)argv, H_PROGRAMMATIC);
+ else
+ return _do_env_set(0, 3, (char * const *)argv, H_PROGRAMMATIC);
+}
+
+/**
+ * Set an environment variable to an integer value
+ *
+ * @param varname Environment variable to set
+ * @param value Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+int env_set_ulong(const char *varname, ulong value)
+{
+ /* TODO: this should be unsigned */
+ char *str = simple_itoa(value);
+
+ return env_set(varname, str);
+}
+
+/**
+ * Set an environment variable to an value in hex
+ *
+ * @param varname Environment variable to set
+ * @param value Value to set it to
+ * @return 0 if ok, 1 on error
+ */
+int env_set_hex(const char *varname, ulong value)
+{
+ char str[17];
+
+ sprintf(str, "%lx", value);
+ return env_set(varname, str);
+}
+
+ulong env_get_hex(const char *varname, ulong default_val)
+{
+ const char *s;
+ ulong value;
+ char *endp;
+
+ s = env_get(varname);
+ if (s)
+ value = simple_strtoul(s, &endp, 16);
+ if (!s || endp == s)
+ return default_val;
+
+ return value;
+}
+
+int eth_env_get_enetaddr(const char *name, uint8_t *enetaddr)
+{
+ string_to_enetaddr(env_get(name), enetaddr);
+ return is_valid_ethaddr(enetaddr);
+}
+
+int eth_env_set_enetaddr(const char *name, const uint8_t *enetaddr)
+{
+ char buf[ARP_HLEN_ASCII + 1];
+
+ if (eth_env_get_enetaddr(name, (uint8_t *)buf))
+ return -EEXIST;
+
+ sprintf(buf, "%pM", enetaddr);
+
+ return env_set(name, buf);
+}
+
+#ifndef CONFIG_SPL_BUILD
+static int do_env_set(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ return _do_env_set(flag, argc, argv, H_INTERACTIVE);
+}
+
+/*
+ * Prompt for environment variable
+ */
+#if defined(CONFIG_CMD_ASKENV)
+int do_env_ask(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char message[CONFIG_SYS_CBSIZE];
+ int i, len, pos, size;
+ char *local_args[4];
+ char *endptr;
+
+ local_args[0] = argv[0];
+ local_args[1] = argv[1];
+ local_args[2] = NULL;
+ local_args[3] = NULL;
+
+ /*
+ * Check the syntax:
+ *
+ * env_ask envname [message1 ...] [size]
+ */
+ if (argc == 1)
+ return CMD_RET_USAGE;
+
+ /*
+ * We test the last argument if it can be converted
+ * into a decimal number. If yes, we assume it's
+ * the size. Otherwise we echo it as part of the
+ * message.
+ */
+ i = simple_strtoul(argv[argc - 1], &endptr, 10);
+ if (*endptr != '\0') { /* no size */
+ size = CONFIG_SYS_CBSIZE - 1;
+ } else { /* size given */
+ size = i;
+ --argc;
+ }
+
+ if (argc <= 2) {
+ sprintf(message, "Please enter '%s': ", argv[1]);
+ } else {
+ /* env_ask envname message1 ... messagen [size] */
+ for (i = 2, pos = 0; i < argc && pos+1 < sizeof(message); i++) {
+ if (pos)
+ message[pos++] = ' ';
+
+ strncpy(message + pos, argv[i], sizeof(message) - pos);
+ pos += strlen(argv[i]);
+ }
+ if (pos < sizeof(message) - 1) {
+ message[pos++] = ' ';
+ message[pos] = '\0';
+ } else
+ message[CONFIG_SYS_CBSIZE - 1] = '\0';
+ }
+
+ if (size >= CONFIG_SYS_CBSIZE)
+ size = CONFIG_SYS_CBSIZE - 1;
+
+ if (size <= 0)
+ return 1;
+
+ /* prompt for input */
+ len = cli_readline(message);
+
+ if (size < len)
+ console_buffer[size] = '\0';
+
+ len = 2;
+ if (console_buffer[0] != '\0') {
+ local_args[2] = console_buffer;
+ len = 3;
+ }
+
+ /* Continue calling setenv code */
+ return _do_env_set(flag, len, local_args, H_INTERACTIVE);
+}
+#endif
+
+#if defined(CONFIG_CMD_ENV_CALLBACK)
+static int print_static_binding(const char *var_name, const char *callback_name,
+ void *priv)
+{
+ printf("\t%-20s %-20s\n", var_name, callback_name);
+
+ return 0;
+}
+
+static int print_active_callback(struct env_entry *entry)
+{
+ struct env_clbk_tbl *clbkp;
+ int i;
+ int num_callbacks;
+
+ if (entry->callback == NULL)
+ return 0;
+
+ /* look up the callback in the linker-list */
+ num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
+ for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
+ i < num_callbacks;
+ i++, clbkp++) {
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+ if (entry->callback == clbkp->callback + gd->reloc_off)
+#else
+ if (entry->callback == clbkp->callback)
+#endif
+ break;
+ }
+
+ if (i == num_callbacks)
+ /* this should probably never happen, but just in case... */
+ printf("\t%-20s %p\n", entry->key, entry->callback);
+ else
+ printf("\t%-20s %-20s\n", entry->key, clbkp->name);
+
+ return 0;
+}
+
+/*
+ * Print the callbacks available and what they are bound to
+ */
+int do_env_callback(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct env_clbk_tbl *clbkp;
+ int i;
+ int num_callbacks;
+
+ /* Print the available callbacks */
+ puts("Available callbacks:\n");
+ puts("\tCallback Name\n");
+ puts("\t-------------\n");
+ num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
+ for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
+ i < num_callbacks;
+ i++, clbkp++)
+ printf("\t%s\n", clbkp->name);
+ puts("\n");
+
+ /* Print the static bindings that may exist */
+ puts("Static callback bindings:\n");
+ printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
+ printf("\t%-20s %-20s\n", "-------------", "-------------");
+ env_attr_walk(ENV_CALLBACK_LIST_STATIC, print_static_binding, NULL);
+ puts("\n");
+
+ /* walk through each variable and print the callback if it has one */
+ puts("Active callback bindings:\n");
+ printf("\t%-20s %-20s\n", "Variable Name", "Callback Name");
+ printf("\t%-20s %-20s\n", "-------------", "-------------");
+ hwalk_r(&env_htab, print_active_callback);
+ return 0;
+}
+#endif
+
+#if defined(CONFIG_CMD_ENV_FLAGS)
+static int print_static_flags(const char *var_name, const char *flags,
+ void *priv)
+{
+ enum env_flags_vartype type = env_flags_parse_vartype(flags);
+ enum env_flags_varaccess access = env_flags_parse_varaccess(flags);
+
+ printf("\t%-20s %-20s %-20s\n", var_name,
+ env_flags_get_vartype_name(type),
+ env_flags_get_varaccess_name(access));
+
+ return 0;
+}
+
+static int print_active_flags(struct env_entry *entry)
+{
+ enum env_flags_vartype type;
+ enum env_flags_varaccess access;
+
+ if (entry->flags == 0)
+ return 0;
+
+ type = (enum env_flags_vartype)
+ (entry->flags & ENV_FLAGS_VARTYPE_BIN_MASK);
+ access = env_flags_parse_varaccess_from_binflags(entry->flags);
+ printf("\t%-20s %-20s %-20s\n", entry->key,
+ env_flags_get_vartype_name(type),
+ env_flags_get_varaccess_name(access));
+
+ return 0;
+}
+
+/*
+ * Print the flags available and what variables have flags
+ */
+int do_env_flags(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ /* Print the available variable types */
+ printf("Available variable type flags (position %d):\n",
+ ENV_FLAGS_VARTYPE_LOC);
+ puts("\tFlag\tVariable Type Name\n");
+ puts("\t----\t------------------\n");
+ env_flags_print_vartypes();
+ puts("\n");
+
+ /* Print the available variable access types */
+ printf("Available variable access flags (position %d):\n",
+ ENV_FLAGS_VARACCESS_LOC);
+ puts("\tFlag\tVariable Access Name\n");
+ puts("\t----\t--------------------\n");
+ env_flags_print_varaccess();
+ puts("\n");
+
+ /* Print the static flags that may exist */
+ puts("Static flags:\n");
+ printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
+ "Variable Access");
+ printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
+ "---------------");
+ env_attr_walk(ENV_FLAGS_LIST_STATIC, print_static_flags, NULL);
+ puts("\n");
+
+ /* walk through each variable and print the flags if non-default */
+ puts("Active flags:\n");
+ printf("\t%-20s %-20s %-20s\n", "Variable Name", "Variable Type",
+ "Variable Access");
+ printf("\t%-20s %-20s %-20s\n", "-------------", "-------------",
+ "---------------");
+ hwalk_r(&env_htab, print_active_flags);
+ return 0;
+}
+#endif
+
+/*
+ * Interactively edit an environment variable
+ */
+#if defined(CONFIG_CMD_EDITENV)
+static int do_env_edit(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char buffer[CONFIG_SYS_CBSIZE];
+ char *init_val;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* before import into hashtable */
+ if (!(gd->flags & GD_FLG_ENV_READY))
+ return 1;
+
+ /* Set read buffer to initial value or empty sting */
+ init_val = env_get(argv[1]);
+ if (init_val)
+ snprintf(buffer, CONFIG_SYS_CBSIZE, "%s", init_val);
+ else
+ buffer[0] = '\0';
+
+ if (cli_readline_into_buffer("edit: ", buffer, 0) < 0)
+ return 1;
+
+ if (buffer[0] == '\0') {
+ const char * const _argv[3] = { "setenv", argv[1], NULL };
+
+ return _do_env_set(0, 2, (char * const *)_argv, H_INTERACTIVE);
+ } else {
+ const char * const _argv[4] = { "setenv", argv[1], buffer,
+ NULL };
+
+ return _do_env_set(0, 3, (char * const *)_argv, H_INTERACTIVE);
+ }
+}
+#endif /* CONFIG_CMD_EDITENV */
+#endif /* CONFIG_SPL_BUILD */
+
+/*
+ * Look up variable from environment,
+ * return address of storage for that variable,
+ * or NULL if not found
+ */
+char *env_get(const char *name)
+{
+ if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */
+ struct env_entry e, *ep;
+
+ WATCHDOG_RESET();
+
+ e.key = name;
+ e.data = NULL;
+ hsearch_r(e, ENV_FIND, &ep, &env_htab, 0);
+
+ return ep ? ep->data : NULL;
+ }
+
+ /* restricted capabilities before import */
+ if (env_get_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0)
+ return (char *)(gd->env_buf);
+
+ return NULL;
+}
+
+/*
+ * Like env_get, but prints an error if envvar isn't defined in the
+ * environment. It always returns what env_get does, so it can be used in
+ * place of env_get without changing error handling otherwise.
+ */
+char *from_env(const char *envvar)
+{
+ char *ret;
+
+ ret = env_get(envvar);
+
+ if (!ret)
+ printf("missing environment variable: %s\n", envvar);
+
+ return ret;
+}
+
+/*
+ * Look up variable from environment for restricted C runtime env.
+ */
+int env_get_f(const char *name, char *buf, unsigned len)
+{
+ int i, nxt, c;
+
+ for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
+ int val, n;
+
+ for (nxt = i; (c = env_get_char(nxt)) != '\0'; ++nxt) {
+ if (c < 0)
+ return c;
+ if (nxt >= CONFIG_ENV_SIZE)
+ return -1;
+ }
+
+ val = env_match((uchar *)name, i);
+ if (val < 0)
+ continue;
+
+ /* found; copy out */
+ for (n = 0; n < len; ++n, ++buf) {
+ c = env_get_char(val++);
+ if (c < 0)
+ return c;
+ *buf = c;
+ if (*buf == '\0')
+ return n;
+ }
+
+ if (n)
+ *--buf = '\0';
+
+ printf("env_buf [%u bytes] too small for value of \"%s\"\n",
+ len, name);
+
+ return n;
+ }
+
+ return -1;
+}
+
+/**
+ * Decode the integer value of an environment variable and return it.
+ *
+ * @param name Name of environment variable
+ * @param base Number base to use (normally 10, or 16 for hex)
+ * @param default_val Default value to return if the variable is not
+ * found
+ * @return the decoded value, or default_val if not found
+ */
+ulong env_get_ulong(const char *name, int base, ulong default_val)
+{
+ /*
+ * We can use env_get() here, even before relocation, since the
+ * environment variable value is an integer and thus short.
+ */
+ const char *str = env_get(name);
+
+ return str ? simple_strtoul(str, NULL, base) : default_val;
+}
+
+#ifndef CONFIG_SPL_BUILD
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
+static int do_env_save(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return env_save() ? 1 : 0;
+}
+
+U_BOOT_CMD(
+ saveenv, 1, 0, do_env_save,
+ "save environment variables to persistent storage",
+ ""
+);
+
+#if defined(CONFIG_CMD_ERASEENV)
+static int do_env_erase(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return env_erase() ? 1 : 0;
+}
+
+U_BOOT_CMD(
+ eraseenv, 1, 0, do_env_erase,
+ "erase environment variables from persistent storage",
+ ""
+);
+#endif
+#endif
+
+#if defined(CONFIG_CMD_NVEDIT_LOAD)
+static int do_env_load(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return env_reload() ? 1 : 0;
+}
+#endif
+
+#if defined(CONFIG_CMD_NVEDIT_SELECT)
+static int do_env_select(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return env_select(argv[1]) ? 1 : 0;
+}
+#endif
+
+#endif /* CONFIG_SPL_BUILD */
+
+int env_match(uchar *s1, int i2)
+{
+ if (s1 == NULL)
+ return -1;
+
+ while (*s1 == env_get_char(i2++))
+ if (*s1++ == '=')
+ return i2;
+
+ if (*s1 == '\0' && env_get_char(i2-1) == '=')
+ return i2;
+
+ return -1;
+}
+
+#ifndef CONFIG_SPL_BUILD
+static int do_env_default(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int all = 0, env_flag = H_INTERACTIVE;
+
+ debug("Initial value for argc=%d\n", argc);
+ while (--argc > 0 && **++argv == '-') {
+ char *arg = *argv;
+
+ while (*++arg) {
+ switch (*arg) {
+ case 'a': /* default all */
+ all = 1;
+ break;
+ case 'f': /* force */
+ env_flag |= H_FORCE;
+ break;
+ default:
+ return cmd_usage(cmdtp);
+ }
+ }
+ }
+ debug("Final value for argc=%d\n", argc);
+ if (all && (argc == 0)) {
+ /* Reset the whole environment */
+ env_set_default("## Resetting to default environment\n",
+ env_flag);
+ return 0;
+ }
+ if (!all && (argc > 0)) {
+ /* Reset individual variables */
+ env_set_default_vars(argc, argv, env_flag);
+ return 0;
+ }
+
+ return cmd_usage(cmdtp);
+}
+
+static int do_env_delete(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int env_flag = H_INTERACTIVE;
+ int ret = 0;
+
+ debug("Initial value for argc=%d\n", argc);
+ while (argc > 1 && **(argv + 1) == '-') {
+ char *arg = *++argv;
+
+ --argc;
+ while (*++arg) {
+ switch (*arg) {
+ case 'f': /* force */
+ env_flag |= H_FORCE;
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+ }
+ debug("Final value for argc=%d\n", argc);
+
+ env_id++;
+
+ while (--argc > 0) {
+ char *name = *++argv;
+
+ if (hdelete_r(name, &env_htab, env_flag))
+ ret = 1;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_CMD_EXPORTENV
+/*
+ * env export [-t | -b | -c] [-s size] addr [var ...]
+ * -t: export as text format; if size is given, data will be
+ * padded with '\0' bytes; if not, one terminating '\0'
+ * will be added (which is included in the "filesize"
+ * setting so you can for exmple copy this to flash and
+ * keep the termination).
+ * -b: export as binary format (name=value pairs separated by
+ * '\0', list end marked by double "\0\0")
+ * -c: export as checksum protected environment format as
+ * used for example by "saveenv" command
+ * -s size:
+ * size of output buffer
+ * addr: memory address where environment gets stored
+ * var... List of variable names that get included into the
+ * export. Without arguments, the whole environment gets
+ * exported.
+ *
+ * With "-c" and size is NOT given, then the export command will
+ * format the data as currently used for the persistent storage,
+ * i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and
+ * prepend a valid CRC32 checksum and, in case of redundant
+ * environment, a "current" redundancy flag. If size is given, this
+ * value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32
+ * checksum and redundancy flag will be inserted.
+ *
+ * With "-b" and "-t", always only the real data (including a
+ * terminating '\0' byte) will be written; here the optional size
+ * argument will be used to make sure not to overflow the user
+ * provided buffer; the command will abort if the size is not
+ * sufficient. Any remaining space will be '\0' padded.
+ *
+ * On successful return, the variable "filesize" will be set.
+ * Note that filesize includes the trailing/terminating '\0' byte(s).
+ *
+ * Usage scenario: create a text snapshot/backup of the current settings:
+ *
+ * => env export -t 100000
+ * => era ${backup_addr} +${filesize}
+ * => cp.b 100000 ${backup_addr} ${filesize}
+ *
+ * Re-import this snapshot, deleting all other settings:
+ *
+ * => env import -d -t ${backup_addr}
+ */
+static int do_env_export(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ char buf[32];
+ ulong addr;
+ char *ptr, *cmd, *res;
+ size_t size = 0;
+ ssize_t len;
+ env_t *envp;
+ char sep = '\n';
+ int chk = 0;
+ int fmt = 0;
+
+ cmd = *argv;
+
+ while (--argc > 0 && **++argv == '-') {
+ char *arg = *argv;
+ while (*++arg) {
+ switch (*arg) {
+ case 'b': /* raw binary format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\0';
+ break;
+ case 'c': /* external checksum format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\0';
+ chk = 1;
+ break;
+ case 's': /* size given */
+ if (--argc <= 0)
+ return cmd_usage(cmdtp);
+ size = simple_strtoul(*++argv, NULL, 16);
+ goto NXTARG;
+ case 't': /* text format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\n';
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+NXTARG: ;
+ }
+
+ if (argc < 1)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[0], NULL, 16);
+ ptr = map_sysmem(addr, size);
+
+ if (size)
+ memset(ptr, '\0', size);
+
+ argc--;
+ argv++;
+
+ if (sep) { /* export as text file */
+ len = hexport_r(&env_htab, sep,
+ H_MATCH_KEY | H_MATCH_IDENT,
+ &ptr, size, argc, argv);
+ if (len < 0) {
+ pr_err("## Error: Cannot export environment: errno = %d\n",
+ errno);
+ return 1;
+ }
+ sprintf(buf, "%zX", (size_t)len);
+ env_set("filesize", buf);
+
+ return 0;
+ }
+
+ envp = (env_t *)ptr;
+
+ if (chk) /* export as checksum protected block */
+ res = (char *)envp->data;
+ else /* export as raw binary data */
+ res = ptr;
+
+ len = hexport_r(&env_htab, '\0',
+ H_MATCH_KEY | H_MATCH_IDENT,
+ &res, ENV_SIZE, argc, argv);
+ if (len < 0) {
+ pr_err("## Error: Cannot export environment: errno = %d\n",
+ errno);
+ return 1;
+ }
+
+ if (chk) {
+ envp->crc = crc32(0, envp->data,
+ size ? size - offsetof(env_t, data) : ENV_SIZE);
+#ifdef CONFIG_ENV_ADDR_REDUND
+ envp->flags = ENV_REDUND_ACTIVE;
+#endif
+ }
+ env_set_hex("filesize", len + offsetof(env_t, data));
+
+ return 0;
+
+sep_err:
+ printf("## Error: %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
+ cmd);
+ return 1;
+}
+#endif
+
+#ifdef CONFIG_CMD_IMPORTENV
+/*
+ * env import [-d] [-t [-r] | -b | -c] addr [size] [var ...]
+ * -d: delete existing environment before importing if no var is
+ * passed; if vars are passed, if one var is in the current
+ * environment but not in the environment at addr, delete var from
+ * current environment;
+ * otherwise overwrite / append to existing definitions
+ * -t: assume text format; either "size" must be given or the
+ * text data must be '\0' terminated
+ * -r: handle CRLF like LF, that means exported variables with
+ * a content which ends with \r won't get imported. Used
+ * to import text files created with editors which are using CRLF
+ * for line endings. Only effective in addition to -t.
+ * -b: assume binary format ('\0' separated, "\0\0" terminated)
+ * -c: assume checksum protected environment format
+ * addr: memory address to read from
+ * size: length of input data; if missing, proper '\0'
+ * termination is mandatory
+ * if var is set and size should be missing (i.e. '\0'
+ * termination), set size to '-'
+ * var... List of the names of the only variables that get imported from
+ * the environment at address 'addr'. Without arguments, the whole
+ * environment gets imported.
+ */
+static int do_env_import(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ ulong addr;
+ char *cmd, *ptr;
+ char sep = '\n';
+ int chk = 0;
+ int fmt = 0;
+ int del = 0;
+ int crlf_is_lf = 0;
+ int wl = 0;
+ size_t size;
+
+ cmd = *argv;
+
+ while (--argc > 0 && **++argv == '-') {
+ char *arg = *argv;
+ while (*++arg) {
+ switch (*arg) {
+ case 'b': /* raw binary format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\0';
+ break;
+ case 'c': /* external checksum format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\0';
+ chk = 1;
+ break;
+ case 't': /* text format */
+ if (fmt++)
+ goto sep_err;
+ sep = '\n';
+ break;
+ case 'r': /* handle CRLF like LF */
+ crlf_is_lf = 1;
+ break;
+ case 'd':
+ del = 1;
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+ }
+
+ if (argc < 1)
+ return CMD_RET_USAGE;
+
+ if (!fmt)
+ printf("## Warning: defaulting to text format\n");
+
+ if (sep != '\n' && crlf_is_lf )
+ crlf_is_lf = 0;
+
+ addr = simple_strtoul(argv[0], NULL, 16);
+ ptr = map_sysmem(addr, 0);
+
+ if (argc >= 2 && strcmp(argv[1], "-")) {
+ size = simple_strtoul(argv[1], NULL, 16);
+ } else if (chk) {
+ puts("## Error: external checksum format must pass size\n");
+ return CMD_RET_FAILURE;
+ } else {
+ char *s = ptr;
+
+ size = 0;
+
+ while (size < MAX_ENV_SIZE) {
+ if ((*s == sep) && (*(s+1) == '\0'))
+ break;
+ ++s;
+ ++size;
+ }
+ if (size == MAX_ENV_SIZE) {
+ printf("## Warning: Input data exceeds %d bytes"
+ " - truncated\n", MAX_ENV_SIZE);
+ }
+ size += 2;
+ printf("## Info: input data size = %zu = 0x%zX\n", size, size);
+ }
+
+ if (argc > 2)
+ wl = 1;
+
+ if (chk) {
+ uint32_t crc;
+ env_t *ep = (env_t *)ptr;
+
+ if (size <= offsetof(env_t, data)) {
+ printf("## Error: Invalid size 0x%zX\n", size);
+ return 1;
+ }
+
+ size -= offsetof(env_t, data);
+ memcpy(&crc, &ep->crc, sizeof(crc));
+
+ if (crc32(0, ep->data, size) != crc) {
+ puts("## Error: bad CRC, import failed\n");
+ return 1;
+ }
+ ptr = (char *)ep->data;
+ }
+
+ if (!himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR,
+ crlf_is_lf, wl ? argc - 2 : 0, wl ? &argv[2] : NULL)) {
+ pr_err("## Error: Environment import failed: errno = %d\n",
+ errno);
+ return 1;
+ }
+ gd->flags |= GD_FLG_ENV_READY;
+
+ return 0;
+
+sep_err:
+ printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
+ cmd);
+ return 1;
+}
+#endif
+
+#if defined(CONFIG_CMD_NVEDIT_INFO)
+/*
+ * print_env_info - print environment information
+ */
+static int print_env_info(void)
+{
+ const char *value;
+
+ /* print environment validity value */
+ switch (gd->env_valid) {
+ case ENV_INVALID:
+ value = "invalid";
+ break;
+ case ENV_VALID:
+ value = "valid";
+ break;
+ case ENV_REDUND:
+ value = "redundant";
+ break;
+ default:
+ value = "unknown";
+ break;
+ }
+ printf("env_valid = %s\n", value);
+
+ /* print environment ready flag */
+ value = gd->flags & GD_FLG_ENV_READY ? "true" : "false";
+ printf("env_ready = %s\n", value);
+
+ /* print environment using default flag */
+ value = gd->flags & GD_FLG_ENV_DEFAULT ? "true" : "false";
+ printf("env_use_default = %s\n", value);
+
+ return CMD_RET_SUCCESS;
+}
+
+#define ENV_INFO_IS_DEFAULT BIT(0) /* default environment bit mask */
+#define ENV_INFO_IS_PERSISTED BIT(1) /* environment persistence bit mask */
+
+/*
+ * env info - display environment information
+ * env info [-d] - evaluate whether default environment is used
+ * env info [-p] - evaluate whether environment can be persisted
+ * Add [-q] - quiet mode, use only for command result, for test by example:
+ * test env info -p -d -q
+ */
+static int do_env_info(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int eval_flags = 0;
+ int eval_results = 0;
+ bool quiet = false;
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
+ enum env_location loc;
+#endif
+
+ /* display environment information */
+ if (argc <= 1)
+ return print_env_info();
+
+ /* process options */
+ while (--argc > 0 && **++argv == '-') {
+ char *arg = *argv;
+
+ while (*++arg) {
+ switch (*arg) {
+ case 'd':
+ eval_flags |= ENV_INFO_IS_DEFAULT;
+ break;
+ case 'p':
+ eval_flags |= ENV_INFO_IS_PERSISTED;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ }
+ }
+
+ /* evaluate whether default environment is used */
+ if (eval_flags & ENV_INFO_IS_DEFAULT) {
+ if (gd->flags & GD_FLG_ENV_DEFAULT) {
+ if (!quiet)
+ printf("Default environment is used\n");
+ eval_results |= ENV_INFO_IS_DEFAULT;
+ } else {
+ if (!quiet)
+ printf("Environment was loaded from persistent storage\n");
+ }
+ }
+
+ /* evaluate whether environment can be persisted */
+ if (eval_flags & ENV_INFO_IS_PERSISTED) {
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
+ loc = env_get_location(ENVOP_SAVE, gd->env_load_prio);
+ if (ENVL_NOWHERE != loc && ENVL_UNKNOWN != loc) {
+ if (!quiet)
+ printf("Environment can be persisted\n");
+ eval_results |= ENV_INFO_IS_PERSISTED;
+ } else {
+ if (!quiet)
+ printf("Environment cannot be persisted\n");
+ }
+#else
+ if (!quiet)
+ printf("Environment cannot be persisted\n");
+#endif
+ }
+
+ /* The result of evaluations is combined with AND */
+ if (eval_flags != eval_results)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+#endif
+
+#if defined(CONFIG_CMD_ENV_EXISTS)
+static int do_env_exists(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct env_entry e, *ep;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ e.key = argv[1];
+ e.data = NULL;
+ hsearch_r(e, ENV_FIND, &ep, &env_htab, 0);
+
+ return (ep == NULL) ? 1 : 0;
+}
+#endif
+
+/*
+ * New command line interface: "env" command with subcommands
+ */
+static struct cmd_tbl cmd_env_sub[] = {
+#if defined(CONFIG_CMD_ASKENV)
+ U_BOOT_CMD_MKENT(ask, CONFIG_SYS_MAXARGS, 1, do_env_ask, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(default, 1, 0, do_env_default, "", ""),
+ U_BOOT_CMD_MKENT(delete, CONFIG_SYS_MAXARGS, 0, do_env_delete, "", ""),
+#if defined(CONFIG_CMD_EDITENV)
+ U_BOOT_CMD_MKENT(edit, 2, 0, do_env_edit, "", ""),
+#endif
+#if defined(CONFIG_CMD_ENV_CALLBACK)
+ U_BOOT_CMD_MKENT(callbacks, 1, 0, do_env_callback, "", ""),
+#endif
+#if defined(CONFIG_CMD_ENV_FLAGS)
+ U_BOOT_CMD_MKENT(flags, 1, 0, do_env_flags, "", ""),
+#endif
+#if defined(CONFIG_CMD_EXPORTENV)
+ U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""),
+#endif
+#if defined(CONFIG_CMD_GREPENV)
+ U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""),
+#endif
+#if defined(CONFIG_CMD_IMPORTENV)
+ U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""),
+#endif
+#if defined(CONFIG_CMD_NVEDIT_INFO)
+ U_BOOT_CMD_MKENT(info, 3, 0, do_env_info, "", ""),
+#endif
+#if defined(CONFIG_CMD_NVEDIT_LOAD)
+ U_BOOT_CMD_MKENT(load, 1, 0, do_env_load, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""),
+#if defined(CONFIG_CMD_RUN)
+ U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""),
+#endif
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
+ U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""),
+#if defined(CONFIG_CMD_ERASEENV)
+ U_BOOT_CMD_MKENT(erase, 1, 0, do_env_erase, "", ""),
+#endif
+#endif
+#if defined(CONFIG_CMD_NVEDIT_SELECT)
+ U_BOOT_CMD_MKENT(select, 2, 0, do_env_select, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""),
+#if defined(CONFIG_CMD_ENV_EXISTS)
+ U_BOOT_CMD_MKENT(exists, 2, 0, do_env_exists, "", ""),
+#endif
+};
+
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+void env_reloc(void)
+{
+ fixup_cmdtable(cmd_env_sub, ARRAY_SIZE(cmd_env_sub));
+}
+#endif
+
+static int do_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* drop initial "env" arg */
+ argc--;
+ argv++;
+
+ cp = find_cmd_tbl(argv[0], cmd_env_sub, ARRAY_SIZE(cmd_env_sub));
+
+ if (cp)
+ return cp->cmd(cmdtp, flag, argc, argv);
+
+ return CMD_RET_USAGE;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char env_help_text[] =
+#if defined(CONFIG_CMD_ASKENV)
+ "ask name [message] [size] - ask for environment variable\nenv "
+#endif
+#if defined(CONFIG_CMD_ENV_CALLBACK)
+ "callbacks - print callbacks and their associated variables\nenv "
+#endif
+ "default [-f] -a - [forcibly] reset default environment\n"
+ "env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n"
+ "env delete [-f] var [...] - [forcibly] delete variable(s)\n"
+#if defined(CONFIG_CMD_EDITENV)
+ "env edit name - edit environment variable\n"
+#endif
+#if defined(CONFIG_CMD_ENV_EXISTS)
+ "env exists name - tests for existence of variable\n"
+#endif
+#if defined(CONFIG_CMD_EXPORTENV)
+ "env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n"
+#endif
+#if defined(CONFIG_CMD_ENV_FLAGS)
+ "env flags - print variables that have non-default flags\n"
+#endif
+#if defined(CONFIG_CMD_GREPENV)
+#ifdef CONFIG_REGEX
+ "env grep [-e] [-n | -v | -b] string [...] - search environment\n"
+#else
+ "env grep [-n | -v | -b] string [...] - search environment\n"
+#endif
+#endif
+#if defined(CONFIG_CMD_IMPORTENV)
+ "env import [-d] [-t [-r] | -b | -c] addr [size] [var ...] - import environment\n"
+#endif
+#if defined(CONFIG_CMD_NVEDIT_INFO)
+ "env info - display environment information\n"
+ "env info [-d] [-p] [-q] - evaluate environment information\n"
+ " \"-d\": default environment is used\n"
+ " \"-p\": environment can be persisted\n"
+ " \"-q\": quiet output\n"
+#endif
+ "env print [-a | name ...] - print environment\n"
+#if defined(CONFIG_CMD_NVEDIT_EFI)
+ "env print -e [-guid guid] [-n] [name ...] - print UEFI environment\n"
+#endif
+#if defined(CONFIG_CMD_RUN)
+ "env run var [...] - run commands in an environment variable\n"
+#endif
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
+ "env save - save environment\n"
+#if defined(CONFIG_CMD_ERASEENV)
+ "env erase - erase environment\n"
+#endif
+#endif
+#if defined(CONFIG_CMD_NVEDIT_LOAD)
+ "env load - load environment\n"
+#endif
+#if defined(CONFIG_CMD_NVEDIT_SELECT)
+ "env select [target] - select environment target\n"
+#endif
+#if defined(CONFIG_CMD_NVEDIT_EFI)
+ "env set -e [-nv][-bs][-rt][-at][-a][-i addr:size][-v] name [arg ...]\n"
+ " - set UEFI variable; unset if '-i' or 'arg' not specified\n"
+#endif
+ "env set [-f] name [arg ...]\n";
+#endif
+
+U_BOOT_CMD(
+ env, CONFIG_SYS_MAXARGS, 1, do_env,
+ "environment handling commands", env_help_text
+);
+
+/*
+ * Old command line interface, kept for compatibility
+ */
+
+#if defined(CONFIG_CMD_EDITENV)
+U_BOOT_CMD_COMPLETE(
+ editenv, 2, 0, do_env_edit,
+ "edit environment variable",
+ "name\n"
+ " - edit environment variable 'name'",
+ var_complete
+);
+#endif
+
+U_BOOT_CMD_COMPLETE(
+ printenv, CONFIG_SYS_MAXARGS, 1, do_env_print,
+ "print environment variables",
+ "[-a]\n - print [all] values of all environment variables\n"
+#if defined(CONFIG_CMD_NVEDIT_EFI)
+ "printenv -e [-guid guid][-n] [name ...]\n"
+ " - print UEFI variable 'name' or all the variables\n"
+ " \"-guid\": GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
+ " \"-n\": suppress dumping variable's value\n"
+#endif
+ "printenv name ...\n"
+ " - print value of environment variable 'name'",
+ var_complete
+);
+
+#ifdef CONFIG_CMD_GREPENV
+U_BOOT_CMD_COMPLETE(
+ grepenv, CONFIG_SYS_MAXARGS, 0, do_env_grep,
+ "search environment variables",
+#ifdef CONFIG_REGEX
+ "[-e] [-n | -v | -b] string ...\n"
+#else
+ "[-n | -v | -b] string ...\n"
+#endif
+ " - list environment name=value pairs matching 'string'\n"
+#ifdef CONFIG_REGEX
+ " \"-e\": enable regular expressions;\n"
+#endif
+ " \"-n\": search variable names; \"-v\": search values;\n"
+ " \"-b\": search both names and values (default)",
+ var_complete
+);
+#endif
+
+U_BOOT_CMD_COMPLETE(
+ setenv, CONFIG_SYS_MAXARGS, 0, do_env_set,
+ "set environment variables",
+#if defined(CONFIG_CMD_NVEDIT_EFI)
+ "-e [-guid guid][-nv][-bs][-rt][-at][-a][-v]\n"
+ " [-i addr:size name], or [name [value ...]]\n"
+ " - set UEFI variable 'name' to 'value' ...'\n"
+ " \"-guid\": GUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
+ " \"-nv\": set non-volatile attribute\n"
+ " \"-bs\": set boot-service attribute\n"
+ " \"-rt\": set runtime attribute\n"
+ " \"-at\": set time-based authentication attribute\n"
+ " \"-a\": append-write\n"
+ " \"-i addr,size\": use <addr,size> as variable's value\n"
+ " \"-v\": verbose message\n"
+ " - delete UEFI variable 'name' if 'value' not specified\n"
+#endif
+ "setenv [-f] name value ...\n"
+ " - [forcibly] set environment variable 'name' to 'value ...'\n"
+ "setenv [-f] name\n"
+ " - [forcibly] delete environment variable 'name'",
+ var_complete
+);
+
+#if defined(CONFIG_CMD_ASKENV)
+
+U_BOOT_CMD(
+ askenv, CONFIG_SYS_MAXARGS, 1, do_env_ask,
+ "get environment variables from stdin",
+ "name [message] [size]\n"
+ " - get environment variable 'name' from stdin (max 'size' chars)"
+);
+#endif
+
+#if defined(CONFIG_CMD_RUN)
+U_BOOT_CMD_COMPLETE(
+ run, CONFIG_SYS_MAXARGS, 1, do_run,
+ "run commands in an environment variable",
+ "var [...]\n"
+ " - run the commands in the environment variable(s) 'var'",
+ var_complete
+);
+#endif
+#endif /* CONFIG_SPL_BUILD */
diff --git a/roms/u-boot/cmd/nvedit_efi.c b/roms/u-boot/cmd/nvedit_efi.c
new file mode 100644
index 000000000..094c0e809
--- /dev/null
+++ b/roms/u-boot/cmd/nvedit_efi.c
@@ -0,0 +1,574 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Integrate UEFI variables to u-boot env interface
+ *
+ * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
+ */
+
+#include <charset.h>
+#include <common.h>
+#include <command.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+#include <env.h>
+#include <exports.h>
+#include <hexdump.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <rtc.h>
+#include <uuid.h>
+#include <linux/kernel.h>
+
+/*
+ * From efi_variable.c,
+ *
+ * Mapping between UEFI variables and u-boot variables:
+ *
+ * efi_$guid_$varname = {attributes}(type)value
+ */
+
+static const struct {
+ u32 mask;
+ char *text;
+} efi_var_attrs[] = {
+ {EFI_VARIABLE_NON_VOLATILE, "NV"},
+ {EFI_VARIABLE_BOOTSERVICE_ACCESS, "BS"},
+ {EFI_VARIABLE_RUNTIME_ACCESS, "RT"},
+ {EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, "AW"},
+ {EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, "AT"},
+ {EFI_VARIABLE_READ_ONLY, "RO"},
+};
+
+static const struct {
+ efi_guid_t guid;
+ char *text;
+} efi_guid_text[] = {
+ /* signature database */
+ {EFI_GLOBAL_VARIABLE_GUID, "EFI_GLOBAL_VARIABLE_GUID"},
+ {EFI_IMAGE_SECURITY_DATABASE_GUID, "EFI_IMAGE_SECURITY_DATABASE_GUID"},
+ /* certificate type */
+ {EFI_CERT_SHA256_GUID, "EFI_CERT_SHA256_GUID"},
+ {EFI_CERT_X509_GUID, "EFI_CERT_X509_GUID"},
+ {EFI_CERT_TYPE_PKCS7_GUID, "EFI_CERT_TYPE_PKCS7_GUID"},
+};
+
+static const char unknown_guid[] = "";
+
+/**
+ * efi_guid_to_str() - convert guid to readable name
+ *
+ * @guid: GUID
+ * Return: string for GUID
+ *
+ * convert guid to readable name
+ */
+static const char *efi_guid_to_str(const efi_guid_t *guid)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(efi_guid_text); i++)
+ if (!guidcmp(guid, &efi_guid_text[i].guid))
+ return efi_guid_text[i].text;
+
+ return unknown_guid;
+}
+
+/**
+ * efi_dump_single_var() - show information about a UEFI variable
+ *
+ * @name: Name of the variable
+ * @guid: Vendor GUID
+ * @verbose: if true, dump data
+ *
+ * Show information encoded in one UEFI variable
+ */
+static void efi_dump_single_var(u16 *name, const efi_guid_t *guid, bool verbose)
+{
+ u32 attributes;
+ u8 *data;
+ u64 time;
+ struct rtc_time tm;
+ efi_uintn_t size;
+ int count, i;
+ efi_status_t ret;
+
+ data = NULL;
+ size = 0;
+ ret = efi_get_variable_int(name, guid, &attributes, &size, data, &time);
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ data = malloc(size);
+ if (!data)
+ goto out;
+
+ ret = efi_get_variable_int(name, guid, &attributes, &size,
+ data, &time);
+ }
+ if (ret == EFI_NOT_FOUND) {
+ printf("Error: \"%ls\" not defined\n", name);
+ goto out;
+ }
+ if (ret != EFI_SUCCESS)
+ goto out;
+
+ rtc_to_tm(time, &tm);
+ printf("%ls:\n %pUl %s\n", name, guid, efi_guid_to_str(guid));
+ if (attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+ printf(" %04d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year,
+ tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+ printf(" ");
+ for (count = 0, i = 0; i < ARRAY_SIZE(efi_var_attrs); i++)
+ if (attributes & efi_var_attrs[i].mask) {
+ if (count)
+ putc('|');
+ count++;
+ puts(efi_var_attrs[i].text);
+ }
+ printf(", DataSize = 0x%zx\n", size);
+ if (verbose)
+ print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
+ data, size, true);
+
+out:
+ free(data);
+}
+
+static bool match_name(int argc, char *const argv[], u16 *var_name16)
+{
+ char *buf, *p;
+ size_t buflen;
+ int i;
+ bool result = false;
+
+ buflen = utf16_utf8_strlen(var_name16) + 1;
+ buf = calloc(1, buflen);
+ if (!buf)
+ return result;
+
+ p = buf;
+ utf16_utf8_strcpy(&p, var_name16);
+
+ for (i = 0; i < argc; argc--, argv++) {
+ if (!strcmp(buf, argv[i])) {
+ result = true;
+ goto out;
+ }
+ }
+
+out:
+ free(buf);
+
+ return result;
+}
+
+/**
+ * efi_dump_var_all() - show information about all the UEFI variables
+ *
+ * @argc: Number of arguments (variables)
+ * @argv: Argument (variable name) array
+ * @verbose: if true, dump data
+ * Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
+ *
+ * Show information encoded in all the UEFI variables
+ */
+static int efi_dump_var_all(int argc, char *const argv[],
+ const efi_guid_t *guid_p, bool verbose)
+{
+ u16 *var_name16, *p;
+ efi_uintn_t buf_size, size;
+ efi_guid_t guid;
+ efi_status_t ret;
+ bool match = false;
+
+ buf_size = 128;
+ var_name16 = malloc(buf_size);
+ if (!var_name16)
+ return CMD_RET_FAILURE;
+
+ var_name16[0] = 0;
+ for (;;) {
+ size = buf_size;
+ ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
+ &guid));
+ if (ret == EFI_NOT_FOUND)
+ break;
+ if (ret == EFI_BUFFER_TOO_SMALL) {
+ buf_size = size;
+ p = realloc(var_name16, buf_size);
+ if (!p) {
+ free(var_name16);
+ return CMD_RET_FAILURE;
+ }
+ var_name16 = p;
+ ret = EFI_CALL(efi_get_next_variable_name(&size,
+ var_name16,
+ &guid));
+ }
+ if (ret != EFI_SUCCESS) {
+ free(var_name16);
+ return CMD_RET_FAILURE;
+ }
+
+ if (guid_p && guidcmp(guid_p, &guid))
+ continue;
+ if (!argc || match_name(argc, argv, var_name16)) {
+ match = true;
+ efi_dump_single_var(var_name16, &guid, verbose);
+ }
+ }
+ free(var_name16);
+
+ if (!match && argc == 1)
+ printf("Error: \"%s\" not defined\n", argv[0]);
+
+ return CMD_RET_SUCCESS;
+}
+
+/**
+ * do_env_print_efi() - show information about UEFI variables
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
+ *
+ * This function is for "env print -e" or "printenv -e" command:
+ * => env print -e [-n] [-guid <guid> | -all] [var [...]]
+ * If one or more variable names are specified, show information
+ * named UEFI variables, otherwise show all the UEFI variables.
+ */
+int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const efi_guid_t *guid_p = NULL;
+ bool verbose = true;
+ efi_status_t ret;
+
+ /* Initialize EFI drivers */
+ ret = efi_init_obj_list();
+ if (ret != EFI_SUCCESS) {
+ printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
+ ret & ~EFI_ERROR_MASK);
+ return CMD_RET_FAILURE;
+ }
+
+ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
+ if (!strcmp(argv[0], "-guid")) {
+ efi_guid_t guid;
+
+ if (argc == 1)
+ return CMD_RET_USAGE;
+ argc--;
+ argv++;
+ if (uuid_str_to_bin(argv[0], guid.b,
+ UUID_STR_FORMAT_GUID))
+ return CMD_RET_USAGE;
+ guid_p = (const efi_guid_t *)guid.b;
+ } else if (!strcmp(argv[0], "-n")) {
+ verbose = false;
+ } else {
+ return CMD_RET_USAGE;
+ }
+ }
+
+ /* enumerate and show all UEFI variables */
+ return efi_dump_var_all(argc, argv, guid_p, verbose);
+}
+
+/**
+ * append_value() - encode UEFI variable's value
+ * @bufp: Buffer of encoded UEFI variable's value
+ * @sizep: Size of buffer
+ * @data: data to be encoded into the value
+ * Return: 0 on success, -1 otherwise
+ *
+ * Interpret a given data string and append it to buffer.
+ * Buffer will be realloc'ed if necessary.
+ *
+ * Currently supported formats are:
+ * =0x0123...: Hexadecimal number
+ * =H0123...: Hexadecimal-byte array
+ * ="...", =S"..." or <string>:
+ * String
+ */
+static int append_value(char **bufp, size_t *sizep, char *data)
+{
+ char *tmp_buf = NULL, *new_buf = NULL, *value;
+ unsigned long len = 0;
+
+ if (!strncmp(data, "=0x", 2)) { /* hexadecimal number */
+ union {
+ u8 u8;
+ u16 u16;
+ u32 u32;
+ u64 u64;
+ } tmp_data;
+ unsigned long hex_value;
+ void *hex_ptr;
+
+ data += 3;
+ len = strlen(data);
+ if ((len & 0x1)) /* not multiple of two */
+ return -1;
+
+ len /= 2;
+ if (len > 8)
+ return -1;
+ else if (len > 4)
+ len = 8;
+ else if (len > 2)
+ len = 4;
+
+ /* convert hex hexadecimal number */
+ if (strict_strtoul(data, 16, &hex_value) < 0)
+ return -1;
+
+ tmp_buf = malloc(len);
+ if (!tmp_buf)
+ return -1;
+
+ if (len == 1) {
+ tmp_data.u8 = hex_value;
+ hex_ptr = &tmp_data.u8;
+ } else if (len == 2) {
+ tmp_data.u16 = hex_value;
+ hex_ptr = &tmp_data.u16;
+ } else if (len == 4) {
+ tmp_data.u32 = hex_value;
+ hex_ptr = &tmp_data.u32;
+ } else {
+ tmp_data.u64 = hex_value;
+ hex_ptr = &tmp_data.u64;
+ }
+ memcpy(tmp_buf, hex_ptr, len);
+ value = tmp_buf;
+
+ } else if (!strncmp(data, "=H", 2)) { /* hexadecimal-byte array */
+ data += 2;
+ len = strlen(data);
+ if (len & 0x1) /* not multiple of two */
+ return -1;
+
+ len /= 2;
+ tmp_buf = malloc(len);
+ if (!tmp_buf)
+ return -1;
+
+ if (hex2bin((u8 *)tmp_buf, data, len) < 0) {
+ printf("Error: illegal hexadecimal string\n");
+ free(tmp_buf);
+ return -1;
+ }
+
+ value = tmp_buf;
+ } else { /* string */
+ if (!strncmp(data, "=\"", 2) || !strncmp(data, "=S\"", 3)) {
+ if (data[1] == '"')
+ data += 2;
+ else
+ data += 3;
+ value = data;
+ len = strlen(data) - 1;
+ if (data[len] != '"')
+ return -1;
+ } else {
+ value = data;
+ len = strlen(data);
+ }
+ }
+
+ new_buf = realloc(*bufp, *sizep + len);
+ if (!new_buf)
+ goto out;
+
+ memcpy(new_buf + *sizep, value, len);
+ *bufp = new_buf;
+ *sizep += len;
+
+out:
+ free(tmp_buf);
+
+ return 0;
+}
+
+/**
+ * do_env_set_efi() - set UEFI variable
+ *
+ * @cmdtp: Command table
+ * @flag: Command flag
+ * @argc: Number of arguments
+ * @argv: Argument array
+ * Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE
+ *
+ * This function is for "env set -e" or "setenv -e" command:
+ * => env set -e [-guid guid][-nv][-bs][-rt][-at][-a][-v]
+ * [-i address,size] var, or
+ * var [value ...]
+ * Encode values specified and set given UEFI variable.
+ * If no value is specified, delete the variable.
+ */
+int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *var_name, *value, *ep;
+ ulong addr;
+ efi_uintn_t size;
+ efi_guid_t guid;
+ u32 attributes;
+ bool default_guid, verbose, value_on_memory;
+ u16 *var_name16 = NULL, *p;
+ size_t len;
+ efi_status_t ret;
+
+ if (argc == 1)
+ return CMD_RET_USAGE;
+
+ /* Initialize EFI drivers */
+ ret = efi_init_obj_list();
+ if (ret != EFI_SUCCESS) {
+ printf("Error: Cannot initialize UEFI sub-system, r = %lu\n",
+ ret & ~EFI_ERROR_MASK);
+ return CMD_RET_FAILURE;
+ }
+
+ /*
+ * attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ * EFI_VARIABLE_RUNTIME_ACCESS;
+ */
+ value = NULL;
+ size = 0;
+ attributes = 0;
+ guid = efi_global_variable_guid;
+ default_guid = true;
+ verbose = false;
+ value_on_memory = false;
+ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
+ if (!strcmp(argv[0], "-guid")) {
+ if (argc == 1)
+ return CMD_RET_USAGE;
+
+ argc--;
+ argv++;
+ if (uuid_str_to_bin(argv[0], guid.b,
+ UUID_STR_FORMAT_GUID)) {
+ return CMD_RET_USAGE;
+ }
+ default_guid = false;
+ } else if (!strcmp(argv[0], "-bs")) {
+ attributes |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ } else if (!strcmp(argv[0], "-rt")) {
+ attributes |= EFI_VARIABLE_RUNTIME_ACCESS;
+ } else if (!strcmp(argv[0], "-nv")) {
+ attributes |= EFI_VARIABLE_NON_VOLATILE;
+ } else if (!strcmp(argv[0], "-at")) {
+ attributes |=
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+ } else if (!strcmp(argv[0], "-a")) {
+ attributes |= EFI_VARIABLE_APPEND_WRITE;
+ } else if (!strcmp(argv[0], "-i")) {
+ /* data comes from memory */
+ if (argc == 1)
+ return CMD_RET_USAGE;
+
+ argc--;
+ argv++;
+ addr = simple_strtoul(argv[0], &ep, 16);
+ if (*ep != ':')
+ return CMD_RET_USAGE;
+
+ /* 0 should be allowed for delete */
+ size = simple_strtoul(++ep, NULL, 16);
+
+ value_on_memory = true;
+ } else if (!strcmp(argv[0], "-v")) {
+ verbose = true;
+ } else {
+ return CMD_RET_USAGE;
+ }
+ }
+ if (!argc)
+ return CMD_RET_USAGE;
+
+ var_name = argv[0];
+ if (default_guid) {
+ if (!strcmp(var_name, "db") || !strcmp(var_name, "dbx") ||
+ !strcmp(var_name, "dbt"))
+ guid = efi_guid_image_security_database;
+ else
+ guid = efi_global_variable_guid;
+ }
+
+ if (verbose) {
+ printf("GUID: %pUl %s\n", &guid,
+ efi_guid_to_str((const efi_guid_t *)&guid));
+ printf("Attributes: 0x%x\n", attributes);
+ }
+
+ /* for value */
+ if (value_on_memory)
+ value = map_sysmem(addr, 0);
+ else if (argc > 1)
+ for (argc--, argv++; argc > 0; argc--, argv++)
+ if (append_value(&value, &size, argv[0]) < 0) {
+ printf("## Failed to process an argument, %s\n",
+ argv[0]);
+ ret = CMD_RET_FAILURE;
+ goto out;
+ }
+
+ if (size && verbose) {
+ printf("Value:\n");
+ print_hex_dump(" ", DUMP_PREFIX_OFFSET,
+ 16, 1, value, size, true);
+ }
+
+ len = utf8_utf16_strnlen(var_name, strlen(var_name));
+ var_name16 = malloc((len + 1) * 2);
+ if (!var_name16) {
+ printf("## Out of memory\n");
+ ret = CMD_RET_FAILURE;
+ goto out;
+ }
+ p = var_name16;
+ utf8_utf16_strncpy(&p, var_name, len + 1);
+
+ ret = efi_set_variable_int(var_name16, &guid, attributes, size, value,
+ true);
+ unmap_sysmem(value);
+ if (ret == EFI_SUCCESS) {
+ ret = CMD_RET_SUCCESS;
+ } else {
+ const char *msg;
+
+ switch (ret) {
+ case EFI_NOT_FOUND:
+ msg = " (not found)";
+ break;
+ case EFI_WRITE_PROTECTED:
+ msg = " (read only)";
+ break;
+ case EFI_INVALID_PARAMETER:
+ msg = " (invalid parameter)";
+ break;
+ case EFI_SECURITY_VIOLATION:
+ msg = " (validation failed)";
+ break;
+ case EFI_OUT_OF_RESOURCES:
+ msg = " (out of memory)";
+ break;
+ default:
+ msg = "";
+ break;
+ }
+ printf("## Failed to set EFI variable%s\n", msg);
+ ret = CMD_RET_FAILURE;
+ }
+out:
+ if (value_on_memory)
+ unmap_sysmem(value);
+ else
+ free(value);
+ free(var_name16);
+
+ return ret;
+}
diff --git a/roms/u-boot/cmd/nvme.c b/roms/u-boot/cmd/nvme.c
new file mode 100644
index 000000000..e715c570a
--- /dev/null
+++ b/roms/u-boot/cmd/nvme.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 NXP Semiconductors
+ * Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <command.h>
+#include <dm.h>
+#include <nvme.h>
+
+static int nvme_curr_dev;
+
+static int do_nvme(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+
+ if (argc == 2) {
+ if (strncmp(argv[1], "scan", 4) == 0) {
+ ret = nvme_scan_namespace();
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ return ret;
+ }
+ if (strncmp(argv[1], "deta", 4) == 0) {
+ struct udevice *udev;
+
+ ret = blk_get_device(IF_TYPE_NVME, nvme_curr_dev,
+ &udev);
+ if (ret < 0)
+ return CMD_RET_FAILURE;
+
+ nvme_print_info(udev);
+
+ return ret;
+ }
+ }
+
+ return blk_common_cmd(argc, argv, IF_TYPE_NVME, &nvme_curr_dev);
+}
+
+U_BOOT_CMD(
+ nvme, 8, 1, do_nvme,
+ "NVM Express sub-system",
+ "scan - scan NVMe devices\n"
+ "nvme detail - show details of current NVMe device\n"
+ "nvme info - show all available NVMe devices\n"
+ "nvme device [dev] - show or set current NVMe device\n"
+ "nvme part [dev] - print partition table of one or all NVMe devices\n"
+ "nvme read addr blk# cnt - read `cnt' blocks starting at block\n"
+ " `blk#' to memory address `addr'\n"
+ "nvme write addr blk# cnt - write `cnt' blocks starting at block\n"
+ " `blk#' from memory address `addr'"
+);
diff --git a/roms/u-boot/cmd/onenand.c b/roms/u-boot/cmd/onenand.c
new file mode 100644
index 000000000..216458bb4
--- /dev/null
+++ b/roms/u-boot/cmd/onenand.c
@@ -0,0 +1,610 @@
+/*
+ * U-Boot command for OneNAND support
+ *
+ * Copyright (C) 2005-2008 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+
+#include <linux/compat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+
+#include <asm/io.h>
+
+static struct mtd_info *mtd;
+
+static loff_t next_ofs;
+static loff_t skip_ofs;
+
+static int arg_off_size_onenand(int argc, char *const argv[], ulong *off,
+ size_t *size)
+{
+ if (argc >= 1) {
+ if (!(str2long(argv[0], off))) {
+ printf("'%s' is not a number\n", argv[0]);
+ return -1;
+ }
+ } else {
+ *off = 0;
+ }
+
+ if (argc >= 2) {
+ if (!(str2long(argv[1], (ulong *)size))) {
+ printf("'%s' is not a number\n", argv[1]);
+ return -1;
+ }
+ } else {
+ *size = mtd->size - *off;
+ }
+
+ if ((*off + *size) > mtd->size) {
+ printf("total chip size (0x%llx) exceeded!\n", mtd->size);
+ return -1;
+ }
+
+ if (*size == mtd->size)
+ puts("whole chip\n");
+ else
+ printf("offset 0x%lx, size 0x%x\n", *off, *size);
+
+ return 0;
+}
+
+static int onenand_block_read(loff_t from, size_t len,
+ size_t *retlen, u_char *buf, int oob)
+{
+ struct onenand_chip *this = mtd->priv;
+ int blocks = (int) len >> this->erase_shift;
+ int blocksize = (1 << this->erase_shift);
+ loff_t ofs = from;
+ struct mtd_oob_ops ops = {
+ .retlen = 0,
+ };
+ int ret;
+
+ if (oob)
+ ops.ooblen = blocksize;
+ else
+ ops.len = blocksize;
+
+ while (blocks) {
+ ret = mtd_block_isbad(mtd, ofs);
+ if (ret) {
+ printk("Bad blocks %d at 0x%x\n",
+ (u32)(ofs >> this->erase_shift), (u32)ofs);
+ ofs += blocksize;
+ continue;
+ }
+
+ if (oob)
+ ops.oobbuf = buf;
+ else
+ ops.datbuf = buf;
+
+ ops.retlen = 0;
+ ret = mtd_read_oob(mtd, ofs, &ops);
+ if (ret) {
+ printk("Read failed 0x%x, %d\n", (u32)ofs, ret);
+ ofs += blocksize;
+ continue;
+ }
+ ofs += blocksize;
+ buf += blocksize;
+ blocks--;
+ *retlen += ops.retlen;
+ }
+
+ return 0;
+}
+
+static int onenand_write_oneblock_withoob(loff_t to, const u_char * buf,
+ size_t *retlen)
+{
+ struct mtd_oob_ops ops = {
+ .len = mtd->writesize,
+ .ooblen = mtd->oobsize,
+ .mode = MTD_OPS_AUTO_OOB,
+ };
+ int page, ret = 0;
+ for (page = 0; page < (mtd->erasesize / mtd->writesize); page ++) {
+ ops.datbuf = (u_char *)buf;
+ buf += mtd->writesize;
+ ops.oobbuf = (u_char *)buf;
+ buf += mtd->oobsize;
+ ret = mtd_write_oob(mtd, to, &ops);
+ if (ret)
+ break;
+ to += mtd->writesize;
+ }
+
+ *retlen = (ret) ? 0 : mtd->erasesize;
+ return ret;
+}
+
+static int onenand_block_write(loff_t to, size_t len,
+ size_t *retlen, const u_char * buf, int withoob)
+{
+ struct onenand_chip *this = mtd->priv;
+ int blocks = len >> this->erase_shift;
+ int blocksize = (1 << this->erase_shift);
+ loff_t ofs;
+ size_t _retlen = 0;
+ int ret;
+
+ if ((to & (mtd->writesize - 1)) != 0) {
+ printf("Attempt to write non block-aligned data\n");
+ *retlen = 0;
+ return 1;
+ }
+
+ if (to == next_ofs) {
+ next_ofs = to + len;
+ to += skip_ofs;
+ } else {
+ next_ofs = to + len;
+ skip_ofs = 0;
+ }
+ ofs = to;
+
+ while (blocks) {
+ ret = mtd_block_isbad(mtd, ofs);
+ if (ret) {
+ printk("Bad blocks %d at 0x%x\n",
+ (u32)(ofs >> this->erase_shift), (u32)ofs);
+ skip_ofs += blocksize;
+ goto next;
+ }
+
+ if (!withoob)
+ ret = mtd_write(mtd, ofs, blocksize, &_retlen, buf);
+ else
+ ret = onenand_write_oneblock_withoob(ofs, buf, &_retlen);
+ if (ret) {
+ printk("Write failed 0x%x, %d", (u32)ofs, ret);
+ skip_ofs += blocksize;
+ goto next;
+ }
+
+ buf += blocksize;
+ blocks--;
+ *retlen += _retlen;
+next:
+ ofs += blocksize;
+ }
+
+ return 0;
+}
+
+static int onenand_block_erase(u32 start, u32 size, int force)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct erase_info instr = {
+ .callback = NULL,
+ };
+ loff_t ofs;
+ int ret;
+ int blocksize = 1 << this->erase_shift;
+
+ for (ofs = start; ofs < (start + size); ofs += blocksize) {
+ ret = mtd_block_isbad(mtd, ofs);
+ if (ret && !force) {
+ printf("Skip erase bad block %d at 0x%x\n",
+ (u32)(ofs >> this->erase_shift), (u32)ofs);
+ continue;
+ }
+
+ instr.addr = ofs;
+ instr.len = blocksize;
+ instr.priv = force;
+ instr.mtd = mtd;
+ ret = mtd_erase(mtd, &instr);
+ if (ret) {
+ printf("erase failed block %d at 0x%x\n",
+ (u32)(ofs >> this->erase_shift), (u32)ofs);
+ continue;
+ }
+ }
+
+ return 0;
+}
+
+static int onenand_block_test(u32 start, u32 size)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct erase_info instr = {
+ .callback = NULL,
+ .priv = 0,
+ };
+
+ int blocks;
+ loff_t ofs;
+ int blocksize = 1 << this->erase_shift;
+ int start_block, end_block;
+ size_t retlen;
+ u_char *buf;
+ u_char *verify_buf;
+ int ret;
+
+ buf = malloc(blocksize);
+ if (!buf) {
+ printf("Not enough malloc space available!\n");
+ return -1;
+ }
+
+ verify_buf = malloc(blocksize);
+ if (!verify_buf) {
+ printf("Not enough malloc space available!\n");
+ return -1;
+ }
+
+ start_block = start >> this->erase_shift;
+ end_block = (start + size) >> this->erase_shift;
+
+ /* Protect boot-loader from badblock testing */
+ if (start_block < 2)
+ start_block = 2;
+
+ if (end_block > (mtd->size >> this->erase_shift))
+ end_block = mtd->size >> this->erase_shift;
+
+ blocks = start_block;
+ ofs = start;
+ while (blocks < end_block) {
+ printf("\rTesting block %d at 0x%x", (u32)(ofs >> this->erase_shift), (u32)ofs);
+
+ ret = mtd_block_isbad(mtd, ofs);
+ if (ret) {
+ printf("Skip erase bad block %d at 0x%x\n",
+ (u32)(ofs >> this->erase_shift), (u32)ofs);
+ goto next;
+ }
+
+ instr.addr = ofs;
+ instr.len = blocksize;
+ ret = mtd_erase(mtd, &instr);
+ if (ret) {
+ printk("Erase failed 0x%x, %d\n", (u32)ofs, ret);
+ goto next;
+ }
+
+ ret = mtd_write(mtd, ofs, blocksize, &retlen, buf);
+ if (ret) {
+ printk("Write failed 0x%x, %d\n", (u32)ofs, ret);
+ goto next;
+ }
+
+ ret = mtd_read(mtd, ofs, blocksize, &retlen, verify_buf);
+ if (ret) {
+ printk("Read failed 0x%x, %d\n", (u32)ofs, ret);
+ goto next;
+ }
+
+ if (memcmp(buf, verify_buf, blocksize))
+ printk("\nRead/Write test failed at 0x%x\n", (u32)ofs);
+
+next:
+ ofs += blocksize;
+ blocks++;
+ }
+ printf("...Done\n");
+
+ free(buf);
+ free(verify_buf);
+
+ return 0;
+}
+
+static int onenand_dump(struct mtd_info *mtd, ulong off, int only_oob)
+{
+ int i;
+ u_char *datbuf, *oobbuf, *p;
+ struct mtd_oob_ops ops;
+ loff_t addr;
+
+ datbuf = malloc(mtd->writesize + mtd->oobsize);
+ oobbuf = malloc(mtd->oobsize);
+ if (!datbuf || !oobbuf) {
+ puts("No memory for page buffer\n");
+ return 1;
+ }
+ off &= ~(mtd->writesize - 1);
+ addr = (loff_t) off;
+ memset(&ops, 0, sizeof(ops));
+ ops.datbuf = datbuf;
+ ops.oobbuf = oobbuf;
+ ops.len = mtd->writesize;
+ ops.ooblen = mtd->oobsize;
+ ops.retlen = 0;
+ i = mtd_read_oob(mtd, addr, &ops);
+ if (i < 0) {
+ printf("Error (%d) reading page %08lx\n", i, off);
+ free(datbuf);
+ free(oobbuf);
+ return 1;
+ }
+ printf("Page %08lx dump:\n", off);
+ i = mtd->writesize >> 4;
+ p = datbuf;
+
+ while (i--) {
+ if (!only_oob)
+ printf("\t%02x %02x %02x %02x %02x %02x %02x %02x"
+ " %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+ p[8], p[9], p[10], p[11], p[12], p[13], p[14],
+ p[15]);
+ p += 16;
+ }
+ puts("OOB:\n");
+ i = mtd->oobsize >> 3;
+ p = oobbuf;
+
+ while (i--) {
+ printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ p += 8;
+ }
+ free(datbuf);
+ free(oobbuf);
+
+ return 0;
+}
+
+static int do_onenand_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ printf("%s\n", mtd->name);
+ return 0;
+}
+
+static int do_onenand_bad(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong ofs;
+
+ mtd = &onenand_mtd;
+ /* Currently only one OneNAND device is supported */
+ printf("\nDevice %d bad blocks:\n", 0);
+ for (ofs = 0; ofs < mtd->size; ofs += mtd->erasesize) {
+ if (mtd_block_isbad(mtd, ofs))
+ printf(" %08x\n", (u32)ofs);
+ }
+
+ return 0;
+}
+
+static int do_onenand_read(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *s;
+ int oob = 0;
+ ulong addr, ofs;
+ size_t len;
+ int ret = 0;
+ size_t retlen = 0;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ s = strchr(argv[0], '.');
+ if ((s != NULL) && (!strcmp(s, ".oob")))
+ oob = 1;
+
+ addr = (ulong)simple_strtoul(argv[1], NULL, 16);
+
+ printf("\nOneNAND read: ");
+ if (arg_off_size_onenand(argc - 2, argv + 2, &ofs, &len) != 0)
+ return 1;
+
+ ret = onenand_block_read(ofs, len, &retlen, (u8 *)addr, oob);
+
+ printf(" %d bytes read: %s\n", retlen, ret ? "ERROR" : "OK");
+
+ return ret == 0 ? 0 : 1;
+}
+
+static int do_onenand_write(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr, ofs;
+ size_t len;
+ int ret = 0, withoob = 0;
+ size_t retlen = 0;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if (strncmp(argv[0] + 6, "yaffs", 5) == 0)
+ withoob = 1;
+
+ addr = (ulong)simple_strtoul(argv[1], NULL, 16);
+
+ printf("\nOneNAND write: ");
+ if (arg_off_size_onenand(argc - 2, argv + 2, &ofs, &len) != 0)
+ return 1;
+
+ ret = onenand_block_write(ofs, len, &retlen, (u8 *)addr, withoob);
+
+ printf(" %d bytes written: %s\n", retlen, ret ? "ERROR" : "OK");
+
+ return ret == 0 ? 0 : 1;
+}
+
+static int do_onenand_erase(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong ofs;
+ int ret = 0;
+ size_t len;
+ int force;
+
+ /*
+ * Syntax is:
+ * 0 1 2 3 4
+ * onenand erase [force] [off size]
+ */
+ argc--;
+ argv++;
+ if (argc)
+ {
+ if (!strcmp("force", argv[0]))
+ {
+ force = 1;
+ argc--;
+ argv++;
+ }
+ }
+ printf("\nOneNAND erase: ");
+
+ /* skip first two or three arguments, look for offset and size */
+ if (arg_off_size_onenand(argc, argv, &ofs, &len) != 0)
+ return 1;
+
+ ret = onenand_block_erase(ofs, len, force);
+
+ printf("%s\n", ret ? "ERROR" : "OK");
+
+ return ret == 0 ? 0 : 1;
+}
+
+static int do_onenand_test(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong ofs;
+ int ret = 0;
+ size_t len;
+
+ /*
+ * Syntax is:
+ * 0 1 2 3 4
+ * onenand test [force] [off size]
+ */
+
+ printf("\nOneNAND test: ");
+
+ /* skip first two or three arguments, look for offset and size */
+ if (arg_off_size_onenand(argc - 1, argv + 1, &ofs, &len) != 0)
+ return 1;
+
+ ret = onenand_block_test(ofs, len);
+
+ printf("%s\n", ret ? "ERROR" : "OK");
+
+ return ret == 0 ? 0 : 1;
+}
+
+static int do_onenand_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong ofs;
+ int ret = 0;
+ char *s;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ s = strchr(argv[0], '.');
+ ofs = (int)simple_strtoul(argv[1], NULL, 16);
+
+ if (s != NULL && strcmp(s, ".oob") == 0)
+ ret = onenand_dump(mtd, ofs, 1);
+ else
+ ret = onenand_dump(mtd, ofs, 0);
+
+ return ret == 0 ? 1 : 0;
+}
+
+static int do_onenand_markbad(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret = 0;
+ ulong addr;
+
+ argc -= 2;
+ argv += 2;
+
+ if (argc <= 0)
+ return CMD_RET_USAGE;
+
+ while (argc > 0) {
+ addr = simple_strtoul(*argv, NULL, 16);
+
+ if (mtd_block_markbad(mtd, addr)) {
+ printf("block 0x%08lx NOT marked "
+ "as bad! ERROR %d\n",
+ addr, ret);
+ ret = 1;
+ } else {
+ printf("block 0x%08lx successfully "
+ "marked as bad\n",
+ addr);
+ }
+ --argc;
+ ++argv;
+ }
+ return ret;
+}
+
+static struct cmd_tbl cmd_onenand_sub[] = {
+ U_BOOT_CMD_MKENT(info, 1, 0, do_onenand_info, "", ""),
+ U_BOOT_CMD_MKENT(bad, 1, 0, do_onenand_bad, "", ""),
+ U_BOOT_CMD_MKENT(read, 4, 0, do_onenand_read, "", ""),
+ U_BOOT_CMD_MKENT(write, 4, 0, do_onenand_write, "", ""),
+ U_BOOT_CMD_MKENT(write.yaffs, 4, 0, do_onenand_write, "", ""),
+ U_BOOT_CMD_MKENT(erase, 3, 0, do_onenand_erase, "", ""),
+ U_BOOT_CMD_MKENT(test, 3, 0, do_onenand_test, "", ""),
+ U_BOOT_CMD_MKENT(dump, 2, 0, do_onenand_dump, "", ""),
+ U_BOOT_CMD_MKENT(markbad, CONFIG_SYS_MAXARGS, 0, do_onenand_markbad, "", ""),
+};
+
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+void onenand_reloc(void) {
+ fixup_cmdtable(cmd_onenand_sub, ARRAY_SIZE(cmd_onenand_sub));
+}
+#endif
+
+static int do_onenand(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ mtd = &onenand_mtd;
+
+ /* Strip off leading 'onenand' command argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], &cmd_onenand_sub[0], ARRAY_SIZE(cmd_onenand_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+ onenand, CONFIG_SYS_MAXARGS, 1, do_onenand,
+ "OneNAND sub-system",
+ "info - show available OneNAND devices\n"
+ "onenand bad - show bad blocks\n"
+ "onenand read[.oob] addr off size\n"
+ "onenand write[.yaffs] addr off size\n"
+ " read/write 'size' bytes starting at offset 'off'\n"
+ " to/from memory address 'addr', skipping bad blocks.\n"
+ "onenand erase [force] [off size] - erase 'size' bytes from\n"
+ "onenand test [off size] - test 'size' bytes from\n"
+ " offset 'off' (entire device if not specified)\n"
+ "onenand dump[.oob] off - dump page\n"
+ "onenand markbad off [...] - mark bad block(s) at offset (UNSAFE)"
+);
diff --git a/roms/u-boot/cmd/optee_rpmb.c b/roms/u-boot/cmd/optee_rpmb.c
new file mode 100644
index 000000000..0d6b1cb1d
--- /dev/null
+++ b/roms/u-boot/cmd/optee_rpmb.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+#include <command.h>
+#include <common.h>
+#include <env.h>
+#include <errno.h>
+#include <image.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <tee.h>
+#include <tee/optee_ta_avb.h>
+
+static struct udevice *tee;
+static u32 session;
+
+static int avb_ta_open_session(void)
+{
+ const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
+ struct tee_open_session_arg arg;
+ int rc;
+
+ tee = tee_find_device(tee, NULL, NULL, NULL);
+ if (!tee)
+ return -ENODEV;
+
+ memset(&arg, 0, sizeof(arg));
+ tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
+ rc = tee_open_session(tee, &arg, 0, NULL);
+ if (!rc)
+ session = arg.session;
+
+ return 0;
+}
+
+static int invoke_func(u32 func, ulong num_param, struct tee_param *param)
+{
+ struct tee_invoke_arg arg;
+
+ if (!tee)
+ if (avb_ta_open_session())
+ return -ENODEV;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.func = func;
+ arg.session = session;
+
+ if (tee_invoke_func(tee, &arg, num_param, param))
+ return -EFAULT;
+ switch (arg.ret) {
+ case TEE_SUCCESS:
+ return 0;
+ case TEE_ERROR_OUT_OF_MEMORY:
+ case TEE_ERROR_STORAGE_NO_SPACE:
+ return -ENOSPC;
+ case TEE_ERROR_ITEM_NOT_FOUND:
+ return -EIO;
+ case TEE_ERROR_TARGET_DEAD:
+ /*
+ * The TA has paniced, close the session to reload the TA
+ * for the next request.
+ */
+ tee_close_session(tee, session);
+ tee = NULL;
+ return -EIO;
+ default:
+ return -EIO;
+ }
+}
+
+static int read_persistent_value(const char *name,
+ size_t buffer_size,
+ u8 *out_buffer,
+ size_t *out_num_bytes_read)
+{
+ int rc = 0;
+ struct tee_shm *shm_name;
+ struct tee_shm *shm_buf;
+ struct tee_param param[2];
+ size_t name_size = strlen(name) + 1;
+
+ if (!tee)
+ if (avb_ta_open_session())
+ return -ENODEV;
+
+ rc = tee_shm_alloc(tee, name_size,
+ TEE_SHM_ALLOC, &shm_name);
+ if (rc)
+ return -ENOMEM;
+
+ rc = tee_shm_alloc(tee, buffer_size,
+ TEE_SHM_ALLOC, &shm_buf);
+ if (rc) {
+ rc = -ENOMEM;
+ goto free_name;
+ }
+
+ memcpy(shm_name->addr, name, name_size);
+
+ memset(param, 0, sizeof(param));
+ param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ param[0].u.memref.shm = shm_name;
+ param[0].u.memref.size = name_size;
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
+ param[1].u.memref.shm = shm_buf;
+ param[1].u.memref.size = buffer_size;
+
+ rc = invoke_func(TA_AVB_CMD_READ_PERSIST_VALUE,
+ 2, param);
+ if (rc)
+ goto out;
+
+ if (param[1].u.memref.size > buffer_size) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ *out_num_bytes_read = param[1].u.memref.size;
+
+ memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
+
+out:
+ tee_shm_free(shm_buf);
+free_name:
+ tee_shm_free(shm_name);
+
+ return rc;
+}
+
+static int write_persistent_value(const char *name,
+ size_t value_size,
+ const u8 *value)
+{
+ int rc = 0;
+ struct tee_shm *shm_name;
+ struct tee_shm *shm_buf;
+ struct tee_param param[2];
+ size_t name_size = strlen(name) + 1;
+
+ if (!tee) {
+ if (avb_ta_open_session())
+ return -ENODEV;
+ }
+ if (!value_size)
+ return -EINVAL;
+
+ rc = tee_shm_alloc(tee, name_size,
+ TEE_SHM_ALLOC, &shm_name);
+ if (rc)
+ return -ENOMEM;
+
+ rc = tee_shm_alloc(tee, value_size,
+ TEE_SHM_ALLOC, &shm_buf);
+ if (rc) {
+ rc = -ENOMEM;
+ goto free_name;
+ }
+
+ memcpy(shm_name->addr, name, name_size);
+ memcpy(shm_buf->addr, value, value_size);
+
+ memset(param, 0, sizeof(param));
+ param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ param[0].u.memref.shm = shm_name;
+ param[0].u.memref.size = name_size;
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ param[1].u.memref.shm = shm_buf;
+ param[1].u.memref.size = value_size;
+
+ rc = invoke_func(TA_AVB_CMD_WRITE_PERSIST_VALUE,
+ 2, param);
+ if (rc)
+ goto out;
+
+out:
+ tee_shm_free(shm_buf);
+free_name:
+ tee_shm_free(shm_name);
+
+ return rc;
+}
+
+int do_optee_rpmb_read(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ const char *name;
+ size_t bytes;
+ size_t bytes_read;
+ void *buffer;
+ char *endp;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ name = argv[1];
+ bytes = simple_strtoul(argv[2], &endp, 10);
+ if (*endp && *endp != '\n')
+ return CMD_RET_USAGE;
+
+ buffer = malloc(bytes);
+ if (!buffer)
+ return CMD_RET_FAILURE;
+
+ if (read_persistent_value(name, bytes, buffer, &bytes_read) == 0) {
+ printf("Read %zu bytes, value = %s\n", bytes_read,
+ (char *)buffer);
+ free(buffer);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Failed to read persistent value\n");
+
+ free(buffer);
+
+ return CMD_RET_FAILURE;
+}
+
+int do_optee_rpmb_write(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ const char *name;
+ const char *value;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ name = argv[1];
+ value = argv[2];
+
+ if (write_persistent_value(name, strlen(value) + 1,
+ (const uint8_t *)value) == 0) {
+ printf("Wrote %zu bytes\n", strlen(value) + 1);
+ return CMD_RET_SUCCESS;
+ }
+
+ printf("Failed to write persistent value\n");
+
+ return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_optee_rpmb[] = {
+ U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_optee_rpmb_read, "", ""),
+ U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_optee_rpmb_write, "", ""),
+};
+
+static int do_optee_rpmb(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ struct cmd_tbl *cp;
+
+ cp = find_cmd_tbl(argv[1], cmd_optee_rpmb, ARRAY_SIZE(cmd_optee_rpmb));
+
+ argc--;
+ argv++;
+
+ if (!cp || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+
+ if (flag == CMD_FLAG_REPEAT)
+ return CMD_RET_FAILURE;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD (
+ optee_rpmb, 29, 0, do_optee_rpmb,
+ "Provides commands for testing secure storage on RPMB on OPTEE",
+ "read_pvalue <name> <bytes> - read a persistent value <name>\n"
+ "optee_rpmb write_pvalue <name> <value> - write a persistent value <name>\n"
+ );
diff --git a/roms/u-boot/cmd/osd.c b/roms/u-boot/cmd/osd.c
new file mode 100644
index 000000000..703d640b0
--- /dev/null
+++ b/roms/u-boot/cmd/osd.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ *
+ * based on the gdsys osd driver, which is
+ *
+ * (C) Copyright 2010
+ * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <hexdump.h>
+#include <video_osd.h>
+#include <malloc.h>
+
+/* Container for selected OSD device */
+static struct udevice *osd_cur;
+
+/**
+ * cmd_osd_set_osd_num() - Set the OSD selected for operation
+ *
+ * Set the OSD device, which will be used by all subsequent OSD commands.
+ *
+ * Devices are identified by their uclass sequence number (as listed by 'osd
+ * show').
+ *
+ * @osdnum: The OSD device to be selected, identified by its sequence number.
+ * Return: 0 if OK, -ve on error
+ */
+static int cmd_osd_set_osd_num(unsigned int osdnum)
+{
+ struct udevice *osd;
+ int res;
+
+ res = uclass_get_device_by_seq(UCLASS_VIDEO_OSD, osdnum, &osd);
+ if (res) {
+ printf("%s: No OSD %u (err = %d)\n", __func__, osdnum, res);
+ return res;
+ }
+ osd_cur = osd;
+
+ return 0;
+}
+
+/**
+ * osd_get_osd_cur() - Get the selected OSD device
+ *
+ * Get the OSD device that is used by all OSD commands.
+ *
+ * @osdp: Pointer to structure that will receive the currently selected OSD
+ * device.
+ * Return: 0 if OK, -ve on error
+ */
+static int osd_get_osd_cur(struct udevice **osdp)
+{
+ if (!osd_cur) {
+ puts("No osd selected\n");
+ return -ENODEV;
+ }
+ *osdp = osd_cur;
+
+ return 0;
+}
+
+/**
+ * show_osd() - Display information about a OSD device
+ *
+ * Display a device's ID (sequence number), and whether it is active (i.e.
+ * probed) or not.
+ *
+ * @osd: OSD device to print information for
+ */
+static void show_osd(struct udevice *osd)
+{
+ printf("OSD %d:\t%s", dev_seq(osd), osd->name);
+ if (device_active(osd))
+ printf(" (active)");
+ printf("\n");
+}
+
+static int do_osd_write(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint x, y;
+ uint count;
+ char *hexstr;
+ u8 *buffer;
+ size_t buflen;
+ int res;
+
+ if (argc < 4 || (strlen(argv[3]) % 2))
+ return CMD_RET_USAGE;
+
+ if (!osd_cur) {
+ puts("No osd selected\n");
+ return CMD_RET_FAILURE;
+ }
+
+ x = simple_strtoul(argv[1], NULL, 16);
+ y = simple_strtoul(argv[2], NULL, 16);
+ hexstr = argv[3];
+ count = (argc > 4) ? simple_strtoul(argv[4], NULL, 16) : 1;
+
+ buflen = strlen(hexstr) / 2;
+
+ buffer = malloc(buflen);
+ if (!buffer) {
+ puts("Memory allocation failure\n");
+ return CMD_RET_FAILURE;
+ }
+
+ res = hex2bin(buffer, hexstr, buflen);
+ if (res) {
+ free(buffer);
+ puts("Hexadecimal input contained invalid characters\n");
+ return CMD_RET_FAILURE;
+ }
+
+ res = video_osd_set_mem(osd_cur, x, y, buffer, buflen, count);
+ if (res) {
+ free(buffer);
+ printf("%s: Could not write to video mem\n",
+ osd_cur->name);
+ return CMD_RET_FAILURE;
+ }
+
+ free(buffer);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_osd_print(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint x, y;
+ u8 color;
+ char *text;
+ int res;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ if (!osd_cur) {
+ puts("No osd selected\n");
+ return CMD_RET_FAILURE;
+ }
+
+ x = simple_strtoul(argv[1], NULL, 16);
+ y = simple_strtoul(argv[2], NULL, 16);
+ color = simple_strtoul(argv[3], NULL, 16);
+ text = argv[4];
+
+ res = video_osd_print(osd_cur, x, y, color, text);
+ if (res) {
+ printf("Could not print string to osd %s\n", osd_cur->name);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_osd_size(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ uint x, y;
+ int res;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if (!osd_cur) {
+ puts("No osd selected\n");
+ return CMD_RET_FAILURE;
+ }
+
+ x = simple_strtoul(argv[1], NULL, 16);
+ y = simple_strtoul(argv[2], NULL, 16);
+
+ res = video_osd_set_size(osd_cur, x, y);
+ if (res) {
+ printf("Could not set size on osd %s\n", osd_cur->name);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_show_osd(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *osd;
+
+ if (argc == 1) {
+ /* show all OSDs */
+ struct uclass *uc;
+ int res;
+
+ res = uclass_get(UCLASS_VIDEO_OSD, &uc);
+ if (res) {
+ printf("Error while getting OSD uclass (err=%d)\n",
+ res);
+ return CMD_RET_FAILURE;
+ }
+
+ uclass_foreach_dev(osd, uc)
+ show_osd(osd);
+ } else {
+ int i, res;
+
+ /* show specific OSD */
+ i = simple_strtoul(argv[1], NULL, 10);
+
+ res = uclass_get_device_by_seq(UCLASS_VIDEO_OSD, i, &osd);
+ if (res) {
+ printf("Invalid osd %d: err=%d\n", i, res);
+ return CMD_RET_FAILURE;
+ }
+ show_osd(osd);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_osd_num(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int osd_no;
+ int res = 0;
+
+ if (argc == 1) {
+ /* querying current setting */
+ struct udevice *osd;
+
+ if (!osd_get_osd_cur(&osd))
+ osd_no = dev_seq(osd);
+ else
+ osd_no = -1;
+ printf("Current osd is %d\n", osd_no);
+ } else {
+ osd_no = simple_strtoul(argv[1], NULL, 10);
+ printf("Setting osd to %d\n", osd_no);
+
+ res = cmd_osd_set_osd_num(osd_no);
+ if (res)
+ printf("Failure changing osd number (err = %d)\n", res);
+ }
+
+ return res ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl cmd_osd_sub[] = {
+ U_BOOT_CMD_MKENT(show, 1, 1, do_show_osd, "", ""),
+ U_BOOT_CMD_MKENT(dev, 1, 1, do_osd_num, "", ""),
+ U_BOOT_CMD_MKENT(write, 4, 1, do_osd_write, "", ""),
+ U_BOOT_CMD_MKENT(print, 4, 1, do_osd_print, "", ""),
+ U_BOOT_CMD_MKENT(size, 2, 1, do_osd_size, "", ""),
+};
+
+static int do_osd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* Strip off leading 'osd' command argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], &cmd_osd_sub[0], ARRAY_SIZE(cmd_osd_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+static char osd_help_text[] =
+ "show - show OSD info\n"
+ "osd dev [dev] - show or set current OSD\n"
+ "write [pos_x] [pos_y] [buffer] [count] - write 8-bit hex encoded buffer to osd memory at a given position\n"
+ "print [pos_x] [pos_y] [color] [text] - write ASCII buffer (given by text data and driver-specific color information) to osd memory\n"
+ "size [size_x] [size_y] - set OSD XY size in characters\n";
+
+U_BOOT_CMD(
+ osd, 6, 1, do_osd,
+ "OSD sub-system",
+ osd_help_text
+);
diff --git a/roms/u-boot/cmd/panic.c b/roms/u-boot/cmd/panic.c
new file mode 100644
index 000000000..f13b3f094
--- /dev/null
+++ b/roms/u-boot/cmd/panic.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_panic(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ char *text = (argc < 2) ? "" : argv[1];
+
+ panic(text);
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ panic, 2, 1, do_panic,
+ "Panic with optional message",
+ "[message]"
+);
diff --git a/roms/u-boot/cmd/part.c b/roms/u-boot/cmd/part.c
new file mode 100644
index 000000000..3395c17b8
--- /dev/null
+++ b/roms/u-boot/cmd/part.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * made from cmd_ext2, which was:
+ *
+ * (C) Copyright 2004
+ * esd gmbh <www.esd-electronics.com>
+ * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
+ *
+ * made from cmd_reiserfs by
+ *
+ * (C) Copyright 2003 - 2004
+ * Sysgo Real-Time Solutions, AG <www.elinos.com>
+ * Pavel Bartusek <pba@sysgo.com>
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <env.h>
+#include <part.h>
+#include <vsprintf.h>
+
+enum cmd_part_info {
+ CMD_PART_INFO_START = 0,
+ CMD_PART_INFO_SIZE,
+ CMD_PART_INFO_NUMBER
+};
+
+static int do_part_uuid(int argc, char *const argv[])
+{
+ int part;
+ struct blk_desc *dev_desc;
+ struct disk_partition info;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ if (argc > 3)
+ return CMD_RET_USAGE;
+
+ part = blk_get_device_part_str(argv[0], argv[1], &dev_desc, &info, 0);
+ if (part < 0)
+ return 1;
+
+ if (argc > 2)
+ env_set(argv[2], info.uuid);
+ else
+ printf("%s\n", info.uuid);
+
+ return 0;
+}
+
+static int do_part_list(int argc, char *const argv[])
+{
+ int ret;
+ struct blk_desc *desc;
+ char *var = NULL;
+ bool bootable = false;
+ int i;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (argc > 2) {
+ for (i = 2; i < argc ; i++) {
+ if (argv[i][0] == '-') {
+ if (!strcmp(argv[i], "-bootable")) {
+ bootable = true;
+ } else {
+ printf("Unknown option %s\n", argv[i]);
+ return CMD_RET_USAGE;
+ }
+ } else {
+ var = argv[i];
+ break;
+ }
+ }
+
+ /* Loops should have been exited at the last argument, which
+ * as it contained the variable */
+ if (argc != i + 1)
+ return CMD_RET_USAGE;
+ }
+
+ ret = blk_get_device_by_str(argv[0], argv[1], &desc);
+ if (ret < 0)
+ return 1;
+
+ if (var != NULL) {
+ int p;
+ char str[512] = { '\0', };
+ struct disk_partition info;
+
+ for (p = 1; p < MAX_SEARCH_PARTITIONS; p++) {
+ char t[5];
+ int r = part_get_info(desc, p, &info);
+
+ if (r != 0)
+ continue;
+
+ if (bootable && !info.bootable)
+ continue;
+
+ sprintf(t, "%s%x", str[0] ? " " : "", p);
+ strcat(str, t);
+ }
+ env_set(var, str);
+ return 0;
+ }
+
+ part_print(desc);
+
+ return 0;
+}
+
+static int do_part_info(int argc, char *const argv[], enum cmd_part_info param)
+{
+ struct blk_desc *desc;
+ struct disk_partition info;
+ char buf[512] = { 0 };
+ char *endp;
+ int part;
+ int err;
+ int ret;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+ if (argc > 4)
+ return CMD_RET_USAGE;
+
+ ret = blk_get_device_by_str(argv[0], argv[1], &desc);
+ if (ret < 0)
+ return 1;
+
+ part = simple_strtoul(argv[2], &endp, 0);
+ if (*endp == '\0') {
+ err = part_get_info(desc, part, &info);
+ if (err)
+ return 1;
+ } else {
+ part = part_get_info_by_name(desc, argv[2], &info);
+ if (part == -1)
+ return 1;
+ }
+
+ switch (param) {
+ case CMD_PART_INFO_START:
+ snprintf(buf, sizeof(buf), LBAF, info.start);
+ break;
+ case CMD_PART_INFO_SIZE:
+ snprintf(buf, sizeof(buf), LBAF, info.size);
+ break;
+ case CMD_PART_INFO_NUMBER:
+ snprintf(buf, sizeof(buf), "0x%x", part);
+ break;
+ default:
+ printf("** Unknown cmd_part_info value: %d\n", param);
+ return 1;
+ }
+
+ if (argc > 3)
+ env_set(argv[3], buf);
+ else
+ printf("%s\n", buf);
+
+ return 0;
+}
+
+static int do_part_start(int argc, char *const argv[])
+{
+ return do_part_info(argc, argv, CMD_PART_INFO_START);
+}
+
+static int do_part_size(int argc, char *const argv[])
+{
+ return do_part_info(argc, argv, CMD_PART_INFO_SIZE);
+}
+
+static int do_part_number(int argc, char *const argv[])
+{
+ return do_part_info(argc, argv, CMD_PART_INFO_NUMBER);
+}
+
+static int do_part_types(int argc, char * const argv[])
+{
+ struct part_driver *drv = ll_entry_start(struct part_driver,
+ part_driver);
+ const int n_ents = ll_entry_count(struct part_driver, part_driver);
+ struct part_driver *entry;
+ int i = 0;
+
+ puts("Supported partition tables");
+
+ for (entry = drv; entry != drv + n_ents; entry++) {
+ printf("%c %s", i ? ',' : ':', entry->name);
+ i++;
+ }
+ if (!i)
+ puts(": <none>");
+ puts("\n");
+ return CMD_RET_SUCCESS;
+}
+
+static int do_part(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(argv[1], "uuid"))
+ return do_part_uuid(argc - 2, argv + 2);
+ else if (!strcmp(argv[1], "list"))
+ return do_part_list(argc - 2, argv + 2);
+ else if (!strcmp(argv[1], "start"))
+ return do_part_start(argc - 2, argv + 2);
+ else if (!strcmp(argv[1], "size"))
+ return do_part_size(argc - 2, argv + 2);
+ else if (!strcmp(argv[1], "number"))
+ return do_part_number(argc - 2, argv + 2);
+ else if (!strcmp(argv[1], "types"))
+ return do_part_types(argc - 2, argv + 2);
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+ part, CONFIG_SYS_MAXARGS, 1, do_part,
+ "disk partition related commands",
+ "uuid <interface> <dev>:<part>\n"
+ " - print partition UUID\n"
+ "part uuid <interface> <dev>:<part> <varname>\n"
+ " - set environment variable to partition UUID\n"
+ "part list <interface> <dev>\n"
+ " - print a device's partition table\n"
+ "part list <interface> <dev> [flags] <varname>\n"
+ " - set environment variable to the list of partitions\n"
+ " flags can be -bootable (list only bootable partitions)\n"
+ "part start <interface> <dev> <part> <varname>\n"
+ " - set environment variable to the start of the partition (in blocks)\n"
+ " part can be either partition number or partition name\n"
+ "part size <interface> <dev> <part> <varname>\n"
+ " - set environment variable to the size of the partition (in blocks)\n"
+ " part can be either partition number or partition name\n"
+ "part number <interface> <dev> <part> <varname>\n"
+ " - set environment variable to the partition number using the partition name\n"
+ " part must be specified as partition name\n"
+ "part types\n"
+ " - list supported partition table types"
+);
diff --git a/roms/u-boot/cmd/pcap.c b/roms/u-boot/cmd/pcap.c
new file mode 100644
index 000000000..d0172f3ff
--- /dev/null
+++ b/roms/u-boot/cmd/pcap.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Ramon Fried <rfried.dev@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <net/pcap.h>
+
+static int do_pcap_init(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ phys_addr_t addr;
+ unsigned int size;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[1], NULL, 16);
+ size = simple_strtoul(argv[2], NULL, 10);
+
+ return pcap_init(addr, size) ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static int do_pcap_start(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return pcap_start_stop(true) ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static int do_pcap_stop(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return pcap_start_stop(false) ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static int do_pcap_status(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return pcap_print_status() ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static int do_pcap_clear(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return pcap_clear() ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+static char pcap_help_text[] =
+ "- network packet capture\n\n"
+ "pcap\n"
+ "pcap init\t\t\t<addr> <max_size>\n"
+ "pcap start\t\t\tstart capture\n"
+ "pcap stop\t\t\tstop capture\n"
+ "pcap status\t\t\tprint status\n"
+ "pcap clear\t\t\tclear capture buffer\n"
+ "\n"
+ "With:\n"
+ "\t<addr>: user address to which pcap will be stored (hexedcimal)\n"
+ "\t<max_size>: Maximum size of pcap file (decimal)\n"
+ "\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(pcap, "pcap", pcap_help_text,
+ U_BOOT_SUBCMD_MKENT(init, 3, 0, do_pcap_init),
+ U_BOOT_SUBCMD_MKENT(start, 1, 0, do_pcap_start),
+ U_BOOT_SUBCMD_MKENT(stop, 1, 0, do_pcap_stop),
+ U_BOOT_SUBCMD_MKENT(status, 1, 0, do_pcap_status),
+ U_BOOT_SUBCMD_MKENT(clear, 1, 0, do_pcap_clear),
+);
diff --git a/roms/u-boot/cmd/pci.c b/roms/u-boot/cmd/pci.c
new file mode 100644
index 000000000..e53b7c858
--- /dev/null
+++ b/roms/u-boot/cmd/pci.c
@@ -0,0 +1,811 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de.
+ */
+
+/*
+ * PCI routines
+ */
+
+#include <common.h>
+#include <bootretry.h>
+#include <cli.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <init.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+
+struct pci_reg_info {
+ const char *name;
+ enum pci_size_t size;
+ u8 offset;
+};
+
+static int pci_byte_size(enum pci_size_t size)
+{
+ switch (size) {
+ case PCI_SIZE_8:
+ return 1;
+ case PCI_SIZE_16:
+ return 2;
+ case PCI_SIZE_32:
+ default:
+ return 4;
+ }
+}
+
+static int pci_field_width(enum pci_size_t size)
+{
+ return pci_byte_size(size) * 2;
+}
+
+#ifdef CONFIG_DM_PCI
+static void pci_show_regs(struct udevice *dev, struct pci_reg_info *regs)
+{
+ for (; regs->name; regs++) {
+ unsigned long val;
+
+ dm_pci_read_config(dev, regs->offset, &val, regs->size);
+ printf(" %s =%*s%#.*lx\n", regs->name,
+ (int)(28 - strlen(regs->name)), "",
+ pci_field_width(regs->size), val);
+ }
+}
+#else
+static unsigned long pci_read_config(pci_dev_t dev, int offset,
+ enum pci_size_t size)
+{
+ u32 val32;
+ u16 val16;
+ u8 val8;
+
+ switch (size) {
+ case PCI_SIZE_8:
+ pci_read_config_byte(dev, offset, &val8);
+ return val8;
+ case PCI_SIZE_16:
+ pci_read_config_word(dev, offset, &val16);
+ return val16;
+ case PCI_SIZE_32:
+ default:
+ pci_read_config_dword(dev, offset, &val32);
+ return val32;
+ }
+}
+
+static void pci_show_regs(pci_dev_t dev, struct pci_reg_info *regs)
+{
+ for (; regs->name; regs++) {
+ printf(" %s =%*s%#.*lx\n", regs->name,
+ (int)(28 - strlen(regs->name)), "",
+ pci_field_width(regs->size),
+ pci_read_config(dev, regs->offset, regs->size));
+ }
+}
+#endif
+
+#ifdef CONFIG_DM_PCI
+int pci_bar_show(struct udevice *dev)
+{
+ u8 header_type;
+ int bar_cnt, bar_id, mem_type;
+ bool is_64, is_io;
+ u32 base_low, base_high;
+ u32 size_low, size_high;
+ u64 base, size;
+ u32 reg_addr;
+ int prefetchable;
+
+ dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
+
+ if (header_type == PCI_HEADER_TYPE_CARDBUS) {
+ printf("CardBus doesn't support BARs\n");
+ return -ENOSYS;
+ }
+
+ bar_cnt = (header_type == PCI_HEADER_TYPE_NORMAL) ? 6 : 2;
+
+ printf("ID Base Size Width Type\n");
+ printf("----------------------------------------------------------\n");
+
+ bar_id = 0;
+ reg_addr = PCI_BASE_ADDRESS_0;
+ while (bar_cnt) {
+ dm_pci_read_config32(dev, reg_addr, &base_low);
+ dm_pci_write_config32(dev, reg_addr, 0xffffffff);
+ dm_pci_read_config32(dev, reg_addr, &size_low);
+ dm_pci_write_config32(dev, reg_addr, base_low);
+ reg_addr += 4;
+
+ base = base_low & ~0xf;
+ size = size_low & ~0xf;
+ base_high = 0x0;
+ size_high = 0xffffffff;
+ is_64 = 0;
+ prefetchable = base_low & PCI_BASE_ADDRESS_MEM_PREFETCH;
+ is_io = base_low & PCI_BASE_ADDRESS_SPACE_IO;
+ mem_type = base_low & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+
+ if (mem_type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ dm_pci_read_config32(dev, reg_addr, &base_high);
+ dm_pci_write_config32(dev, reg_addr, 0xffffffff);
+ dm_pci_read_config32(dev, reg_addr, &size_high);
+ dm_pci_write_config32(dev, reg_addr, base_high);
+ bar_cnt--;
+ reg_addr += 4;
+ is_64 = 1;
+ }
+
+ base = base | ((u64)base_high << 32);
+ size = size | ((u64)size_high << 32);
+
+ if ((!is_64 && size_low) || (is_64 && size)) {
+ size = ~size + 1;
+ printf(" %d %#018llx %#018llx %d %s %s\n",
+ bar_id, (unsigned long long)base,
+ (unsigned long long)size, is_64 ? 64 : 32,
+ is_io ? "I/O" : "MEM",
+ prefetchable ? "Prefetchable" : "");
+ }
+
+ bar_id++;
+ bar_cnt--;
+ }
+
+ return 0;
+}
+#endif
+
+static struct pci_reg_info regs_start[] = {
+ { "vendor ID", PCI_SIZE_16, PCI_VENDOR_ID },
+ { "device ID", PCI_SIZE_16, PCI_DEVICE_ID },
+ { "command register ID", PCI_SIZE_16, PCI_COMMAND },
+ { "status register", PCI_SIZE_16, PCI_STATUS },
+ { "revision ID", PCI_SIZE_8, PCI_REVISION_ID },
+ {},
+};
+
+static struct pci_reg_info regs_rest[] = {
+ { "sub class code", PCI_SIZE_8, PCI_CLASS_SUB_CODE },
+ { "programming interface", PCI_SIZE_8, PCI_CLASS_PROG },
+ { "cache line", PCI_SIZE_8, PCI_CACHE_LINE_SIZE },
+ { "latency time", PCI_SIZE_8, PCI_LATENCY_TIMER },
+ { "header type", PCI_SIZE_8, PCI_HEADER_TYPE },
+ { "BIST", PCI_SIZE_8, PCI_BIST },
+ { "base address 0", PCI_SIZE_32, PCI_BASE_ADDRESS_0 },
+ {},
+};
+
+static struct pci_reg_info regs_normal[] = {
+ { "base address 1", PCI_SIZE_32, PCI_BASE_ADDRESS_1 },
+ { "base address 2", PCI_SIZE_32, PCI_BASE_ADDRESS_2 },
+ { "base address 3", PCI_SIZE_32, PCI_BASE_ADDRESS_3 },
+ { "base address 4", PCI_SIZE_32, PCI_BASE_ADDRESS_4 },
+ { "base address 5", PCI_SIZE_32, PCI_BASE_ADDRESS_5 },
+ { "cardBus CIS pointer", PCI_SIZE_32, PCI_CARDBUS_CIS },
+ { "sub system vendor ID", PCI_SIZE_16, PCI_SUBSYSTEM_VENDOR_ID },
+ { "sub system ID", PCI_SIZE_16, PCI_SUBSYSTEM_ID },
+ { "expansion ROM base address", PCI_SIZE_32, PCI_ROM_ADDRESS },
+ { "interrupt line", PCI_SIZE_8, PCI_INTERRUPT_LINE },
+ { "interrupt pin", PCI_SIZE_8, PCI_INTERRUPT_PIN },
+ { "min Grant", PCI_SIZE_8, PCI_MIN_GNT },
+ { "max Latency", PCI_SIZE_8, PCI_MAX_LAT },
+ {},
+};
+
+static struct pci_reg_info regs_bridge[] = {
+ { "base address 1", PCI_SIZE_32, PCI_BASE_ADDRESS_1 },
+ { "primary bus number", PCI_SIZE_8, PCI_PRIMARY_BUS },
+ { "secondary bus number", PCI_SIZE_8, PCI_SECONDARY_BUS },
+ { "subordinate bus number", PCI_SIZE_8, PCI_SUBORDINATE_BUS },
+ { "secondary latency timer", PCI_SIZE_8, PCI_SEC_LATENCY_TIMER },
+ { "IO base", PCI_SIZE_8, PCI_IO_BASE },
+ { "IO limit", PCI_SIZE_8, PCI_IO_LIMIT },
+ { "secondary status", PCI_SIZE_16, PCI_SEC_STATUS },
+ { "memory base", PCI_SIZE_16, PCI_MEMORY_BASE },
+ { "memory limit", PCI_SIZE_16, PCI_MEMORY_LIMIT },
+ { "prefetch memory base", PCI_SIZE_16, PCI_PREF_MEMORY_BASE },
+ { "prefetch memory limit", PCI_SIZE_16, PCI_PREF_MEMORY_LIMIT },
+ { "prefetch memory base upper", PCI_SIZE_32, PCI_PREF_BASE_UPPER32 },
+ { "prefetch memory limit upper", PCI_SIZE_32, PCI_PREF_LIMIT_UPPER32 },
+ { "IO base upper 16 bits", PCI_SIZE_16, PCI_IO_BASE_UPPER16 },
+ { "IO limit upper 16 bits", PCI_SIZE_16, PCI_IO_LIMIT_UPPER16 },
+ { "expansion ROM base address", PCI_SIZE_32, PCI_ROM_ADDRESS1 },
+ { "interrupt line", PCI_SIZE_8, PCI_INTERRUPT_LINE },
+ { "interrupt pin", PCI_SIZE_8, PCI_INTERRUPT_PIN },
+ { "bridge control", PCI_SIZE_16, PCI_BRIDGE_CONTROL },
+ {},
+};
+
+static struct pci_reg_info regs_cardbus[] = {
+ { "capabilities", PCI_SIZE_8, PCI_CB_CAPABILITY_LIST },
+ { "secondary status", PCI_SIZE_16, PCI_CB_SEC_STATUS },
+ { "primary bus number", PCI_SIZE_8, PCI_CB_PRIMARY_BUS },
+ { "CardBus number", PCI_SIZE_8, PCI_CB_CARD_BUS },
+ { "subordinate bus number", PCI_SIZE_8, PCI_CB_SUBORDINATE_BUS },
+ { "CardBus latency timer", PCI_SIZE_8, PCI_CB_LATENCY_TIMER },
+ { "CardBus memory base 0", PCI_SIZE_32, PCI_CB_MEMORY_BASE_0 },
+ { "CardBus memory limit 0", PCI_SIZE_32, PCI_CB_MEMORY_LIMIT_0 },
+ { "CardBus memory base 1", PCI_SIZE_32, PCI_CB_MEMORY_BASE_1 },
+ { "CardBus memory limit 1", PCI_SIZE_32, PCI_CB_MEMORY_LIMIT_1 },
+ { "CardBus IO base 0", PCI_SIZE_16, PCI_CB_IO_BASE_0 },
+ { "CardBus IO base high 0", PCI_SIZE_16, PCI_CB_IO_BASE_0_HI },
+ { "CardBus IO limit 0", PCI_SIZE_16, PCI_CB_IO_LIMIT_0 },
+ { "CardBus IO limit high 0", PCI_SIZE_16, PCI_CB_IO_LIMIT_0_HI },
+ { "CardBus IO base 1", PCI_SIZE_16, PCI_CB_IO_BASE_1 },
+ { "CardBus IO base high 1", PCI_SIZE_16, PCI_CB_IO_BASE_1_HI },
+ { "CardBus IO limit 1", PCI_SIZE_16, PCI_CB_IO_LIMIT_1 },
+ { "CardBus IO limit high 1", PCI_SIZE_16, PCI_CB_IO_LIMIT_1_HI },
+ { "interrupt line", PCI_SIZE_8, PCI_INTERRUPT_LINE },
+ { "interrupt pin", PCI_SIZE_8, PCI_INTERRUPT_PIN },
+ { "bridge control", PCI_SIZE_16, PCI_CB_BRIDGE_CONTROL },
+ { "subvendor ID", PCI_SIZE_16, PCI_CB_SUBSYSTEM_VENDOR_ID },
+ { "subdevice ID", PCI_SIZE_16, PCI_CB_SUBSYSTEM_ID },
+ { "PC Card 16bit base address", PCI_SIZE_32, PCI_CB_LEGACY_MODE_BASE },
+ {},
+};
+
+/**
+ * pci_header_show() - Show the header of the specified PCI device.
+ *
+ * @dev: Bus+Device+Function number
+ */
+#ifdef CONFIG_DM_PCI
+void pci_header_show(struct udevice *dev)
+#else
+void pci_header_show(pci_dev_t dev)
+#endif
+{
+#ifdef CONFIG_DM_PCI
+ unsigned long class, header_type;
+
+ dm_pci_read_config(dev, PCI_CLASS_CODE, &class, PCI_SIZE_8);
+ dm_pci_read_config(dev, PCI_HEADER_TYPE, &header_type, PCI_SIZE_8);
+#else
+ u8 class, header_type;
+
+ pci_read_config_byte(dev, PCI_CLASS_CODE, &class);
+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+#endif
+ pci_show_regs(dev, regs_start);
+ printf(" class code = 0x%.2x (%s)\n", (int)class,
+ pci_class_str(class));
+ pci_show_regs(dev, regs_rest);
+
+ switch (header_type & 0x03) {
+ case PCI_HEADER_TYPE_NORMAL: /* "normal" PCI device */
+ pci_show_regs(dev, regs_normal);
+ break;
+ case PCI_HEADER_TYPE_BRIDGE: /* PCI-to-PCI bridge */
+ pci_show_regs(dev, regs_bridge);
+ break;
+ case PCI_HEADER_TYPE_CARDBUS: /* PCI-to-CardBus bridge */
+ pci_show_regs(dev, regs_cardbus);
+ break;
+
+ default:
+ printf("unknown header\n");
+ break;
+ }
+}
+
+void pciinfo_header(int busnum, bool short_listing)
+{
+ printf("Scanning PCI devices on bus %d\n", busnum);
+
+ if (short_listing) {
+ printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
+ printf("_____________________________________________________________\n");
+ }
+}
+
+#ifdef CONFIG_DM_PCI
+/**
+ * pci_header_show_brief() - Show the short-form PCI device header
+ *
+ * Reads and prints the header of the specified PCI device in short form.
+ *
+ * @dev: PCI device to show
+ */
+static void pci_header_show_brief(struct udevice *dev)
+{
+ ulong vendor, device;
+ ulong class, subclass;
+
+ dm_pci_read_config(dev, PCI_VENDOR_ID, &vendor, PCI_SIZE_16);
+ dm_pci_read_config(dev, PCI_DEVICE_ID, &device, PCI_SIZE_16);
+ dm_pci_read_config(dev, PCI_CLASS_CODE, &class, PCI_SIZE_8);
+ dm_pci_read_config(dev, PCI_CLASS_SUB_CODE, &subclass, PCI_SIZE_8);
+
+ printf("0x%.4lx 0x%.4lx %-23s 0x%.2lx\n",
+ vendor, device,
+ pci_class_str(class), subclass);
+}
+
+static void pciinfo(struct udevice *bus, bool short_listing)
+{
+ struct udevice *dev;
+
+ pciinfo_header(dev_seq(bus), short_listing);
+
+ for (device_find_first_child(bus, &dev);
+ dev;
+ device_find_next_child(&dev)) {
+ struct pci_child_plat *pplat;
+
+ pplat = dev_get_parent_plat(dev);
+ if (short_listing) {
+ printf("%02x.%02x.%02x ", dev_seq(bus),
+ PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn));
+ pci_header_show_brief(dev);
+ } else {
+ printf("\nFound PCI device %02x.%02x.%02x:\n",
+ dev_seq(bus),
+ PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn));
+ pci_header_show(dev);
+ }
+ }
+}
+
+#else
+
+/**
+ * pci_header_show_brief() - Show the short-form PCI device header
+ *
+ * Reads and prints the header of the specified PCI device in short form.
+ *
+ * @dev: Bus+Device+Function number
+ */
+void pci_header_show_brief(pci_dev_t dev)
+{
+ u16 vendor, device;
+ u8 class, subclass;
+
+ pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
+ pci_read_config_word(dev, PCI_DEVICE_ID, &device);
+ pci_read_config_byte(dev, PCI_CLASS_CODE, &class);
+ pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &subclass);
+
+ printf("0x%.4x 0x%.4x %-23s 0x%.2x\n",
+ vendor, device,
+ pci_class_str(class), subclass);
+}
+
+/**
+ * pciinfo() - Show a list of devices on the PCI bus
+ *
+ * Show information about devices on PCI bus. Depending on @short_pci_listing
+ * the output will be more or less exhaustive.
+ *
+ * @bus_num: The number of the bus to be scanned
+ * @short_pci_listing: true to use short form, showing only a brief header
+ * for each device
+ */
+void pciinfo(int bus_num, int short_pci_listing)
+{
+ struct pci_controller *hose = pci_bus_to_hose(bus_num);
+ int device;
+ int function;
+ unsigned char header_type;
+ unsigned short vendor_id;
+ pci_dev_t dev;
+ int ret;
+
+ if (!hose)
+ return;
+
+ pciinfo_header(bus_num, short_pci_listing);
+
+ for (device = 0; device < PCI_MAX_PCI_DEVICES; device++) {
+ header_type = 0;
+ vendor_id = 0;
+ for (function = 0; function < PCI_MAX_PCI_FUNCTIONS;
+ function++) {
+ /*
+ * If this is not a multi-function device, we skip
+ * the rest.
+ */
+ if (function && !(header_type & 0x80))
+ break;
+
+ dev = PCI_BDF(bus_num, device, function);
+
+ if (pci_skip_dev(hose, dev))
+ continue;
+
+ ret = pci_read_config_word(dev, PCI_VENDOR_ID,
+ &vendor_id);
+ if (ret)
+ goto error;
+ if ((vendor_id == 0xFFFF) || (vendor_id == 0x0000))
+ continue;
+
+ if (!function) {
+ pci_read_config_byte(dev, PCI_HEADER_TYPE,
+ &header_type);
+ }
+
+ if (short_pci_listing) {
+ printf("%02x.%02x.%02x ", bus_num, device,
+ function);
+ pci_header_show_brief(dev);
+ } else {
+ printf("\nFound PCI device %02x.%02x.%02x:\n",
+ bus_num, device, function);
+ pci_header_show(dev);
+ }
+ }
+ }
+
+ return;
+error:
+ printf("Cannot read bus configuration: %d\n", ret);
+}
+#endif
+
+/**
+ * get_pci_dev() - Convert the "bus.device.function" identifier into a number
+ *
+ * @name: Device string in the form "bus.device.function" where each is in hex
+ * @return encoded pci_dev_t or -1 if the string was invalid
+ */
+static pci_dev_t get_pci_dev(char *name)
+{
+ char cnum[12];
+ int len, i, iold, n;
+ int bdfs[3] = {0,0,0};
+
+ len = strlen(name);
+ if (len > 8)
+ return -1;
+ for (i = 0, iold = 0, n = 0; i < len; i++) {
+ if (name[i] == '.') {
+ memcpy(cnum, &name[iold], i - iold);
+ cnum[i - iold] = '\0';
+ bdfs[n++] = simple_strtoul(cnum, NULL, 16);
+ iold = i + 1;
+ }
+ }
+ strcpy(cnum, &name[iold]);
+ if (n == 0)
+ n = 1;
+ bdfs[n] = simple_strtoul(cnum, NULL, 16);
+
+ return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]);
+}
+
+#ifdef CONFIG_DM_PCI
+static int pci_cfg_display(struct udevice *dev, ulong addr,
+ enum pci_size_t size, ulong length)
+#else
+static int pci_cfg_display(pci_dev_t bdf, ulong addr, enum pci_size_t size,
+ ulong length)
+#endif
+{
+#define DISP_LINE_LEN 16
+ ulong i, nbytes, linebytes;
+ int byte_size;
+ int rc = 0;
+
+ byte_size = pci_byte_size(size);
+ if (length == 0)
+ length = 0x40 / byte_size; /* Standard PCI config space */
+
+ /* Print the lines.
+ * once, and all accesses are with the specified bus width.
+ */
+ nbytes = length * byte_size;
+ do {
+ printf("%08lx:", addr);
+ linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
+ for (i = 0; i < linebytes; i += byte_size) {
+ unsigned long val;
+
+#ifdef CONFIG_DM_PCI
+ dm_pci_read_config(dev, addr, &val, size);
+#else
+ val = pci_read_config(bdf, addr, size);
+#endif
+ printf(" %0*lx", pci_field_width(size), val);
+ addr += byte_size;
+ }
+ printf("\n");
+ nbytes -= linebytes;
+ if (ctrlc()) {
+ rc = 1;
+ break;
+ }
+ } while (nbytes > 0);
+
+ return (rc);
+}
+
+#ifndef CONFIG_DM_PCI
+static int pci_cfg_write (pci_dev_t bdf, ulong addr, ulong size, ulong value)
+{
+ if (size == 4) {
+ pci_write_config_dword(bdf, addr, value);
+ }
+ else if (size == 2) {
+ ushort val = value & 0xffff;
+ pci_write_config_word(bdf, addr, val);
+ }
+ else {
+ u_char val = value & 0xff;
+ pci_write_config_byte(bdf, addr, val);
+ }
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_DM_PCI
+static int pci_cfg_modify(struct udevice *dev, ulong addr, ulong size,
+ ulong value, int incrflag)
+#else
+static int pci_cfg_modify(pci_dev_t bdf, ulong addr, ulong size, ulong value,
+ int incrflag)
+#endif
+{
+ ulong i;
+ int nbytes;
+ ulong val;
+
+ /* Print the address, followed by value. Then accept input for
+ * the next value. A non-converted value exits.
+ */
+ do {
+ printf("%08lx:", addr);
+#ifdef CONFIG_DM_PCI
+ dm_pci_read_config(dev, addr, &val, size);
+#else
+ val = pci_read_config(bdf, addr, size);
+#endif
+ printf(" %0*lx", pci_field_width(size), val);
+
+ nbytes = cli_readline(" ? ");
+ if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
+ /* <CR> pressed as only input, don't modify current
+ * location and move to next. "-" pressed will go back.
+ */
+ if (incrflag)
+ addr += nbytes ? -size : size;
+ nbytes = 1;
+ /* good enough to not time out */
+ bootretry_reset_cmd_timeout();
+ }
+#ifdef CONFIG_BOOT_RETRY_TIME
+ else if (nbytes == -2) {
+ break; /* timed out, exit the command */
+ }
+#endif
+ else {
+ char *endp;
+ i = simple_strtoul(console_buffer, &endp, 16);
+ nbytes = endp - console_buffer;
+ if (nbytes) {
+ /* good enough to not time out
+ */
+ bootretry_reset_cmd_timeout();
+#ifdef CONFIG_DM_PCI
+ dm_pci_write_config(dev, addr, i, size);
+#else
+ pci_cfg_write(bdf, addr, size, i);
+#endif
+ if (incrflag)
+ addr += size;
+ }
+ }
+ } while (nbytes);
+
+ return 0;
+}
+
+#ifdef CONFIG_DM_PCI
+static const struct pci_flag_info {
+ uint flag;
+ const char *name;
+} pci_flag_info[] = {
+ { PCI_REGION_IO, "io" },
+ { PCI_REGION_PREFETCH, "prefetch" },
+ { PCI_REGION_SYS_MEMORY, "sysmem" },
+ { PCI_REGION_RO, "readonly" },
+ { PCI_REGION_IO, "io" },
+};
+
+static void pci_show_regions(struct udevice *bus)
+{
+ struct pci_controller *hose = dev_get_uclass_priv(bus);
+ const struct pci_region *reg;
+ int i, j;
+
+ if (!hose) {
+ printf("Bus '%s' is not a PCI controller\n", bus->name);
+ return;
+ }
+
+ printf("# %-18s %-18s %-18s %s\n", "Bus start", "Phys start", "Size",
+ "Flags");
+ for (i = 0, reg = hose->regions; i < hose->region_count; i++, reg++) {
+ printf("%d %#018llx %#018llx %#018llx ", i,
+ (unsigned long long)reg->bus_start,
+ (unsigned long long)reg->phys_start,
+ (unsigned long long)reg->size);
+ if (!(reg->flags & PCI_REGION_TYPE))
+ printf("mem ");
+ for (j = 0; j < ARRAY_SIZE(pci_flag_info); j++) {
+ if (reg->flags & pci_flag_info[j].flag)
+ printf("%s ", pci_flag_info[j].name);
+ }
+ printf("\n");
+ }
+}
+#endif
+
+/* PCI Configuration Space access commands
+ *
+ * Syntax:
+ * pci display[.b, .w, .l] bus.device.function} [addr] [len]
+ * pci next[.b, .w, .l] bus.device.function [addr]
+ * pci modify[.b, .w, .l] bus.device.function [addr]
+ * pci write[.b, .w, .l] bus.device.function addr value
+ */
+static int do_pci(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong addr = 0, value = 0, cmd_size = 0;
+ enum pci_size_t size = PCI_SIZE_32;
+#ifdef CONFIG_DM_PCI
+ struct udevice *dev, *bus;
+#else
+ pci_dev_t dev;
+#endif
+ int busnum = 0;
+ pci_dev_t bdf = 0;
+ char cmd = 's';
+ int ret = 0;
+
+ if (argc > 1)
+ cmd = argv[1][0];
+
+ switch (cmd) {
+ case 'd': /* display */
+ case 'n': /* next */
+ case 'm': /* modify */
+ case 'w': /* write */
+ /* Check for a size specification. */
+ cmd_size = cmd_get_data_size(argv[1], 4);
+ size = (cmd_size == 4) ? PCI_SIZE_32 : cmd_size - 1;
+ if (argc > 3)
+ addr = simple_strtoul(argv[3], NULL, 16);
+ if (argc > 4)
+ value = simple_strtoul(argv[4], NULL, 16);
+ case 'h': /* header */
+#ifdef CONFIG_DM_PCI
+ case 'b': /* bars */
+#endif
+ if (argc < 3)
+ goto usage;
+ if ((bdf = get_pci_dev(argv[2])) == -1)
+ return 1;
+ break;
+#if defined(CONFIG_DM_PCI)
+ case 'e':
+ pci_init();
+ return 0;
+#endif
+ case 'r': /* no break */
+ default: /* scan bus */
+ value = 1; /* short listing */
+ if (argc > 1) {
+ if (cmd != 'r' && argv[argc-1][0] == 'l') {
+ value = 0;
+ argc--;
+ }
+ if (argc > 1)
+ busnum = simple_strtoul(argv[1], NULL, 16);
+ }
+#ifdef CONFIG_DM_PCI
+ ret = uclass_get_device_by_seq(UCLASS_PCI, busnum, &bus);
+ if (ret) {
+ printf("No such bus\n");
+ return CMD_RET_FAILURE;
+ }
+ if (cmd == 'r')
+ pci_show_regions(bus);
+ else
+ pciinfo(bus, value);
+#else
+ pciinfo(busnum, value);
+#endif
+ return 0;
+ }
+
+#ifdef CONFIG_DM_PCI
+ ret = dm_pci_bus_find_bdf(bdf, &dev);
+ if (ret) {
+ printf("No such device\n");
+ return CMD_RET_FAILURE;
+ }
+#else
+ dev = bdf;
+#endif
+
+ switch (argv[1][0]) {
+ case 'h': /* header */
+ pci_header_show(dev);
+ break;
+ case 'd': /* display */
+ return pci_cfg_display(dev, addr, size, value);
+ case 'n': /* next */
+ if (argc < 4)
+ goto usage;
+ ret = pci_cfg_modify(dev, addr, size, value, 0);
+ break;
+ case 'm': /* modify */
+ if (argc < 4)
+ goto usage;
+ ret = pci_cfg_modify(dev, addr, size, value, 1);
+ break;
+ case 'w': /* write */
+ if (argc < 5)
+ goto usage;
+#ifdef CONFIG_DM_PCI
+ ret = dm_pci_write_config(dev, addr, value, size);
+#else
+ ret = pci_cfg_write(dev, addr, size, value);
+#endif
+ break;
+#ifdef CONFIG_DM_PCI
+
+ case 'b': /* bars */
+ return pci_bar_show(dev);
+#endif
+ default:
+ ret = CMD_RET_USAGE;
+ break;
+ }
+
+ return ret;
+ usage:
+ return CMD_RET_USAGE;
+}
+
+/***************************************************/
+
+#ifdef CONFIG_SYS_LONGHELP
+static char pci_help_text[] =
+ "[bus] [long]\n"
+ " - short or long list of PCI devices on bus 'bus'\n"
+#if defined(CONFIG_DM_PCI)
+ "pci enum\n"
+ " - Enumerate PCI buses\n"
+#endif
+ "pci header b.d.f\n"
+ " - show header of PCI device 'bus.device.function'\n"
+#ifdef CONFIG_DM_PCI
+ "pci bar b.d.f\n"
+ " - show BARs base and size for device b.d.f'\n"
+ "pci regions\n"
+ " - show PCI regions\n"
+#endif
+ "pci display[.b, .w, .l] b.d.f [address] [# of objects]\n"
+ " - display PCI configuration space (CFG)\n"
+ "pci next[.b, .w, .l] b.d.f address\n"
+ " - modify, read and keep CFG address\n"
+ "pci modify[.b, .w, .l] b.d.f address\n"
+ " - modify, auto increment CFG address\n"
+ "pci write[.b, .w, .l] b.d.f address value\n"
+ " - write to CFG address";
+#endif
+
+U_BOOT_CMD(
+ pci, 5, 1, do_pci,
+ "list and access PCI Configuration Space", pci_help_text
+);
diff --git a/roms/u-boot/cmd/pinmux.c b/roms/u-boot/cmd/pinmux.c
new file mode 100644
index 000000000..9942b1541
--- /dev/null
+++ b/roms/u-boot/cmd/pinmux.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/pinctrl.h>
+#include <dm/uclass-internal.h>
+
+#define LIMIT_DEVNAME 30
+
+static struct udevice *currdev;
+
+static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *name;
+ int ret;
+
+ switch (argc) {
+ case 2:
+ name = argv[1];
+ ret = uclass_get_device_by_name(UCLASS_PINCTRL, name, &currdev);
+ if (ret) {
+ printf("Can't get the pin-controller: %s!\n", name);
+ return CMD_RET_FAILURE;
+ }
+ /* fall through */
+ case 1:
+ if (!currdev) {
+ printf("Pin-controller device is not set!\n");
+ return CMD_RET_USAGE;
+ }
+
+ printf("dev: %s\n", currdev->name);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int show_pinmux(struct udevice *dev)
+{
+ char pin_name[PINNAME_SIZE];
+ char pin_mux[PINMUX_SIZE];
+ int pins_count;
+ int i;
+ int ret;
+
+ pins_count = pinctrl_get_pins_count(dev);
+
+ if (pins_count == -ENOSYS) {
+ printf("Ops get_pins_count not supported\n");
+ return pins_count;
+ }
+
+ for (i = 0; i < pins_count; i++) {
+ ret = pinctrl_get_pin_name(dev, i, pin_name, PINNAME_SIZE);
+ if (ret == -ENOSYS) {
+ printf("Ops get_pin_name not supported\n");
+ return ret;
+ }
+
+ ret = pinctrl_get_pin_muxing(dev, i, pin_mux, PINMUX_SIZE);
+ if (ret) {
+ printf("Ops get_pin_muxing error (%d)\n", ret);
+ return ret;
+ }
+
+ printf("%-*s: %-*s\n", PINNAME_SIZE, pin_name,
+ PINMUX_SIZE, pin_mux);
+ }
+
+ return 0;
+}
+
+static int do_status(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int ret = CMD_RET_USAGE;
+
+ if (currdev && (argc < 2 || strcmp(argv[1], "-a")))
+ return show_pinmux(currdev);
+
+ if (argc < 2 || strcmp(argv[1], "-a"))
+ return ret;
+
+ uclass_foreach_dev_probe(UCLASS_PINCTRL, dev) {
+ /* insert a separator between each pin-controller display */
+ printf("--------------------------\n");
+ printf("%s:\n", dev->name);
+ ret = show_pinmux(dev);
+ if (ret < 0)
+ printf("Can't display pin muxing for %s\n",
+ dev->name);
+ }
+
+ return ret;
+}
+
+static int do_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+
+ printf("| %-*.*s| %-*.*s| %s\n",
+ LIMIT_DEVNAME, LIMIT_DEVNAME, "Device",
+ LIMIT_DEVNAME, LIMIT_DEVNAME, "Driver",
+ "Parent");
+
+ uclass_foreach_dev_probe(UCLASS_PINCTRL, dev) {
+ printf("| %-*.*s| %-*.*s| %s\n",
+ LIMIT_DEVNAME, LIMIT_DEVNAME, dev->name,
+ LIMIT_DEVNAME, LIMIT_DEVNAME, dev->driver->name,
+ dev->parent->name);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl pinmux_subcmd[] = {
+ U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""),
+ U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""),
+ U_BOOT_CMD_MKENT(status, 2, 1, do_status, "", ""),
+};
+
+static int do_pinmux(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cmd;
+
+ argc--;
+ argv++;
+
+ cmd = find_cmd_tbl(argv[0], pinmux_subcmd, ARRAY_SIZE(pinmux_subcmd));
+ if (!cmd || argc > cmd->maxargs)
+ return CMD_RET_USAGE;
+
+ return cmd->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(pinmux, CONFIG_SYS_MAXARGS, 1, do_pinmux,
+ "show pin-controller muxing",
+ "list - list UCLASS_PINCTRL devices\n"
+ "pinmux dev [pincontroller-name] - select pin-controller device\n"
+ "pinmux status [-a] - print pin-controller muxing [for all]\n"
+)
diff --git a/roms/u-boot/cmd/pmc.c b/roms/u-boot/cmd/pmc.c
new file mode 100644
index 000000000..9a3ba2bff
--- /dev/null
+++ b/roms/u-boot/cmd/pmc.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel PMC command
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <power/acpi_pmc.h>
+
+static int get_pmc_dev(struct udevice **devp)
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_ACPI_PMC, &dev);
+ if (ret) {
+ printf("Could not find device (err=%d)\n", ret);
+ return ret;
+ }
+ ret = pmc_init(dev);
+ if (ret) {
+ printf("Could not init device (err=%d)\n", ret);
+ return ret;
+ }
+ *devp = dev;
+
+ return 0;
+}
+
+static int do_pmc_init(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = get_pmc_dev(&dev);
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ return 0;
+}
+
+static int do_pmc_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = get_pmc_dev(&dev);
+ if (ret)
+ return CMD_RET_FAILURE;
+ pmc_dump_info(dev);
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_pmc_sub[] = {
+ U_BOOT_CMD_MKENT(init, 0, 1, do_pmc_init, "", ""),
+ U_BOOT_CMD_MKENT(info, 0, 1, do_pmc_info, "", ""),
+};
+
+static int do_pmc(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const struct cmd_tbl *cp;
+
+ if (argc < 2) /* no subcommand */
+ return cmd_usage(cmdtp);
+
+ cp = find_cmd_tbl(argv[1], &cmd_pmc_sub[0], ARRAY_SIZE(cmd_pmc_sub));
+ if (!cp)
+ return CMD_RET_USAGE;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ pmc, 2, 1, do_pmc, "Power-management controller info",
+ "info - read state and show info about the PMC\n"
+ "pmc init - read state from the PMC\n"
+ );
diff --git a/roms/u-boot/cmd/pmic.c b/roms/u-boot/cmd/pmic.c
new file mode 100644
index 000000000..0cb44d074
--- /dev/null
+++ b/roms/u-boot/cmd/pmic.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014-2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ */
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <power/pmic.h>
+
+#define LIMIT_DEV 32
+#define LIMIT_PARENT 20
+
+static struct udevice *currdev;
+
+static int failure(int ret)
+{
+ printf("Error: %d (%s)\n", ret, errno_str(ret));
+
+ return CMD_RET_FAILURE;
+}
+
+static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *name;
+ int ret = -ENODEV;
+
+ switch (argc) {
+ case 2:
+ name = argv[1];
+ ret = pmic_get(name, &currdev);
+ if (ret) {
+ printf("Can't get PMIC: %s!\n", name);
+ return failure(ret);
+ }
+ case 1:
+ if (!currdev) {
+ printf("PMIC device is not set!\n\n");
+ return CMD_RET_USAGE;
+ }
+
+ printf("dev: %d @ %s\n", dev_seq(currdev), currdev->name);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int ret;
+
+ printf("| %-*.*s| %-*.*s| %s @ %s\n",
+ LIMIT_DEV, LIMIT_DEV, "Name",
+ LIMIT_PARENT, LIMIT_PARENT, "Parent name",
+ "Parent uclass", "seq");
+
+ for (ret = uclass_first_device(UCLASS_PMIC, &dev); dev;
+ ret = uclass_next_device(&dev)) {
+ if (ret)
+ continue;
+
+ printf("| %-*.*s| %-*.*s| %s @ %d\n",
+ LIMIT_DEV, LIMIT_DEV, dev->name,
+ LIMIT_PARENT, LIMIT_PARENT, dev->parent->name,
+ dev_get_uclass_name(dev->parent), dev_seq(dev->parent));
+ }
+
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_dump(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct uc_pmic_priv *priv;
+ struct udevice *dev;
+ char fmt[16];
+ uint reg;
+ int ret;
+
+ if (!currdev) {
+ printf("First, set the PMIC device!\n");
+ return CMD_RET_USAGE;
+ }
+
+ dev = currdev;
+ priv = dev_get_uclass_priv(dev);
+ printf("Dump pmic: %s registers\n", dev->name);
+
+ sprintf(fmt, "%%%d.%dx ", priv->trans_len * 2,
+ priv->trans_len * 2);
+
+ for (reg = 0; reg < pmic_reg_count(dev); reg++) {
+ ret = pmic_reg_read(dev, reg);
+ if (ret < 0 && ret != -ENODATA) {
+ printf("Can't read register: %d\n", reg);
+ return failure(ret);
+ }
+
+ if (!(reg % 16))
+ printf("\n0x%02x: ", reg);
+
+ if (ret == -ENODATA) {
+ int i;
+
+ for (i = 0; i < priv->trans_len; i++)
+ puts("--");
+ puts(" ");
+ } else {
+ printf(fmt, ret);
+ }
+ }
+ printf("\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_read(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct uc_pmic_priv *priv;
+ struct udevice *dev;
+ int regs, ret;
+ char fmt[24];
+ uint reg;
+
+ if (!currdev) {
+ printf("First, set the PMIC device!\n");
+ return CMD_RET_USAGE;
+ }
+
+ dev = currdev;
+ priv = dev_get_uclass_priv(dev);
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ reg = simple_strtoul(argv[1], NULL, 0);
+ regs = pmic_reg_count(dev);
+ if (reg > regs) {
+ printf("PMIC max reg: %d\n", regs);
+ return failure(-EFAULT);
+ }
+
+ ret = pmic_reg_read(dev, reg);
+ if (ret < 0) {
+ printf("Can't read PMIC register: %d!\n", reg);
+ return failure(ret);
+ }
+
+ sprintf(fmt, "0x%%02x: 0x%%%d.%dx\n", priv->trans_len * 2,
+ priv->trans_len * 2);
+ printf(fmt, reg, ret);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_write(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ uint reg, value;
+ int regs, ret;
+
+ if (!currdev) {
+ printf("First, set the PMIC device!\n");
+ return CMD_RET_USAGE;
+ }
+
+ dev = currdev;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ reg = simple_strtoul(argv[1], NULL, 0);
+ regs = pmic_reg_count(dev);
+ if (reg > regs) {
+ printf("PMIC max reg: %d\n", regs);
+ return failure(-EFAULT);
+ }
+
+ value = simple_strtoul(argv[2], NULL, 0);
+
+ ret = pmic_reg_write(dev, reg, value);
+ if (ret) {
+ printf("Can't write PMIC register: %d!\n", reg);
+ return failure(ret);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl subcmd[] = {
+ U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""),
+ U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""),
+ U_BOOT_CMD_MKENT(dump, 1, 1, do_dump, "", ""),
+ U_BOOT_CMD_MKENT(read, 2, 1, do_read, "", ""),
+ U_BOOT_CMD_MKENT(write, 3, 1, do_write, "", ""),
+};
+
+static int do_pmic(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cmd;
+
+ argc--;
+ argv++;
+
+ cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd));
+ if (cmd == NULL || argc > cmd->maxargs)
+ return CMD_RET_USAGE;
+
+ return cmd->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(pmic, CONFIG_SYS_MAXARGS, 1, do_pmic,
+ "PMIC sub-system",
+ "list - list pmic devices\n"
+ "pmic dev [name] - show or [set] operating PMIC device\n"
+ "pmic dump - dump registers\n"
+ "pmic read address - read byte of register at address\n"
+ "pmic write address - write byte to register at address\n"
+);
diff --git a/roms/u-boot/cmd/pstore.c b/roms/u-boot/cmd/pstore.c
new file mode 100644
index 000000000..5656bae6d
--- /dev/null
+++ b/roms/u-boot/cmd/pstore.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright © 2019 Collabora Ltd
+ */
+
+#include <config.h>
+#include <command.h>
+#include <fdtdec.h>
+#include <fs.h>
+#include <log.h>
+#include <mapmem.h>
+#include <memalign.h>
+#include <part.h>
+
+struct persistent_ram_buffer {
+ u32 sig;
+ u32 start;
+ u32 size;
+ u8 data[0];
+};
+
+#define PERSISTENT_RAM_SIG (0x43474244) /* DBGC */
+#define RAMOOPS_KERNMSG_HDR "===="
+
+#define PSTORE_TYPE_DMESG 0
+#define PSTORE_TYPE_CONSOLE 2
+#define PSTORE_TYPE_FTRACE 3
+#define PSTORE_TYPE_PMSG 7
+#define PSTORE_TYPE_ALL 255
+
+static phys_addr_t pstore_addr = CONFIG_CMD_PSTORE_MEM_ADDR;
+static phys_size_t pstore_length = CONFIG_CMD_PSTORE_MEM_SIZE;
+static unsigned int pstore_record_size = CONFIG_CMD_PSTORE_RECORD_SIZE;
+static unsigned int pstore_console_size = CONFIG_CMD_PSTORE_CONSOLE_SIZE;
+static unsigned int pstore_ftrace_size = CONFIG_CMD_PSTORE_FTRACE_SIZE;
+static unsigned int pstore_pmsg_size = CONFIG_CMD_PSTORE_PMSG_SIZE;
+static unsigned int pstore_ecc_size = CONFIG_CMD_PSTORE_ECC_SIZE;
+static unsigned int buffer_size;
+
+ /**
+ * pstore_read_kmsg_hdr() - Check kernel header and get compression flag if
+ * available.
+ * @buffer: Kernel messages buffer.
+ * @compressed: Returns TRUE if kernel buffer is compressed, else FALSE.
+ *
+ * Check if buffer starts with a kernel header of the form:
+ * ====<secs>.<nsecs>[-<compression>]\n
+ * If <compression> is equal to 'C' then the buffer is compressed, else iter
+ * should be 'D'.
+ *
+ * Return: Length of kernel header.
+ */
+static int pstore_read_kmsg_hdr(char *buffer, bool *compressed)
+{
+ char *ptr = buffer;
+ *compressed = false;
+
+ if (strncmp(RAMOOPS_KERNMSG_HDR, ptr, strlen(RAMOOPS_KERNMSG_HDR)) != 0)
+ return 0;
+
+ ptr += strlen(RAMOOPS_KERNMSG_HDR);
+
+ ptr = strchr(ptr, '\n');
+ if (!ptr)
+ return 0;
+
+ if (ptr[-2] == '-' && ptr[-1] == 'C')
+ *compressed = true;
+
+ return ptr - buffer + 1;
+}
+
+/**
+ * pstore_get_buffer() - Get unwrapped record buffer
+ * @sig: Signature to check
+ * @buffer: Buffer containing wrapped record
+ * @size: wrapped record size
+ * @dest: Buffer used to store unwrapped record
+ *
+ * The record starts with <signature><start><size> header.
+ * The signature is 'DBGC' for all records except for Ftrace's record(s) wich
+ * use LINUX_VERSION_CODE ^ 'DBGC'.
+ * Use 0 for @sig to prevent checking signature.
+ * Start and size are 4 bytes long.
+ *
+ * Return: record's length
+ */
+static u32 pstore_get_buffer(u32 sig, phys_addr_t buffer, u32 size, char *dest)
+{
+ struct persistent_ram_buffer *prb =
+ (struct persistent_ram_buffer *)map_sysmem(buffer, size);
+ u32 dest_size;
+
+ if (sig == 0 || prb->sig == sig) {
+ if (prb->size == 0) {
+ log_debug("found existing empty buffer\n");
+ return 0;
+ }
+
+ if (prb->size > size) {
+ log_debug("found existing invalid buffer, size %u, start %u\n",
+ prb->size, prb->start);
+ return 0;
+ }
+ } else {
+ log_debug("no valid data in buffer (sig = 0x%08x)\n", prb->sig);
+ return 0;
+ }
+
+ log_debug("found existing buffer, size %u, start %u\n",
+ prb->size, prb->start);
+
+ memcpy(dest, &prb->data[prb->start], prb->size - prb->start);
+ memcpy(dest + prb->size - prb->start, &prb->data[0], prb->start);
+
+ dest_size = prb->size;
+ unmap_sysmem(prb);
+
+ return dest_size;
+}
+
+/**
+ * pstore_init_buffer_size() - Init buffer size to largest record size
+ *
+ * Records, console, FTrace and user logs can use different buffer sizes.
+ * This function allows to retrieve the biggest one.
+ */
+static void pstore_init_buffer_size(void)
+{
+ if (pstore_record_size > buffer_size)
+ buffer_size = pstore_record_size;
+
+ if (pstore_console_size > buffer_size)
+ buffer_size = pstore_console_size;
+
+ if (pstore_ftrace_size > buffer_size)
+ buffer_size = pstore_ftrace_size;
+
+ if (pstore_pmsg_size > buffer_size)
+ buffer_size = pstore_pmsg_size;
+}
+
+/**
+ * pstore_set() - Initialize PStore settings from command line arguments
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * Set pstore reserved memory info, starting at 'addr' for 'len' bytes.
+ * Default length for records is 4K.
+ * Mandatory arguments:
+ * - addr: ramoops starting address
+ * - len: ramoops total length
+ * Optional arguments:
+ * - record-size: size of one panic or oops record ('dump' type)
+ * - console-size: size of the kernel logs record
+ * - ftrace-size: size of the ftrace record(s), this can be a single record or
+ * divided in parts based on number of CPUs
+ * - pmsg-size: size of the user space logs record
+ * - ecc-size: enables/disables ECC support and specifies ECC buffer size in
+ * bytes (0 disables it, 1 is a special value, means 16 bytes ECC)
+ *
+ * Return: zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int pstore_set(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ /* Address is specified since argc > 2
+ */
+ pstore_addr = simple_strtoul(argv[1], NULL, 16);
+
+ /* Length is specified since argc > 2
+ */
+ pstore_length = simple_strtoul(argv[2], NULL, 16);
+
+ if (argc > 3)
+ pstore_record_size = simple_strtoul(argv[3], NULL, 16);
+
+ if (argc > 4)
+ pstore_console_size = simple_strtoul(argv[4], NULL, 16);
+
+ if (argc > 5)
+ pstore_ftrace_size = simple_strtoul(argv[5], NULL, 16);
+
+ if (argc > 6)
+ pstore_pmsg_size = simple_strtoul(argv[6], NULL, 16);
+
+ if (argc > 7)
+ pstore_ecc_size = simple_strtoul(argv[7], NULL, 16);
+
+ if (pstore_length < (pstore_record_size + pstore_console_size
+ + pstore_ftrace_size + pstore_pmsg_size)) {
+ printf("pstore <len> should be larger than the sum of all records sizes\n");
+ pstore_length = 0;
+ }
+
+ log_debug("pstore set done: start 0x%08llx - length 0x%llx\n",
+ (unsigned long long)pstore_addr,
+ (unsigned long long)pstore_length);
+
+ return 0;
+}
+
+/**
+ * pstore_print_buffer() - Print buffer
+ * @type: buffer type
+ * @buffer: buffer to print
+ * @size: buffer size
+ *
+ * Print buffer type and content
+ */
+static void pstore_print_buffer(char *type, char *buffer, u32 size)
+{
+ u32 i = 0;
+
+ printf("**** %s\n", type);
+ while (i < size && buffer[i] != 0) {
+ putc(buffer[i]);
+ i++;
+ }
+}
+
+/**
+ * pstore_display() - Display existing records in pstore reserved memory
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * A 'record-type' can be given to only display records of this kind.
+ * If no 'record-type' is given, all valid records are dispayed.
+ * 'record-type' can be one of 'dump', 'console', 'ftrace' or 'user'. For 'dump'
+ * and 'ftrace' types, a 'nb' can be given to only display one record.
+ *
+ * Return: zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int pstore_display(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ int type = PSTORE_TYPE_ALL;
+ phys_addr_t ptr;
+ char *buffer;
+ u32 size;
+ int header_len = 0;
+ bool compressed;
+
+ if (argc > 1) {
+ if (!strcmp(argv[1], "dump"))
+ type = PSTORE_TYPE_DMESG;
+ else if (!strcmp(argv[1], "console"))
+ type = PSTORE_TYPE_CONSOLE;
+ else if (!strcmp(argv[1], "ftrace"))
+ type = PSTORE_TYPE_FTRACE;
+ else if (!strcmp(argv[1], "user"))
+ type = PSTORE_TYPE_PMSG;
+ else
+ return CMD_RET_USAGE;
+ }
+
+ if (pstore_length == 0) {
+ printf("Please set PStore configuration\n");
+ return CMD_RET_USAGE;
+ }
+
+ if (buffer_size == 0)
+ pstore_init_buffer_size();
+
+ buffer = malloc_cache_aligned(buffer_size);
+
+ if (type == PSTORE_TYPE_DMESG || type == PSTORE_TYPE_ALL) {
+ ptr = pstore_addr;
+ phys_addr_t ptr_end = ptr + pstore_length - pstore_pmsg_size
+ - pstore_ftrace_size - pstore_console_size;
+
+ if (argc > 2) {
+ ptr += simple_strtoul(argv[2], NULL, 10)
+ * pstore_record_size;
+ ptr_end = ptr + pstore_record_size;
+ }
+
+ while (ptr < ptr_end) {
+ size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr,
+ pstore_record_size, buffer);
+ ptr += pstore_record_size;
+
+ if (size == 0)
+ continue;
+
+ header_len = pstore_read_kmsg_hdr(buffer, &compressed);
+ if (header_len == 0) {
+ log_debug("no valid kernel header\n");
+ continue;
+ }
+
+ if (compressed) {
+ printf("Compressed buffer, display not available\n");
+ continue;
+ }
+
+ pstore_print_buffer("Dump", buffer + header_len,
+ size - header_len);
+ }
+ }
+
+ if (type == PSTORE_TYPE_CONSOLE || type == PSTORE_TYPE_ALL) {
+ ptr = pstore_addr + pstore_length - pstore_pmsg_size
+ - pstore_ftrace_size - pstore_console_size;
+ size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr,
+ pstore_console_size, buffer);
+ if (size != 0)
+ pstore_print_buffer("Console", buffer, size);
+ }
+
+ if (type == PSTORE_TYPE_FTRACE || type == PSTORE_TYPE_ALL) {
+ ptr = pstore_addr + pstore_length - pstore_pmsg_size
+ - pstore_ftrace_size;
+ /* The FTrace record(s) uses LINUX_VERSION_CODE ^ 'DBGC'
+ * signature, pass 0 to pstore_get_buffer to prevent
+ * checking it
+ */
+ size = pstore_get_buffer(0, ptr, pstore_ftrace_size, buffer);
+ if (size != 0)
+ pstore_print_buffer("FTrace", buffer, size);
+ }
+
+ if (type == PSTORE_TYPE_PMSG || type == PSTORE_TYPE_ALL) {
+ ptr = pstore_addr + pstore_length - pstore_pmsg_size;
+ size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr,
+ pstore_pmsg_size, buffer);
+ if (size != 0)
+ pstore_print_buffer("User", buffer, size);
+ }
+
+ free(buffer);
+
+ return 0;
+}
+
+/**
+ * pstore_save() - Save existing records from pstore reserved memory
+ * @cmdtp: Command data struct pointer
+ * @flag: Command flag
+ * @argc: Command-line argument count
+ * @argv: Array of command-line arguments
+ *
+ * the records are saved under 'directory path', which should already exist,
+ * to partition 'part' on device type 'interface' instance 'dev'
+ * Filenames are automatically generated, depending on record type, like in
+ * /sys/fs/pstore under Linux
+ *
+ * Return: zero on success, CMD_RET_USAGE in case of misuse and negative
+ * on error.
+ */
+static int pstore_save(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ phys_addr_t ptr, ptr_end;
+ char *buffer;
+ char *save_argv[6];
+ char addr[19], length[19];
+ char path[256];
+ u32 size;
+ unsigned int index;
+ int header_len = 0;
+ bool compressed;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ if (pstore_length == 0) {
+ printf("Please set PStore configuration\n");
+ return CMD_RET_USAGE;
+ }
+
+ if (buffer_size == 0)
+ pstore_init_buffer_size();
+
+ buffer = malloc_cache_aligned(buffer_size);
+ sprintf(addr, "0x%p", buffer);
+
+ save_argv[0] = argv[0];
+ save_argv[1] = argv[1];
+ save_argv[2] = argv[2];
+ save_argv[3] = addr;
+ save_argv[4] = path;
+ save_argv[5] = length;
+
+ /* Save all Dump records */
+ ptr = pstore_addr;
+ ptr_end = ptr + pstore_length - pstore_pmsg_size - pstore_ftrace_size
+ - pstore_console_size;
+ index = 0;
+ while (ptr < ptr_end) {
+ size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr,
+ pstore_record_size, buffer);
+ ptr += pstore_record_size;
+
+ if (size == 0)
+ continue;
+
+ header_len = pstore_read_kmsg_hdr(buffer, &compressed);
+ if (header_len == 0) {
+ log_debug("no valid kernel header\n");
+ continue;
+ }
+
+ sprintf(addr, "0x%08lx", (ulong)map_to_sysmem(buffer + header_len));
+ sprintf(length, "0x%X", size - header_len);
+ sprintf(path, "%s/dmesg-ramoops-%u%s", argv[3], index,
+ compressed ? ".enc.z" : "");
+ do_save(cmdtp, flag, 6, save_argv, FS_TYPE_ANY);
+ index++;
+ }
+
+ sprintf(addr, "0x%08lx", (ulong)map_to_sysmem(buffer));
+
+ /* Save Console record */
+ size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr, pstore_console_size,
+ buffer);
+ if (size != 0) {
+ sprintf(length, "0x%X", size);
+ sprintf(path, "%s/console-ramoops-0", argv[3]);
+ do_save(cmdtp, flag, 6, save_argv, FS_TYPE_ANY);
+ }
+ ptr += pstore_console_size;
+
+ /* Save FTrace record(s)
+ * The FTrace record(s) uses LINUX_VERSION_CODE ^ 'DBGC' signature,
+ * pass 0 to pstore_get_buffer to prevent checking it
+ */
+ size = pstore_get_buffer(0, ptr, pstore_ftrace_size, buffer);
+ if (size != 0) {
+ sprintf(length, "0x%X", size);
+ sprintf(path, "%s/ftrace-ramoops-0", argv[3]);
+ do_save(cmdtp, flag, 6, save_argv, FS_TYPE_ANY);
+ }
+ ptr += pstore_ftrace_size;
+
+ /* Save Console record */
+ size = pstore_get_buffer(PERSISTENT_RAM_SIG, ptr, pstore_pmsg_size,
+ buffer);
+ if (size != 0) {
+ sprintf(length, "0x%X", size);
+ sprintf(path, "%s/pmsg-ramoops-0", argv[3]);
+ do_save(cmdtp, flag, 6, save_argv, FS_TYPE_ANY);
+ }
+
+ free(buffer);
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_pstore_sub[] = {
+ U_BOOT_CMD_MKENT(set, 8, 0, pstore_set, "", ""),
+ U_BOOT_CMD_MKENT(display, 3, 0, pstore_display, "", ""),
+ U_BOOT_CMD_MKENT(save, 4, 0, pstore_save, "", ""),
+};
+
+static int do_pstore(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+ struct cmd_tbl *c;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* Strip off leading argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], cmd_pstore_sub, ARRAY_SIZE(cmd_pstore_sub));
+
+ if (!c)
+ return CMD_RET_USAGE;
+
+ return c->cmd(cmdtp, flag, argc, argv);
+}
+
+void fdt_fixup_pstore(void *blob)
+{
+ char node[32];
+ int nodeoffset; /* node offset from libfdt */
+
+ nodeoffset = fdt_path_offset(blob, "/");
+ if (nodeoffset < 0) {
+ /* Not found or something else bad happened. */
+ log_err("fdt_path_offset() returned %s\n", fdt_strerror(nodeoffset));
+ return;
+ }
+
+ nodeoffset = fdt_add_subnode(blob, nodeoffset, "reserved-memory");
+ if (nodeoffset < 0) {
+ log_err("Add 'reserved-memory' node failed: %s\n",
+ fdt_strerror(nodeoffset));
+ return;
+ }
+ fdt_setprop_u32(blob, nodeoffset, "#address-cells", 2);
+ fdt_setprop_u32(blob, nodeoffset, "#size-cells", 2);
+ fdt_setprop_empty(blob, nodeoffset, "ranges");
+
+ sprintf(node, "ramoops@%llx", (unsigned long long)pstore_addr);
+ nodeoffset = fdt_add_subnode(blob, nodeoffset, node);
+ if (nodeoffset < 0) {
+ log_err("Add '%s' node failed: %s\n", node, fdt_strerror(nodeoffset));
+ return;
+ }
+ fdt_setprop_string(blob, nodeoffset, "compatible", "ramoops");
+ fdt_setprop_u64(blob, nodeoffset, "reg", pstore_addr);
+ fdt_appendprop_u64(blob, nodeoffset, "reg", pstore_length);
+ fdt_setprop_u32(blob, nodeoffset, "record-size", pstore_record_size);
+ fdt_setprop_u32(blob, nodeoffset, "console-size", pstore_console_size);
+ fdt_setprop_u32(blob, nodeoffset, "ftrace-size", pstore_ftrace_size);
+ fdt_setprop_u32(blob, nodeoffset, "pmsg-size", pstore_pmsg_size);
+ fdt_setprop_u32(blob, nodeoffset, "ecc-size", pstore_ecc_size);
+}
+
+U_BOOT_CMD(pstore, 10, 0, do_pstore,
+ "Manage Linux Persistent Storage",
+ "set <addr> <len> [record-size] [console-size] [ftrace-size] [pmsg_size] [ecc-size]\n"
+ "- Set pstore reserved memory info, starting at 'addr' for 'len' bytes.\n"
+ " Default length for records is 4K.\n"
+ " 'record-size' is the size of one panic or oops record ('dump' type).\n"
+ " 'console-size' is the size of the kernel logs record.\n"
+ " 'ftrace-size' is the size of the ftrace record(s), this can be a single\n"
+ " record or divided in parts based on number of CPUs.\n"
+ " 'pmsg-size' is the size of the user space logs record.\n"
+ " 'ecc-size' enables/disables ECC support and specifies ECC buffer size in\n"
+ " bytes (0 disables it, 1 is a special value, means 16 bytes ECC).\n"
+ "pstore display [record-type] [nb]\n"
+ "- Display existing records in pstore reserved memory. A 'record-type' can\n"
+ " be given to only display records of this kind. 'record-type' can be one\n"
+ " of 'dump', 'console', 'ftrace' or 'user'. For 'dump' and 'ftrace' types,\n"
+ " a 'nb' can be given to only display one record.\n"
+ "pstore save <interface> <dev[:part]> <directory-path>\n"
+ "- Save existing records in pstore reserved memory under 'directory path'\n"
+ " to partition 'part' on device type 'interface' instance 'dev'.\n"
+ " Filenames are automatically generated, depending on record type, like\n"
+ " in /sys/fs/pstore under Linux.\n"
+ " The 'directory-path' should already exist.\n"
+);
diff --git a/roms/u-boot/cmd/pvblock.c b/roms/u-boot/cmd/pvblock.c
new file mode 100644
index 000000000..4e99b0612
--- /dev/null
+++ b/roms/u-boot/cmd/pvblock.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020 EPAM Systems Inc.
+ *
+ * XEN para-virtualized block device support
+ */
+
+#include <blk.h>
+#include <common.h>
+#include <command.h>
+
+/* Current I/O Device */
+static int pvblock_curr_device;
+
+int do_pvblock(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ return blk_common_cmd(argc, argv, IF_TYPE_PVBLOCK,
+ &pvblock_curr_device);
+}
+
+U_BOOT_CMD(pvblock, 5, 1, do_pvblock,
+ "Xen para-virtualized block device",
+ "info - show available block devices\n"
+ "pvblock device [dev] - show or set current device\n"
+ "pvblock part [dev] - print partition table of one or all devices\n"
+ "pvblock read addr blk# cnt\n"
+ "pvblock write addr blk# cnt - read/write `cnt'"
+ " blocks starting at block `blk#'\n"
+ " to/from memory address `addr'");
+
diff --git a/roms/u-boot/cmd/pwm.c b/roms/u-boot/cmd/pwm.c
new file mode 100644
index 000000000..e1f97c759
--- /dev/null
+++ b/roms/u-boot/cmd/pwm.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Control PWM channels
+ *
+ * Copyright (c) 2020 SiFive, Inc
+ * author: Pragnesh Patel <pragnesh.patel@sifive.com>
+ */
+
+#include <command.h>
+#include <dm.h>
+#include <pwm.h>
+
+enum pwm_cmd {
+ PWM_SET_INVERT,
+ PWM_SET_CONFIG,
+ PWM_SET_ENABLE,
+ PWM_SET_DISABLE,
+};
+
+static int do_pwm(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *str_cmd, *str_channel = NULL, *str_enable = NULL;
+ const char *str_pwm = NULL, *str_period = NULL, *str_duty = NULL;
+ enum pwm_cmd sub_cmd;
+ struct udevice *dev;
+ u32 channel, pwm_enable, pwm_dev, period_ns = 0, duty_ns = 0;
+ int ret;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ str_cmd = argv[1];
+ argc -= 2;
+ argv += 2;
+
+ str_pwm = *argv;
+ argc--;
+ argv++;
+
+ if (!str_pwm)
+ return CMD_RET_USAGE;
+
+ switch (*str_cmd) {
+ case 'i':
+ sub_cmd = PWM_SET_INVERT;
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ break;
+ case 'c':
+ sub_cmd = PWM_SET_CONFIG;
+ if (argc != 3)
+ return CMD_RET_USAGE;
+ break;
+ case 'e':
+ sub_cmd = PWM_SET_ENABLE;
+ if (argc != 1)
+ return CMD_RET_USAGE;
+ break;
+ case 'd':
+ sub_cmd = PWM_SET_DISABLE;
+ if (argc != 1)
+ return CMD_RET_USAGE;
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ pwm_dev = simple_strtoul(str_pwm, NULL, 10);
+ ret = uclass_get_device(UCLASS_PWM, pwm_dev, &dev);
+ if (ret) {
+ printf("pwm: '%s' not found\n", str_pwm);
+ return cmd_process_error(cmdtp, ret);
+ }
+
+ str_channel = *argv;
+ channel = simple_strtoul(str_channel, NULL, 10);
+ argc--;
+ argv++;
+
+ if (sub_cmd == PWM_SET_INVERT) {
+ str_enable = *argv;
+ pwm_enable = simple_strtoul(str_enable, NULL, 10);
+ ret = pwm_set_invert(dev, channel, pwm_enable);
+ } else if (sub_cmd == PWM_SET_CONFIG) {
+ str_period = *argv;
+ argc--;
+ argv++;
+ period_ns = simple_strtoul(str_period, NULL, 10);
+
+ str_duty = *argv;
+ duty_ns = simple_strtoul(str_duty, NULL, 10);
+
+ ret = pwm_set_config(dev, channel, period_ns, duty_ns);
+ } else if (sub_cmd == PWM_SET_ENABLE) {
+ ret = pwm_set_enable(dev, channel, 1);
+ } else if (sub_cmd == PWM_SET_DISABLE) {
+ ret = pwm_set_enable(dev, channel, 0);
+ }
+
+ if (ret) {
+ printf("error(%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(pwm, 6, 0, do_pwm,
+ "control pwm channels",
+ "pwm <invert> <pwm_dev_num> <channel> <polarity>\n"
+ "pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns>\n"
+ "pwm <enable/disable> <pwm_dev_num> <channel>\n"
+ "Note: All input values are in decimal");
diff --git a/roms/u-boot/cmd/pxe.c b/roms/u-boot/cmd/pxe.c
new file mode 100644
index 000000000..46ac08fa3
--- /dev/null
+++ b/roms/u-boot/cmd/pxe.c
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <net.h>
+
+#include "pxe_utils.h"
+
+#ifdef CONFIG_CMD_NET
+const char *pxe_default_paths[] = {
+#ifdef CONFIG_SYS_SOC
+#ifdef CONFIG_SYS_BOARD
+ "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC "-" CONFIG_SYS_BOARD,
+#endif
+ "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC,
+#endif
+ "default-" CONFIG_SYS_ARCH,
+ "default",
+ NULL
+};
+
+static int do_get_tftp(struct cmd_tbl *cmdtp, const char *file_path,
+ char *file_addr)
+{
+ char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
+
+ tftp_argv[1] = file_addr;
+ tftp_argv[2] = (void *)file_path;
+
+ if (do_tftpb(cmdtp, 0, 3, tftp_argv))
+ return -ENOENT;
+
+ return 1;
+}
+
+/*
+ * Looks for a pxe file with a name based on the pxeuuid environment variable.
+ *
+ * Returns 1 on success or < 0 on error.
+ */
+static int pxe_uuid_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
+{
+ char *uuid_str;
+
+ uuid_str = from_env("pxeuuid");
+
+ if (!uuid_str)
+ return -ENOENT;
+
+ return get_pxelinux_path(cmdtp, uuid_str, pxefile_addr_r);
+}
+
+/*
+ * Looks for a pxe file with a name based on the 'ethaddr' environment
+ * variable.
+ *
+ * Returns 1 on success or < 0 on error.
+ */
+static int pxe_mac_path(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
+{
+ char mac_str[21];
+ int err;
+
+ err = format_mac_pxe(mac_str, sizeof(mac_str));
+
+ if (err < 0)
+ return err;
+
+ return get_pxelinux_path(cmdtp, mac_str, pxefile_addr_r);
+}
+
+/*
+ * Looks for pxe files with names based on our IP address. See pxelinux
+ * documentation for details on what these file names look like. We match
+ * that exactly.
+ *
+ * Returns 1 on success or < 0 on error.
+ */
+static int pxe_ipaddr_paths(struct cmd_tbl *cmdtp, unsigned long pxefile_addr_r)
+{
+ char ip_addr[9];
+ int mask_pos, err;
+
+ sprintf(ip_addr, "%08X", ntohl(net_ip.s_addr));
+
+ for (mask_pos = 7; mask_pos >= 0; mask_pos--) {
+ err = get_pxelinux_path(cmdtp, ip_addr, pxefile_addr_r);
+
+ if (err > 0)
+ return err;
+
+ ip_addr[mask_pos] = '\0';
+ }
+
+ return -ENOENT;
+}
+/*
+ * Entry point for the 'pxe get' command.
+ * This Follows pxelinux's rules to download a config file from a tftp server.
+ * The file is stored at the location given by the pxefile_addr_r environment
+ * variable, which must be set.
+ *
+ * UUID comes from pxeuuid env variable, if defined
+ * MAC addr comes from ethaddr env variable, if defined
+ * IP
+ *
+ * see http://syslinux.zytor.com/wiki/index.php/PXELINUX
+ *
+ * Returns 0 on success or 1 on error.
+ */
+static int
+do_pxe_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *pxefile_addr_str;
+ unsigned long pxefile_addr_r;
+ int err, i = 0;
+
+ do_getfile = do_get_tftp;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ pxefile_addr_str = from_env("pxefile_addr_r");
+
+ if (!pxefile_addr_str)
+ return 1;
+
+ err = strict_strtoul(pxefile_addr_str, 16,
+ (unsigned long *)&pxefile_addr_r);
+ if (err < 0)
+ return 1;
+
+ /*
+ * Keep trying paths until we successfully get a file we're looking
+ * for.
+ */
+ if (pxe_uuid_path(cmdtp, pxefile_addr_r) > 0 ||
+ pxe_mac_path(cmdtp, pxefile_addr_r) > 0 ||
+ pxe_ipaddr_paths(cmdtp, pxefile_addr_r) > 0) {
+ printf("Config file found\n");
+
+ return 0;
+ }
+
+ while (pxe_default_paths[i]) {
+ if (get_pxelinux_path(cmdtp, pxe_default_paths[i],
+ pxefile_addr_r) > 0) {
+ printf("Config file found\n");
+ return 0;
+ }
+ i++;
+ }
+
+ printf("Config file not found\n");
+
+ return 1;
+}
+
+/*
+ * Boots a system using a pxe file
+ *
+ * Returns 0 on success, 1 on error.
+ */
+static int
+do_pxe_boot(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned long pxefile_addr_r;
+ struct pxe_menu *cfg;
+ char *pxefile_addr_str;
+
+ do_getfile = do_get_tftp;
+
+ if (argc == 1) {
+ pxefile_addr_str = from_env("pxefile_addr_r");
+ if (!pxefile_addr_str)
+ return 1;
+
+ } else if (argc == 2) {
+ pxefile_addr_str = argv[1];
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ if (strict_strtoul(pxefile_addr_str, 16, &pxefile_addr_r) < 0) {
+ printf("Invalid pxefile address: %s\n", pxefile_addr_str);
+ return 1;
+ }
+
+ cfg = parse_pxefile(cmdtp, pxefile_addr_r);
+
+ if (!cfg) {
+ printf("Error parsing config file\n");
+ return 1;
+ }
+
+ handle_pxe_menu(cmdtp, cfg);
+
+ destroy_pxe_menu(cfg);
+
+ copy_filename(net_boot_file_name, "", sizeof(net_boot_file_name));
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_pxe_sub[] = {
+ U_BOOT_CMD_MKENT(get, 1, 1, do_pxe_get, "", ""),
+ U_BOOT_CMD_MKENT(boot, 2, 1, do_pxe_boot, "", "")
+};
+
+static void __maybe_unused pxe_reloc(void)
+{
+ static int relocated_pxe;
+
+ if (!relocated_pxe) {
+ fixup_cmdtable(cmd_pxe_sub, ARRAY_SIZE(cmd_pxe_sub));
+ relocated_pxe = 1;
+ }
+}
+
+static int do_pxe(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+ pxe_reloc();
+#endif
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ is_pxe = true;
+
+ /* drop initial "pxe" arg */
+ argc--;
+ argv++;
+
+ cp = find_cmd_tbl(argv[0], cmd_pxe_sub, ARRAY_SIZE(cmd_pxe_sub));
+
+ if (cp)
+ return cp->cmd(cmdtp, flag, argc, argv);
+
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(pxe, 3, 1, do_pxe,
+ "commands to get and boot from pxe files",
+ "get - try to retrieve a pxe file using tftp\n"
+ "pxe boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n"
+);
+#endif
diff --git a/roms/u-boot/cmd/pxe_utils.c b/roms/u-boot/cmd/pxe_utils.c
new file mode 100644
index 000000000..9a30629e2
--- /dev/null
+++ b/roms/u-boot/cmd/pxe_utils.c
@@ -0,0 +1,1479 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2010-2011 Calxeda, Inc.
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <lcd.h>
+#include <net.h>
+#include <fdt_support.h>
+#include <linux/libfdt.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <errno.h>
+#include <linux/list.h>
+
+#include <splash.h>
+#include <asm/io.h>
+
+#include "menu.h"
+#include "cli.h"
+
+#include "pxe_utils.h"
+
+#define MAX_TFTP_PATH_LEN 512
+
+bool is_pxe;
+
+/*
+ * Convert an ethaddr from the environment to the format used by pxelinux
+ * filenames based on mac addresses. Convert's ':' to '-', and adds "01-" to
+ * the beginning of the ethernet address to indicate a hardware type of
+ * Ethernet. Also converts uppercase hex characters into lowercase, to match
+ * pxelinux's behavior.
+ *
+ * Returns 1 for success, -ENOENT if 'ethaddr' is undefined in the
+ * environment, or some other value < 0 on error.
+ */
+int format_mac_pxe(char *outbuf, size_t outbuf_len)
+{
+ uchar ethaddr[6];
+
+ if (outbuf_len < 21) {
+ printf("outbuf is too small (%zd < 21)\n", outbuf_len);
+
+ return -EINVAL;
+ }
+
+ if (!eth_env_get_enetaddr_by_index("eth", eth_get_dev_index(), ethaddr))
+ return -ENOENT;
+
+ sprintf(outbuf, "01-%02x-%02x-%02x-%02x-%02x-%02x",
+ ethaddr[0], ethaddr[1], ethaddr[2],
+ ethaddr[3], ethaddr[4], ethaddr[5]);
+
+ return 1;
+}
+
+/*
+ * Returns the directory the file specified in the bootfile env variable is
+ * in. If bootfile isn't defined in the environment, return NULL, which should
+ * be interpreted as "don't prepend anything to paths".
+ */
+static int get_bootfile_path(const char *file_path, char *bootfile_path,
+ size_t bootfile_path_size)
+{
+ char *bootfile, *last_slash;
+ size_t path_len = 0;
+
+ /* Only syslinux allows absolute paths */
+ if (file_path[0] == '/' && !is_pxe)
+ goto ret;
+
+ bootfile = from_env("bootfile");
+
+ if (!bootfile)
+ goto ret;
+
+ last_slash = strrchr(bootfile, '/');
+
+ if (!last_slash)
+ goto ret;
+
+ path_len = (last_slash - bootfile) + 1;
+
+ if (bootfile_path_size < path_len) {
+ printf("bootfile_path too small. (%zd < %zd)\n",
+ bootfile_path_size, path_len);
+
+ return -1;
+ }
+
+ strncpy(bootfile_path, bootfile, path_len);
+
+ ret:
+ bootfile_path[path_len] = '\0';
+
+ return 1;
+}
+
+int (*do_getfile)(struct cmd_tbl *cmdtp, const char *file_path,
+ char *file_addr);
+
+/*
+ * As in pxelinux, paths to files referenced from files we retrieve are
+ * relative to the location of bootfile. get_relfile takes such a path and
+ * joins it with the bootfile path to get the full path to the target file. If
+ * the bootfile path is NULL, we use file_path as is.
+ *
+ * Returns 1 for success, or < 0 on error.
+ */
+static int get_relfile(struct cmd_tbl *cmdtp, const char *file_path,
+ unsigned long file_addr)
+{
+ size_t path_len;
+ char relfile[MAX_TFTP_PATH_LEN + 1];
+ char addr_buf[18];
+ int err;
+
+ err = get_bootfile_path(file_path, relfile, sizeof(relfile));
+
+ if (err < 0)
+ return err;
+
+ path_len = strlen(file_path);
+ path_len += strlen(relfile);
+
+ if (path_len > MAX_TFTP_PATH_LEN) {
+ printf("Base path too long (%s%s)\n", relfile, file_path);
+
+ return -ENAMETOOLONG;
+ }
+
+ strcat(relfile, file_path);
+
+ printf("Retrieving file: %s\n", relfile);
+
+ sprintf(addr_buf, "%lx", file_addr);
+
+ return do_getfile(cmdtp, relfile, addr_buf);
+}
+
+/*
+ * Retrieve the file at 'file_path' to the locate given by 'file_addr'. If
+ * 'bootfile' was specified in the environment, the path to bootfile will be
+ * prepended to 'file_path' and the resulting path will be used.
+ *
+ * Returns 1 on success, or < 0 for error.
+ */
+int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
+ unsigned long file_addr)
+{
+ unsigned long config_file_size;
+ char *tftp_filesize;
+ int err;
+ char *buf;
+
+ err = get_relfile(cmdtp, file_path, file_addr);
+
+ if (err < 0)
+ return err;
+
+ /*
+ * the file comes without a NUL byte at the end, so find out its size
+ * and add the NUL byte.
+ */
+ tftp_filesize = from_env("filesize");
+
+ if (!tftp_filesize)
+ return -ENOENT;
+
+ if (strict_strtoul(tftp_filesize, 16, &config_file_size) < 0)
+ return -EINVAL;
+
+ buf = map_sysmem(file_addr + config_file_size, 1);
+ *buf = '\0';
+ unmap_sysmem(buf);
+
+ return 1;
+}
+
+#define PXELINUX_DIR "pxelinux.cfg/"
+
+/*
+ * Retrieves a file in the 'pxelinux.cfg' folder. Since this uses get_pxe_file
+ * to do the hard work, the location of the 'pxelinux.cfg' folder is generated
+ * from the bootfile path, as described above.
+ *
+ * Returns 1 on success or < 0 on error.
+ */
+int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
+ unsigned long pxefile_addr_r)
+{
+ size_t base_len = strlen(PXELINUX_DIR);
+ char path[MAX_TFTP_PATH_LEN + 1];
+
+ if (base_len + strlen(file) > MAX_TFTP_PATH_LEN) {
+ printf("path (%s%s) too long, skipping\n",
+ PXELINUX_DIR, file);
+ return -ENAMETOOLONG;
+ }
+
+ sprintf(path, PXELINUX_DIR "%s", file);
+
+ return get_pxe_file(cmdtp, path, pxefile_addr_r);
+}
+
+/*
+ * Wrapper to make it easier to store the file at file_path in the location
+ * specified by envaddr_name. file_path will be joined to the bootfile path,
+ * if any is specified.
+ *
+ * Returns 1 on success or < 0 on error.
+ */
+static int get_relfile_envaddr(struct cmd_tbl *cmdtp, const char *file_path,
+ const char *envaddr_name)
+{
+ unsigned long file_addr;
+ char *envaddr;
+
+ envaddr = from_env(envaddr_name);
+
+ if (!envaddr)
+ return -ENOENT;
+
+ if (strict_strtoul(envaddr, 16, &file_addr) < 0)
+ return -EINVAL;
+
+ return get_relfile(cmdtp, file_path, file_addr);
+}
+
+/*
+ * Allocates memory for and initializes a pxe_label. This uses malloc, so the
+ * result must be free()'d to reclaim the memory.
+ *
+ * Returns NULL if malloc fails.
+ */
+static struct pxe_label *label_create(void)
+{
+ struct pxe_label *label;
+
+ label = malloc(sizeof(struct pxe_label));
+
+ if (!label)
+ return NULL;
+
+ memset(label, 0, sizeof(struct pxe_label));
+
+ return label;
+}
+
+/*
+ * Free the memory used by a pxe_label, including that used by its name,
+ * kernel, append and initrd members, if they're non NULL.
+ *
+ * So - be sure to only use dynamically allocated memory for the members of
+ * the pxe_label struct, unless you want to clean it up first. These are
+ * currently only created by the pxe file parsing code.
+ */
+static void label_destroy(struct pxe_label *label)
+{
+ if (label->name)
+ free(label->name);
+
+ if (label->kernel)
+ free(label->kernel);
+
+ if (label->config)
+ free(label->config);
+
+ if (label->append)
+ free(label->append);
+
+ if (label->initrd)
+ free(label->initrd);
+
+ if (label->fdt)
+ free(label->fdt);
+
+ if (label->fdtdir)
+ free(label->fdtdir);
+
+ if (label->fdtoverlays)
+ free(label->fdtoverlays);
+
+ free(label);
+}
+
+/*
+ * Print a label and its string members if they're defined.
+ *
+ * This is passed as a callback to the menu code for displaying each
+ * menu entry.
+ */
+static void label_print(void *data)
+{
+ struct pxe_label *label = data;
+ const char *c = label->menu ? label->menu : label->name;
+
+ printf("%s:\t%s\n", label->num, c);
+}
+
+/*
+ * Boot a label that specified 'localboot'. This requires that the 'localcmd'
+ * environment variable is defined. Its contents will be executed as U-Boot
+ * command. If the label specified an 'append' line, its contents will be
+ * used to overwrite the contents of the 'bootargs' environment variable prior
+ * to running 'localcmd'.
+ *
+ * Returns 1 on success or < 0 on error.
+ */
+static int label_localboot(struct pxe_label *label)
+{
+ char *localcmd;
+
+ localcmd = from_env("localcmd");
+
+ if (!localcmd)
+ return -ENOENT;
+
+ if (label->append) {
+ char bootargs[CONFIG_SYS_CBSIZE];
+
+ cli_simple_process_macros(label->append, bootargs,
+ sizeof(bootargs));
+ env_set("bootargs", bootargs);
+ }
+
+ debug("running: %s\n", localcmd);
+
+ return run_command_list(localcmd, strlen(localcmd), 0);
+}
+
+/*
+ * Loads fdt overlays specified in 'fdtoverlays'.
+ */
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+static void label_boot_fdtoverlay(struct cmd_tbl *cmdtp, struct pxe_label *label)
+{
+ char *fdtoverlay = label->fdtoverlays;
+ struct fdt_header *working_fdt;
+ char *fdtoverlay_addr_env;
+ ulong fdtoverlay_addr;
+ ulong fdt_addr;
+ int err;
+
+ /* Get the main fdt and map it */
+ fdt_addr = simple_strtoul(env_get("fdt_addr_r"), NULL, 16);
+ working_fdt = map_sysmem(fdt_addr, 0);
+ err = fdt_check_header(working_fdt);
+ if (err)
+ return;
+
+ /* Get the specific overlay loading address */
+ fdtoverlay_addr_env = env_get("fdtoverlay_addr_r");
+ if (!fdtoverlay_addr_env) {
+ printf("Invalid fdtoverlay_addr_r for loading overlays\n");
+ return;
+ }
+
+ fdtoverlay_addr = simple_strtoul(fdtoverlay_addr_env, NULL, 16);
+
+ /* Cycle over the overlay files and apply them in order */
+ do {
+ struct fdt_header *blob;
+ char *overlayfile;
+ char *end;
+ int len;
+
+ /* Drop leading spaces */
+ while (*fdtoverlay == ' ')
+ ++fdtoverlay;
+
+ /* Copy a single filename if multiple provided */
+ end = strstr(fdtoverlay, " ");
+ if (end) {
+ len = (int)(end - fdtoverlay);
+ overlayfile = malloc(len + 1);
+ strncpy(overlayfile, fdtoverlay, len);
+ overlayfile[len] = '\0';
+ } else
+ overlayfile = fdtoverlay;
+
+ if (!strlen(overlayfile))
+ goto skip_overlay;
+
+ /* Load overlay file */
+ err = get_relfile_envaddr(cmdtp, overlayfile,
+ "fdtoverlay_addr_r");
+ if (err < 0) {
+ printf("Failed loading overlay %s\n", overlayfile);
+ goto skip_overlay;
+ }
+
+ /* Resize main fdt */
+ fdt_shrink_to_minimum(working_fdt, 8192);
+
+ blob = map_sysmem(fdtoverlay_addr, 0);
+ err = fdt_check_header(blob);
+ if (err) {
+ printf("Invalid overlay %s, skipping\n",
+ overlayfile);
+ goto skip_overlay;
+ }
+
+ err = fdt_overlay_apply_verbose(working_fdt, blob);
+ if (err) {
+ printf("Failed to apply overlay %s, skipping\n",
+ overlayfile);
+ goto skip_overlay;
+ }
+
+skip_overlay:
+ if (end)
+ free(overlayfile);
+ } while ((fdtoverlay = strstr(fdtoverlay, " ")));
+}
+#endif
+
+/*
+ * Boot according to the contents of a pxe_label.
+ *
+ * If we can't boot for any reason, we return. A successful boot never
+ * returns.
+ *
+ * The kernel will be stored in the location given by the 'kernel_addr_r'
+ * environment variable.
+ *
+ * If the label specifies an initrd file, it will be stored in the location
+ * given by the 'ramdisk_addr_r' environment variable.
+ *
+ * If the label specifies an 'append' line, its contents will overwrite that
+ * of the 'bootargs' environment variable.
+ */
+static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
+{
+ char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL };
+ char initrd_str[28];
+ char mac_str[29] = "";
+ char ip_str[68] = "";
+ char *fit_addr = NULL;
+ int bootm_argc = 2;
+ int len = 0;
+ ulong kernel_addr;
+ void *buf;
+
+ label_print(label);
+
+ label->attempted = 1;
+
+ if (label->localboot) {
+ if (label->localboot_val >= 0)
+ label_localboot(label);
+ return 0;
+ }
+
+ if (!label->kernel) {
+ printf("No kernel given, skipping %s\n",
+ label->name);
+ return 1;
+ }
+
+ if (label->initrd) {
+ if (get_relfile_envaddr(cmdtp, label->initrd, "ramdisk_addr_r") < 0) {
+ printf("Skipping %s for failure retrieving initrd\n",
+ label->name);
+ return 1;
+ }
+
+ bootm_argv[2] = initrd_str;
+ strncpy(bootm_argv[2], env_get("ramdisk_addr_r"), 18);
+ strcat(bootm_argv[2], ":");
+ strncat(bootm_argv[2], env_get("filesize"), 9);
+ bootm_argc = 3;
+ }
+
+ if (get_relfile_envaddr(cmdtp, label->kernel, "kernel_addr_r") < 0) {
+ printf("Skipping %s for failure retrieving kernel\n",
+ label->name);
+ return 1;
+ }
+
+ if (label->ipappend & 0x1) {
+ sprintf(ip_str, " ip=%s:%s:%s:%s",
+ env_get("ipaddr"), env_get("serverip"),
+ env_get("gatewayip"), env_get("netmask"));
+ }
+
+ if (IS_ENABLED(CONFIG_CMD_NET)) {
+ if (label->ipappend & 0x2) {
+ int err;
+
+ strcpy(mac_str, " BOOTIF=");
+ err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8);
+ if (err < 0)
+ mac_str[0] = '\0';
+ }
+ }
+
+ if ((label->ipappend & 0x3) || label->append) {
+ char bootargs[CONFIG_SYS_CBSIZE] = "";
+ char finalbootargs[CONFIG_SYS_CBSIZE];
+
+ if (strlen(label->append ?: "") +
+ strlen(ip_str) + strlen(mac_str) + 1 > sizeof(bootargs)) {
+ printf("bootarg overflow %zd+%zd+%zd+1 > %zd\n",
+ strlen(label->append ?: ""),
+ strlen(ip_str), strlen(mac_str),
+ sizeof(bootargs));
+ return 1;
+ }
+
+ if (label->append)
+ strncpy(bootargs, label->append, sizeof(bootargs));
+
+ strcat(bootargs, ip_str);
+ strcat(bootargs, mac_str);
+
+ cli_simple_process_macros(bootargs, finalbootargs,
+ sizeof(finalbootargs));
+ env_set("bootargs", finalbootargs);
+ printf("append: %s\n", finalbootargs);
+ }
+
+ bootm_argv[1] = env_get("kernel_addr_r");
+ /* for FIT, append the configuration identifier */
+ if (label->config) {
+ int len = strlen(bootm_argv[1]) + strlen(label->config) + 1;
+
+ fit_addr = malloc(len);
+ if (!fit_addr) {
+ printf("malloc fail (FIT address)\n");
+ return 1;
+ }
+ snprintf(fit_addr, len, "%s%s", bootm_argv[1], label->config);
+ bootm_argv[1] = fit_addr;
+ }
+
+ /*
+ * fdt usage is optional:
+ * It handles the following scenarios.
+ *
+ * Scenario 1: If fdt_addr_r specified and "fdt" or "fdtdir" label is
+ * defined in pxe file, retrieve fdt blob from server. Pass fdt_addr_r to
+ * bootm, and adjust argc appropriately.
+ *
+ * If retrieve fails and no exact fdt blob is specified in pxe file with
+ * "fdt" label, try Scenario 2.
+ *
+ * Scenario 2: If there is an fdt_addr specified, pass it along to
+ * bootm, and adjust argc appropriately.
+ *
+ * Scenario 3: fdt blob is not available.
+ */
+ bootm_argv[3] = env_get("fdt_addr_r");
+
+ /* if fdt label is defined then get fdt from server */
+ if (bootm_argv[3]) {
+ char *fdtfile = NULL;
+ char *fdtfilefree = NULL;
+
+ if (label->fdt) {
+ fdtfile = label->fdt;
+ } else if (label->fdtdir) {
+ char *f1, *f2, *f3, *f4, *slash;
+
+ f1 = env_get("fdtfile");
+ if (f1) {
+ f2 = "";
+ f3 = "";
+ f4 = "";
+ } else {
+ /*
+ * For complex cases where this code doesn't
+ * generate the correct filename, the board
+ * code should set $fdtfile during early boot,
+ * or the boot scripts should set $fdtfile
+ * before invoking "pxe" or "sysboot".
+ */
+ f1 = env_get("soc");
+ f2 = "-";
+ f3 = env_get("board");
+ f4 = ".dtb";
+ if (!f1) {
+ f1 = "";
+ f2 = "";
+ }
+ if (!f3) {
+ f2 = "";
+ f3 = "";
+ }
+ }
+
+ len = strlen(label->fdtdir);
+ if (!len)
+ slash = "./";
+ else if (label->fdtdir[len - 1] != '/')
+ slash = "/";
+ else
+ slash = "";
+
+ len = strlen(label->fdtdir) + strlen(slash) +
+ strlen(f1) + strlen(f2) + strlen(f3) +
+ strlen(f4) + 1;
+ fdtfilefree = malloc(len);
+ if (!fdtfilefree) {
+ printf("malloc fail (FDT filename)\n");
+ goto cleanup;
+ }
+
+ snprintf(fdtfilefree, len, "%s%s%s%s%s%s",
+ label->fdtdir, slash, f1, f2, f3, f4);
+ fdtfile = fdtfilefree;
+ }
+
+ if (fdtfile) {
+ int err = get_relfile_envaddr(cmdtp, fdtfile,
+ "fdt_addr_r");
+
+ free(fdtfilefree);
+ if (err < 0) {
+ bootm_argv[3] = NULL;
+
+ if (label->fdt) {
+ printf("Skipping %s for failure retrieving FDT\n",
+ label->name);
+ goto cleanup;
+ }
+ }
+
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+ if (label->fdtoverlays)
+ label_boot_fdtoverlay(cmdtp, label);
+#endif
+ } else {
+ bootm_argv[3] = NULL;
+ }
+ }
+
+ if (!bootm_argv[3])
+ bootm_argv[3] = env_get("fdt_addr");
+
+ if (bootm_argv[3]) {
+ if (!bootm_argv[2])
+ bootm_argv[2] = "-";
+ bootm_argc = 4;
+ }
+
+ kernel_addr = genimg_get_kernel_addr(bootm_argv[1]);
+ buf = map_sysmem(kernel_addr, 0);
+ /* Try bootm for legacy and FIT format image */
+ if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID)
+ do_bootm(cmdtp, 0, bootm_argc, bootm_argv);
+ /* Try booting an AArch64 Linux kernel image */
+ else if (IS_ENABLED(CONFIG_CMD_BOOTI))
+ do_booti(cmdtp, 0, bootm_argc, bootm_argv);
+ /* Try booting a Image */
+ else if (IS_ENABLED(CONFIG_CMD_BOOTZ))
+ do_bootz(cmdtp, 0, bootm_argc, bootm_argv);
+ /* Try booting an x86_64 Linux kernel image */
+ else if (IS_ENABLED(CONFIG_CMD_ZBOOT))
+ do_zboot_parent(cmdtp, 0, bootm_argc, bootm_argv, NULL);
+
+ unmap_sysmem(buf);
+
+cleanup:
+ if (fit_addr)
+ free(fit_addr);
+ return 1;
+}
+
+/*
+ * Tokens for the pxe file parser.
+ */
+enum token_type {
+ T_EOL,
+ T_STRING,
+ T_EOF,
+ T_MENU,
+ T_TITLE,
+ T_TIMEOUT,
+ T_LABEL,
+ T_KERNEL,
+ T_LINUX,
+ T_APPEND,
+ T_INITRD,
+ T_LOCALBOOT,
+ T_DEFAULT,
+ T_PROMPT,
+ T_INCLUDE,
+ T_FDT,
+ T_FDTDIR,
+ T_FDTOVERLAYS,
+ T_ONTIMEOUT,
+ T_IPAPPEND,
+ T_BACKGROUND,
+ T_INVALID
+};
+
+/*
+ * A token - given by a value and a type.
+ */
+struct token {
+ char *val;
+ enum token_type type;
+};
+
+/*
+ * Keywords recognized.
+ */
+static const struct token keywords[] = {
+ {"menu", T_MENU},
+ {"title", T_TITLE},
+ {"timeout", T_TIMEOUT},
+ {"default", T_DEFAULT},
+ {"prompt", T_PROMPT},
+ {"label", T_LABEL},
+ {"kernel", T_KERNEL},
+ {"linux", T_LINUX},
+ {"localboot", T_LOCALBOOT},
+ {"append", T_APPEND},
+ {"initrd", T_INITRD},
+ {"include", T_INCLUDE},
+ {"devicetree", T_FDT},
+ {"fdt", T_FDT},
+ {"devicetreedir", T_FDTDIR},
+ {"fdtdir", T_FDTDIR},
+ {"fdtoverlays", T_FDTOVERLAYS},
+ {"ontimeout", T_ONTIMEOUT,},
+ {"ipappend", T_IPAPPEND,},
+ {"background", T_BACKGROUND,},
+ {NULL, T_INVALID}
+};
+
+/*
+ * Since pxe(linux) files don't have a token to identify the start of a
+ * literal, we have to keep track of when we're in a state where a literal is
+ * expected vs when we're in a state a keyword is expected.
+ */
+enum lex_state {
+ L_NORMAL = 0,
+ L_KEYWORD,
+ L_SLITERAL
+};
+
+/*
+ * get_string retrieves a string from *p and stores it as a token in
+ * *t.
+ *
+ * get_string used for scanning both string literals and keywords.
+ *
+ * Characters from *p are copied into t-val until a character equal to
+ * delim is found, or a NUL byte is reached. If delim has the special value of
+ * ' ', any whitespace character will be used as a delimiter.
+ *
+ * If lower is unequal to 0, uppercase characters will be converted to
+ * lowercase in the result. This is useful to make keywords case
+ * insensitive.
+ *
+ * The location of *p is updated to point to the first character after the end
+ * of the token - the ending delimiter.
+ *
+ * On success, the new value of t->val is returned. Memory for t->val is
+ * allocated using malloc and must be free()'d to reclaim it. If insufficient
+ * memory is available, NULL is returned.
+ */
+static char *get_string(char **p, struct token *t, char delim, int lower)
+{
+ char *b, *e;
+ size_t len, i;
+
+ /*
+ * b and e both start at the beginning of the input stream.
+ *
+ * e is incremented until we find the ending delimiter, or a NUL byte
+ * is reached. Then, we take e - b to find the length of the token.
+ */
+ b = *p;
+ e = *p;
+
+ while (*e) {
+ if ((delim == ' ' && isspace(*e)) || delim == *e)
+ break;
+ e++;
+ }
+
+ len = e - b;
+
+ /*
+ * Allocate memory to hold the string, and copy it in, converting
+ * characters to lowercase if lower is != 0.
+ */
+ t->val = malloc(len + 1);
+ if (!t->val)
+ return NULL;
+
+ for (i = 0; i < len; i++, b++) {
+ if (lower)
+ t->val[i] = tolower(*b);
+ else
+ t->val[i] = *b;
+ }
+
+ t->val[len] = '\0';
+
+ /*
+ * Update *p so the caller knows where to continue scanning.
+ */
+ *p = e;
+
+ t->type = T_STRING;
+
+ return t->val;
+}
+
+/*
+ * Populate a keyword token with a type and value.
+ */
+static void get_keyword(struct token *t)
+{
+ int i;
+
+ for (i = 0; keywords[i].val; i++) {
+ if (!strcmp(t->val, keywords[i].val)) {
+ t->type = keywords[i].type;
+ break;
+ }
+ }
+}
+
+/*
+ * Get the next token. We have to keep track of which state we're in to know
+ * if we're looking to get a string literal or a keyword.
+ *
+ * *p is updated to point at the first character after the current token.
+ */
+static void get_token(char **p, struct token *t, enum lex_state state)
+{
+ char *c = *p;
+
+ t->type = T_INVALID;
+
+ /* eat non EOL whitespace */
+ while (isblank(*c))
+ c++;
+
+ /*
+ * eat comments. note that string literals can't begin with #, but
+ * can contain a # after their first character.
+ */
+ if (*c == '#') {
+ while (*c && *c != '\n')
+ c++;
+ }
+
+ if (*c == '\n') {
+ t->type = T_EOL;
+ c++;
+ } else if (*c == '\0') {
+ t->type = T_EOF;
+ c++;
+ } else if (state == L_SLITERAL) {
+ get_string(&c, t, '\n', 0);
+ } else if (state == L_KEYWORD) {
+ /*
+ * when we expect a keyword, we first get the next string
+ * token delimited by whitespace, and then check if it
+ * matches a keyword in our keyword list. if it does, it's
+ * converted to a keyword token of the appropriate type, and
+ * if not, it remains a string token.
+ */
+ get_string(&c, t, ' ', 1);
+ get_keyword(t);
+ }
+
+ *p = c;
+}
+
+/*
+ * Increment *c until we get to the end of the current line, or EOF.
+ */
+static void eol_or_eof(char **c)
+{
+ while (**c && **c != '\n')
+ (*c)++;
+}
+
+/*
+ * All of these parse_* functions share some common behavior.
+ *
+ * They finish with *c pointing after the token they parse, and return 1 on
+ * success, or < 0 on error.
+ */
+
+/*
+ * Parse a string literal and store a pointer it at *dst. String literals
+ * terminate at the end of the line.
+ */
+static int parse_sliteral(char **c, char **dst)
+{
+ struct token t;
+ char *s = *c;
+
+ get_token(c, &t, L_SLITERAL);
+
+ if (t.type != T_STRING) {
+ printf("Expected string literal: %.*s\n", (int)(*c - s), s);
+ return -EINVAL;
+ }
+
+ *dst = t.val;
+
+ return 1;
+}
+
+/*
+ * Parse a base 10 (unsigned) integer and store it at *dst.
+ */
+static int parse_integer(char **c, int *dst)
+{
+ struct token t;
+ char *s = *c;
+
+ get_token(c, &t, L_SLITERAL);
+
+ if (t.type != T_STRING) {
+ printf("Expected string: %.*s\n", (int)(*c - s), s);
+ return -EINVAL;
+ }
+
+ *dst = simple_strtol(t.val, NULL, 10);
+
+ free(t.val);
+
+ return 1;
+}
+
+static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
+ struct pxe_menu *cfg, int nest_level);
+
+/*
+ * Parse an include statement, and retrieve and parse the file it mentions.
+ *
+ * base should point to a location where it's safe to store the file, and
+ * nest_level should indicate how many nested includes have occurred. For this
+ * include, nest_level has already been incremented and doesn't need to be
+ * incremented here.
+ */
+static int handle_include(struct cmd_tbl *cmdtp, char **c, unsigned long base,
+ struct pxe_menu *cfg, int nest_level)
+{
+ char *include_path;
+ char *s = *c;
+ int err;
+ char *buf;
+ int ret;
+
+ err = parse_sliteral(c, &include_path);
+
+ if (err < 0) {
+ printf("Expected include path: %.*s\n", (int)(*c - s), s);
+ return err;
+ }
+
+ err = get_pxe_file(cmdtp, include_path, base);
+
+ if (err < 0) {
+ printf("Couldn't retrieve %s\n", include_path);
+ return err;
+ }
+
+ buf = map_sysmem(base, 0);
+ ret = parse_pxefile_top(cmdtp, buf, base, cfg, nest_level);
+ unmap_sysmem(buf);
+
+ return ret;
+}
+
+/*
+ * Parse lines that begin with 'menu'.
+ *
+ * base and nest are provided to handle the 'menu include' case.
+ *
+ * base should point to a location where it's safe to store the included file.
+ *
+ * nest_level should be 1 when parsing the top level pxe file, 2 when parsing
+ * a file it includes, 3 when parsing a file included by that file, and so on.
+ */
+static int parse_menu(struct cmd_tbl *cmdtp, char **c, struct pxe_menu *cfg,
+ unsigned long base, int nest_level)
+{
+ struct token t;
+ char *s = *c;
+ int err = 0;
+
+ get_token(c, &t, L_KEYWORD);
+
+ switch (t.type) {
+ case T_TITLE:
+ err = parse_sliteral(c, &cfg->title);
+
+ break;
+
+ case T_INCLUDE:
+ err = handle_include(cmdtp, c, base, cfg, nest_level + 1);
+ break;
+
+ case T_BACKGROUND:
+ err = parse_sliteral(c, &cfg->bmp);
+ break;
+
+ default:
+ printf("Ignoring malformed menu command: %.*s\n",
+ (int)(*c - s), s);
+ }
+
+ if (err < 0)
+ return err;
+
+ eol_or_eof(c);
+
+ return 1;
+}
+
+/*
+ * Handles parsing a 'menu line' when we're parsing a label.
+ */
+static int parse_label_menu(char **c, struct pxe_menu *cfg,
+ struct pxe_label *label)
+{
+ struct token t;
+ char *s;
+
+ s = *c;
+
+ get_token(c, &t, L_KEYWORD);
+
+ switch (t.type) {
+ case T_DEFAULT:
+ if (!cfg->default_label)
+ cfg->default_label = strdup(label->name);
+
+ if (!cfg->default_label)
+ return -ENOMEM;
+
+ break;
+ case T_LABEL:
+ parse_sliteral(c, &label->menu);
+ break;
+ default:
+ printf("Ignoring malformed menu command: %.*s\n",
+ (int)(*c - s), s);
+ }
+
+ eol_or_eof(c);
+
+ return 0;
+}
+
+/*
+ * Handles parsing a 'kernel' label.
+ * expecting "filename" or "<fit_filename>#cfg"
+ */
+static int parse_label_kernel(char **c, struct pxe_label *label)
+{
+ char *s;
+ int err;
+
+ err = parse_sliteral(c, &label->kernel);
+ if (err < 0)
+ return err;
+
+ s = strstr(label->kernel, "#");
+ if (!s)
+ return 1;
+
+ label->config = malloc(strlen(s) + 1);
+ if (!label->config)
+ return -ENOMEM;
+
+ strcpy(label->config, s);
+ *s = 0;
+
+ return 1;
+}
+
+/*
+ * Parses a label and adds it to the list of labels for a menu.
+ *
+ * A label ends when we either get to the end of a file, or
+ * get some input we otherwise don't have a handler defined
+ * for.
+ *
+ */
+static int parse_label(char **c, struct pxe_menu *cfg)
+{
+ struct token t;
+ int len;
+ char *s = *c;
+ struct pxe_label *label;
+ int err;
+
+ label = label_create();
+ if (!label)
+ return -ENOMEM;
+
+ err = parse_sliteral(c, &label->name);
+ if (err < 0) {
+ printf("Expected label name: %.*s\n", (int)(*c - s), s);
+ label_destroy(label);
+ return -EINVAL;
+ }
+
+ list_add_tail(&label->list, &cfg->labels);
+
+ while (1) {
+ s = *c;
+ get_token(c, &t, L_KEYWORD);
+
+ err = 0;
+ switch (t.type) {
+ case T_MENU:
+ err = parse_label_menu(c, cfg, label);
+ break;
+
+ case T_KERNEL:
+ case T_LINUX:
+ err = parse_label_kernel(c, label);
+ break;
+
+ case T_APPEND:
+ err = parse_sliteral(c, &label->append);
+ if (label->initrd)
+ break;
+ s = strstr(label->append, "initrd=");
+ if (!s)
+ break;
+ s += 7;
+ len = (int)(strchr(s, ' ') - s);
+ label->initrd = malloc(len + 1);
+ strncpy(label->initrd, s, len);
+ label->initrd[len] = '\0';
+
+ break;
+
+ case T_INITRD:
+ if (!label->initrd)
+ err = parse_sliteral(c, &label->initrd);
+ break;
+
+ case T_FDT:
+ if (!label->fdt)
+ err = parse_sliteral(c, &label->fdt);
+ break;
+
+ case T_FDTDIR:
+ if (!label->fdtdir)
+ err = parse_sliteral(c, &label->fdtdir);
+ break;
+
+ case T_FDTOVERLAYS:
+ if (!label->fdtoverlays)
+ err = parse_sliteral(c, &label->fdtoverlays);
+ break;
+
+ case T_LOCALBOOT:
+ label->localboot = 1;
+ err = parse_integer(c, &label->localboot_val);
+ break;
+
+ case T_IPAPPEND:
+ err = parse_integer(c, &label->ipappend);
+ break;
+
+ case T_EOL:
+ break;
+
+ default:
+ /*
+ * put the token back! we don't want it - it's the end
+ * of a label and whatever token this is, it's
+ * something for the menu level context to handle.
+ */
+ *c = s;
+ return 1;
+ }
+
+ if (err < 0)
+ return err;
+ }
+}
+
+/*
+ * This 16 comes from the limit pxelinux imposes on nested includes.
+ *
+ * There is no reason at all we couldn't do more, but some limit helps prevent
+ * infinite (until crash occurs) recursion if a file tries to include itself.
+ */
+#define MAX_NEST_LEVEL 16
+
+/*
+ * Entry point for parsing a menu file. nest_level indicates how many times
+ * we've nested in includes. It will be 1 for the top level menu file.
+ *
+ * Returns 1 on success, < 0 on error.
+ */
+static int parse_pxefile_top(struct cmd_tbl *cmdtp, char *p, unsigned long base,
+ struct pxe_menu *cfg, int nest_level)
+{
+ struct token t;
+ char *s, *b, *label_name;
+ int err;
+
+ b = p;
+
+ if (nest_level > MAX_NEST_LEVEL) {
+ printf("Maximum nesting (%d) exceeded\n", MAX_NEST_LEVEL);
+ return -EMLINK;
+ }
+
+ while (1) {
+ s = p;
+
+ get_token(&p, &t, L_KEYWORD);
+
+ err = 0;
+ switch (t.type) {
+ case T_MENU:
+ cfg->prompt = 1;
+ err = parse_menu(cmdtp, &p, cfg,
+ base + ALIGN(strlen(b) + 1, 4),
+ nest_level);
+ break;
+
+ case T_TIMEOUT:
+ err = parse_integer(&p, &cfg->timeout);
+ break;
+
+ case T_LABEL:
+ err = parse_label(&p, cfg);
+ break;
+
+ case T_DEFAULT:
+ case T_ONTIMEOUT:
+ err = parse_sliteral(&p, &label_name);
+
+ if (label_name) {
+ if (cfg->default_label)
+ free(cfg->default_label);
+
+ cfg->default_label = label_name;
+ }
+
+ break;
+
+ case T_INCLUDE:
+ err = handle_include(cmdtp, &p,
+ base + ALIGN(strlen(b), 4), cfg,
+ nest_level + 1);
+ break;
+
+ case T_PROMPT:
+ eol_or_eof(&p);
+ break;
+
+ case T_EOL:
+ break;
+
+ case T_EOF:
+ return 1;
+
+ default:
+ printf("Ignoring unknown command: %.*s\n",
+ (int)(p - s), s);
+ eol_or_eof(&p);
+ }
+
+ if (err < 0)
+ return err;
+ }
+}
+
+/*
+ * Free the memory used by a pxe_menu and its labels.
+ */
+void destroy_pxe_menu(struct pxe_menu *cfg)
+{
+ struct list_head *pos, *n;
+ struct pxe_label *label;
+
+ if (cfg->title)
+ free(cfg->title);
+
+ if (cfg->default_label)
+ free(cfg->default_label);
+
+ list_for_each_safe(pos, n, &cfg->labels) {
+ label = list_entry(pos, struct pxe_label, list);
+
+ label_destroy(label);
+ }
+
+ free(cfg);
+}
+
+/*
+ * Entry point for parsing a pxe file. This is only used for the top level
+ * file.
+ *
+ * Returns NULL if there is an error, otherwise, returns a pointer to a
+ * pxe_menu struct populated with the results of parsing the pxe file (and any
+ * files it includes). The resulting pxe_menu struct can be free()'d by using
+ * the destroy_pxe_menu() function.
+ */
+struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, unsigned long menucfg)
+{
+ struct pxe_menu *cfg;
+ char *buf;
+ int r;
+
+ cfg = malloc(sizeof(struct pxe_menu));
+
+ if (!cfg)
+ return NULL;
+
+ memset(cfg, 0, sizeof(struct pxe_menu));
+
+ INIT_LIST_HEAD(&cfg->labels);
+
+ buf = map_sysmem(menucfg, 0);
+ r = parse_pxefile_top(cmdtp, buf, menucfg, cfg, 1);
+ unmap_sysmem(buf);
+
+ if (r < 0) {
+ destroy_pxe_menu(cfg);
+ return NULL;
+ }
+
+ return cfg;
+}
+
+/*
+ * Converts a pxe_menu struct into a menu struct for use with U-Boot's generic
+ * menu code.
+ */
+static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
+{
+ struct pxe_label *label;
+ struct list_head *pos;
+ struct menu *m;
+ int err;
+ int i = 1;
+ char *default_num = NULL;
+
+ /*
+ * Create a menu and add items for all the labels.
+ */
+ m = menu_create(cfg->title, DIV_ROUND_UP(cfg->timeout, 10),
+ cfg->prompt, NULL, label_print, NULL, NULL);
+
+ if (!m)
+ return NULL;
+
+ list_for_each(pos, &cfg->labels) {
+ label = list_entry(pos, struct pxe_label, list);
+
+ sprintf(label->num, "%d", i++);
+ if (menu_item_add(m, label->num, label) != 1) {
+ menu_destroy(m);
+ return NULL;
+ }
+ if (cfg->default_label &&
+ (strcmp(label->name, cfg->default_label) == 0))
+ default_num = label->num;
+ }
+
+ /*
+ * After we've created items for each label in the menu, set the
+ * menu's default label if one was specified.
+ */
+ if (default_num) {
+ err = menu_default_set(m, default_num);
+ if (err != 1) {
+ if (err != -ENOENT) {
+ menu_destroy(m);
+ return NULL;
+ }
+
+ printf("Missing default: %s\n", cfg->default_label);
+ }
+ }
+
+ return m;
+}
+
+/*
+ * Try to boot any labels we have yet to attempt to boot.
+ */
+static void boot_unattempted_labels(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
+{
+ struct list_head *pos;
+ struct pxe_label *label;
+
+ list_for_each(pos, &cfg->labels) {
+ label = list_entry(pos, struct pxe_label, list);
+
+ if (!label->attempted)
+ label_boot(cmdtp, label);
+ }
+}
+
+/*
+ * Boot the system as prescribed by a pxe_menu.
+ *
+ * Use the menu system to either get the user's choice or the default, based
+ * on config or user input. If there is no default or user's choice,
+ * attempted to boot labels in the order they were given in pxe files.
+ * If the default or user's choice fails to boot, attempt to boot other
+ * labels in the order they were given in pxe files.
+ *
+ * If this function returns, there weren't any labels that successfully
+ * booted, or the user interrupted the menu selection via ctrl+c.
+ */
+void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
+{
+ void *choice;
+ struct menu *m;
+ int err;
+
+ if (IS_ENABLED(CONFIG_CMD_BMP)) {
+ /* display BMP if available */
+ if (cfg->bmp) {
+ if (get_relfile(cmdtp, cfg->bmp, image_load_addr)) {
+ if (CONFIG_IS_ENABLED(CMD_CLS))
+ run_command("cls", 0);
+ bmp_display(image_load_addr,
+ BMP_ALIGN_CENTER, BMP_ALIGN_CENTER);
+ } else {
+ printf("Skipping background bmp %s for failure\n",
+ cfg->bmp);
+ }
+ }
+ }
+
+ m = pxe_menu_to_menu(cfg);
+ if (!m)
+ return;
+
+ err = menu_get_choice(m, &choice);
+
+ menu_destroy(m);
+
+ /*
+ * err == 1 means we got a choice back from menu_get_choice.
+ *
+ * err == -ENOENT if the menu was setup to select the default but no
+ * default was set. in that case, we should continue trying to boot
+ * labels that haven't been attempted yet.
+ *
+ * otherwise, the user interrupted or there was some other error and
+ * we give up.
+ */
+
+ if (err == 1) {
+ err = label_boot(cmdtp, choice);
+ if (!err)
+ return;
+ } else if (err != -ENOENT) {
+ return;
+ }
+
+ boot_unattempted_labels(cmdtp, cfg);
+}
diff --git a/roms/u-boot/cmd/pxe_utils.h b/roms/u-boot/cmd/pxe_utils.h
new file mode 100644
index 000000000..bf58e1534
--- /dev/null
+++ b/roms/u-boot/cmd/pxe_utils.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef __PXE_UTILS_H
+#define __PXE_UTILS_H
+
+#include <linux/list.h>
+
+/*
+ * A note on the pxe file parser.
+ *
+ * We're parsing files that use syslinux grammar, which has a few quirks.
+ * String literals must be recognized based on context - there is no
+ * quoting or escaping support. There's also nothing to explicitly indicate
+ * when a label section completes. We deal with that by ending a label
+ * section whenever we see a line that doesn't include.
+ *
+ * As with the syslinux family, this same file format could be reused in the
+ * future for non pxe purposes. The only action it takes during parsing that
+ * would throw this off is handling of include files. It assumes we're using
+ * pxe, and does a tftp download of a file listed as an include file in the
+ * middle of the parsing operation. That could be handled by refactoring it to
+ * take a 'include file getter' function.
+ */
+
+/*
+ * Describes a single label given in a pxe file.
+ *
+ * Create these with the 'label_create' function given below.
+ *
+ * name - the name of the menu as given on the 'menu label' line.
+ * kernel - the path to the kernel file to use for this label.
+ * append - kernel command line to use when booting this label
+ * initrd - path to the initrd to use for this label.
+ * attempted - 0 if we haven't tried to boot this label, 1 if we have.
+ * localboot - 1 if this label specified 'localboot', 0 otherwise.
+ * list - lets these form a list, which a pxe_menu struct will hold.
+ */
+struct pxe_label {
+ char num[4];
+ char *name;
+ char *menu;
+ char *kernel;
+ char *config;
+ char *append;
+ char *initrd;
+ char *fdt;
+ char *fdtdir;
+ char *fdtoverlays;
+ int ipappend;
+ int attempted;
+ int localboot;
+ int localboot_val;
+ struct list_head list;
+};
+
+/*
+ * Describes a pxe menu as given via pxe files.
+ *
+ * title - the name of the menu as given by a 'menu title' line.
+ * default_label - the name of the default label, if any.
+ * bmp - the bmp file name which is displayed in background
+ * timeout - time in tenths of a second to wait for a user key-press before
+ * booting the default label.
+ * prompt - if 0, don't prompt for a choice unless the timeout period is
+ * interrupted. If 1, always prompt for a choice regardless of
+ * timeout.
+ * labels - a list of labels defined for the menu.
+ */
+struct pxe_menu {
+ char *title;
+ char *default_label;
+ char *bmp;
+ int timeout;
+ int prompt;
+ struct list_head labels;
+};
+
+extern bool is_pxe;
+
+extern int (*do_getfile)(struct cmd_tbl *cmdtp, const char *file_path,
+ char *file_addr);
+void destroy_pxe_menu(struct pxe_menu *cfg);
+int get_pxe_file(struct cmd_tbl *cmdtp, const char *file_path,
+ unsigned long file_addr);
+int get_pxelinux_path(struct cmd_tbl *cmdtp, const char *file,
+ unsigned long pxefile_addr_r);
+void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg);
+struct pxe_menu *parse_pxefile(struct cmd_tbl *cmdtp, unsigned long menucfg);
+int format_mac_pxe(char *outbuf, size_t outbuf_len);
+
+#endif /* __PXE_UTILS_H */
diff --git a/roms/u-boot/cmd/qfw.c b/roms/u-boot/cmd/qfw.c
new file mode 100644
index 000000000..e6a9fdb2a
--- /dev/null
+++ b/roms/u-boot/cmd/qfw.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <errno.h>
+#include <qfw.h>
+#include <dm.h>
+
+static struct udevice *qfw_dev;
+
+/*
+ * This function prepares kernel for zboot. It loads kernel data
+ * to 'load_addr', initrd to 'initrd_addr' and kernel command
+ * line using qemu fw_cfg interface.
+ */
+static int qemu_fwcfg_cmd_setup_kernel(void *load_addr, void *initrd_addr)
+{
+ char *data_addr;
+ uint32_t setup_size, kernel_size, cmdline_size, initrd_size;
+
+ qfw_read_entry(qfw_dev, FW_CFG_SETUP_SIZE, 4, &setup_size);
+ qfw_read_entry(qfw_dev, FW_CFG_KERNEL_SIZE, 4, &kernel_size);
+
+ if (setup_size == 0 || kernel_size == 0) {
+ printf("warning: no kernel available\n");
+ return -1;
+ }
+
+ data_addr = load_addr;
+ qfw_read_entry(qfw_dev, FW_CFG_SETUP_DATA,
+ le32_to_cpu(setup_size), data_addr);
+ data_addr += le32_to_cpu(setup_size);
+
+ qfw_read_entry(qfw_dev, FW_CFG_KERNEL_DATA,
+ le32_to_cpu(kernel_size), data_addr);
+ data_addr += le32_to_cpu(kernel_size);
+
+ data_addr = initrd_addr;
+ qfw_read_entry(qfw_dev, FW_CFG_INITRD_SIZE, 4, &initrd_size);
+ if (initrd_size == 0) {
+ printf("warning: no initrd available\n");
+ } else {
+ qfw_read_entry(qfw_dev, FW_CFG_INITRD_DATA,
+ le32_to_cpu(initrd_size), data_addr);
+ data_addr += le32_to_cpu(initrd_size);
+ }
+
+ qfw_read_entry(qfw_dev, FW_CFG_CMDLINE_SIZE, 4, &cmdline_size);
+ if (cmdline_size) {
+ qfw_read_entry(qfw_dev, FW_CFG_CMDLINE_DATA,
+ le32_to_cpu(cmdline_size), data_addr);
+ /*
+ * if kernel cmdline only contains '\0', (e.g. no -append
+ * when invoking qemu), do not update bootargs
+ */
+ if (*data_addr != '\0') {
+ if (env_set("bootargs", data_addr) < 0)
+ printf("warning: unable to change bootargs\n");
+ }
+ }
+
+ printf("loading kernel to address %p size %x", load_addr,
+ le32_to_cpu(kernel_size));
+ if (initrd_size)
+ printf(" initrd %p size %x\n",
+ initrd_addr,
+ le32_to_cpu(initrd_size));
+ else
+ printf("\n");
+
+ return 0;
+}
+
+static int qemu_fwcfg_cmd_list_firmware(void)
+{
+ int ret;
+ struct fw_cfg_file_iter iter;
+ struct fw_file *file;
+
+ /* make sure fw_list is loaded */
+ ret = qfw_read_firmware_list(qfw_dev);
+ if (ret)
+ return ret;
+
+ for (file = qfw_file_iter_init(qfw_dev, &iter);
+ !qfw_file_iter_end(&iter);
+ file = qfw_file_iter_next(&iter)) {
+ printf("%-56s\n", file->cfg.name);
+ }
+
+ return 0;
+}
+
+static int qemu_fwcfg_do_list(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ if (qemu_fwcfg_cmd_list_firmware() < 0)
+ return CMD_RET_FAILURE;
+
+ return 0;
+}
+
+static int qemu_fwcfg_do_cpus(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ printf("%d cpu(s) online\n", qfw_online_cpus(qfw_dev));
+ return 0;
+}
+
+static int qemu_fwcfg_do_load(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ char *env;
+ void *load_addr;
+ void *initrd_addr;
+
+ env = env_get("loadaddr");
+ load_addr = env ?
+ (void *)simple_strtoul(env, NULL, 16) :
+#ifdef CONFIG_LOADADDR
+ (void *)CONFIG_LOADADDR;
+#else
+ NULL;
+#endif
+
+ env = env_get("ramdiskaddr");
+ initrd_addr = env ?
+ (void *)simple_strtoul(env, NULL, 16) :
+#ifdef CONFIG_RAMDISK_ADDR
+ (void *)CONFIG_RAMDISK_ADDR;
+#else
+ NULL;
+#endif
+
+ if (argc == 2) {
+ load_addr = (void *)simple_strtoul(argv[0], NULL, 16);
+ initrd_addr = (void *)simple_strtoul(argv[1], NULL, 16);
+ } else if (argc == 1) {
+ load_addr = (void *)simple_strtoul(argv[0], NULL, 16);
+ }
+
+ if (!load_addr || !initrd_addr) {
+ printf("missing load or initrd address\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return qemu_fwcfg_cmd_setup_kernel(load_addr, initrd_addr);
+}
+
+static struct cmd_tbl fwcfg_commands[] = {
+ U_BOOT_CMD_MKENT(list, 0, 1, qemu_fwcfg_do_list, "", ""),
+ U_BOOT_CMD_MKENT(cpus, 0, 1, qemu_fwcfg_do_cpus, "", ""),
+ U_BOOT_CMD_MKENT(load, 2, 1, qemu_fwcfg_do_load, "", ""),
+};
+
+static int do_qemu_fw(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+ struct cmd_tbl *fwcfg_cmd;
+
+ ret = qfw_get_dev(&qfw_dev);
+ if (ret) {
+ printf("QEMU fw_cfg interface not found\n");
+ return CMD_RET_USAGE;
+ }
+
+ fwcfg_cmd = find_cmd_tbl(argv[1], fwcfg_commands,
+ ARRAY_SIZE(fwcfg_commands));
+ argc -= 2;
+ argv += 2;
+ if (!fwcfg_cmd || argc > fwcfg_cmd->maxargs)
+ return CMD_RET_USAGE;
+
+ ret = fwcfg_cmd->cmd(fwcfg_cmd, flag, argc, argv);
+
+ return cmd_process_error(fwcfg_cmd, ret);
+}
+
+U_BOOT_CMD(
+ qfw, 4, 1, do_qemu_fw,
+ "QEMU firmware interface",
+ "<command>\n"
+ " - list : print firmware(s) currently loaded\n"
+ " - cpus : print online cpu number\n"
+ " - load <kernel addr> <initrd addr> : load kernel and initrd (if any), and setup for zboot\n"
+)
diff --git a/roms/u-boot/cmd/read.c b/roms/u-boot/cmd/read.c
new file mode 100644
index 000000000..34f53f9a2
--- /dev/null
+++ b/roms/u-boot/cmd/read.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <part.h>
+
+int do_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *ep;
+ struct blk_desc *dev_desc = NULL;
+ int dev;
+ int part = 0;
+ struct disk_partition part_info;
+ ulong offset = 0u;
+ ulong limit = 0u;
+ void *addr;
+ uint blk;
+ uint cnt;
+
+ if (argc != 6) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ dev = (int)simple_strtoul(argv[2], &ep, 16);
+ if (*ep) {
+ if (*ep != ':') {
+ printf("Invalid block device %s\n", argv[2]);
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+
+ dev_desc = blk_get_dev(argv[1], dev);
+ if (dev_desc == NULL) {
+ printf("Block device %s %d not supported\n", argv[1], dev);
+ return 1;
+ }
+
+ addr = (void *)simple_strtoul(argv[3], NULL, 16);
+ blk = simple_strtoul(argv[4], NULL, 16);
+ cnt = simple_strtoul(argv[5], NULL, 16);
+
+ if (part != 0) {
+ if (part_get_info(dev_desc, part, &part_info)) {
+ printf("Cannot find partition %d\n", part);
+ return 1;
+ }
+ offset = part_info.start;
+ limit = part_info.size;
+ } else {
+ /* Largest address not available in struct blk_desc. */
+ limit = ~0;
+ }
+
+ if (cnt + blk > limit) {
+ printf("Read out of range\n");
+ return 1;
+ }
+
+ if (blk_dread(dev_desc, offset + blk, cnt, addr) != cnt) {
+ printf("Error reading blocks\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ read, 6, 0, do_read,
+ "Load binary data from a partition",
+ "<interface> <dev[:part]> addr blk# cnt"
+);
diff --git a/roms/u-boot/cmd/reginfo.c b/roms/u-boot/cmd/reginfo.c
new file mode 100644
index 000000000..c8a04b175
--- /dev/null
+++ b/roms/u-boot/cmd/reginfo.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Subodh Nijsure, SkyStream Networks, snijsure@skystream.com
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/ppc.h>
+
+static int do_reginfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ print_reginfo();
+
+ return 0;
+}
+
+ /**************************************************/
+
+U_BOOT_CMD(
+ reginfo, 2, 1, do_reginfo,
+ "print register information",
+ ""
+);
diff --git a/roms/u-boot/cmd/regulator.c b/roms/u-boot/cmd/regulator.c
new file mode 100644
index 000000000..60a70036d
--- /dev/null
+++ b/roms/u-boot/cmd/regulator.c
@@ -0,0 +1,466 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014-2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ */
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <power/regulator.h>
+
+#define LIMIT_DEVNAME 20
+#define LIMIT_OFNAME 32
+#define LIMIT_INFO 18
+
+static struct udevice *currdev;
+
+static int failure(int ret)
+{
+ printf("Error: %d (%s)\n", ret, errno_str(ret));
+
+ return CMD_RET_FAILURE;
+}
+
+static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct dm_regulator_uclass_plat *uc_pdata;
+ const char *name;
+ int ret = -ENXIO;
+
+ switch (argc) {
+ case 2:
+ name = argv[1];
+ ret = regulator_get_by_platname(name, &currdev);
+ if (ret) {
+ printf("Can't get the regulator: %s!\n", name);
+ return failure(ret);
+ }
+ case 1:
+ if (!currdev) {
+ printf("Regulator device is not set!\n\n");
+ return CMD_RET_USAGE;
+ }
+
+ uc_pdata = dev_get_uclass_plat(currdev);
+ if (!uc_pdata) {
+ printf("%s: no regulator platform data!\n", currdev->name);
+ return failure(ret);
+ }
+
+ printf("dev: %s @ %s\n", uc_pdata->name, currdev->name);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int curr_dev_and_plat(struct udevice **devp,
+ struct dm_regulator_uclass_plat **uc_pdata,
+ bool allow_type_fixed)
+{
+ *devp = NULL;
+ *uc_pdata = NULL;
+
+ if (!currdev) {
+ printf("First, set the regulator device!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ *devp = currdev;
+
+ *uc_pdata = dev_get_uclass_plat(*devp);
+ if (!*uc_pdata) {
+ pr_err("Regulator: %s - missing platform data!\n", currdev->name);
+ return CMD_RET_FAILURE;
+ }
+
+ if (!allow_type_fixed && (*uc_pdata)->type == REGULATOR_TYPE_FIXED) {
+ printf("Operation not allowed for fixed regulator!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct dm_regulator_uclass_plat *uc_pdata;
+ struct udevice *dev;
+ int ret;
+
+ printf("| %-*.*s| %-*.*s| %s\n",
+ LIMIT_DEVNAME, LIMIT_DEVNAME, "Device",
+ LIMIT_OFNAME, LIMIT_OFNAME, "regulator-name",
+ "Parent");
+
+ for (ret = uclass_find_first_device(UCLASS_REGULATOR, &dev); dev;
+ ret = uclass_find_next_device(&dev)) {
+ if (ret)
+ continue;
+
+ uc_pdata = dev_get_uclass_plat(dev);
+ printf("| %-*.*s| %-*.*s| %s\n",
+ LIMIT_DEVNAME, LIMIT_DEVNAME, dev->name,
+ LIMIT_OFNAME, LIMIT_OFNAME, uc_pdata->name,
+ dev->parent->name);
+ }
+
+ return ret;
+}
+
+static int constraint(const char *name, int val, const char *val_name)
+{
+ printf("%-*s", LIMIT_INFO, name);
+ if (val < 0) {
+ printf(" %s (err: %d)\n", errno_str(val), val);
+ return val;
+ }
+
+ if (val_name)
+ printf(" %d (%s)\n", val, val_name);
+ else
+ printf(" %d\n", val);
+
+ return 0;
+}
+
+static const char *get_mode_name(struct dm_regulator_mode *mode,
+ int mode_count,
+ int mode_id)
+{
+ while (mode_count--) {
+ if (mode->id == mode_id)
+ return mode->name;
+ mode++;
+ }
+
+ return NULL;
+}
+
+static int do_info(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct dm_regulator_uclass_plat *uc_pdata;
+ struct dm_regulator_mode *modes;
+ const char *parent_uc;
+ int mode_count;
+ int ret;
+ int i;
+
+ ret = curr_dev_and_plat(&dev, &uc_pdata, true);
+ if (ret)
+ return ret;
+
+ parent_uc = dev_get_uclass_name(dev->parent);
+
+ printf("%s\n%-*s %s\n%-*s %s\n%-*s %s\n%-*s %s\n%-*s\n",
+ "Regulator info:",
+ LIMIT_INFO, "* regulator-name:", uc_pdata->name,
+ LIMIT_INFO, "* device name:", dev->name,
+ LIMIT_INFO, "* parent name:", dev->parent->name,
+ LIMIT_INFO, "* parent uclass:", parent_uc,
+ LIMIT_INFO, "* constraints:");
+
+ constraint(" - min uV:", uc_pdata->min_uV, NULL);
+ constraint(" - max uV:", uc_pdata->max_uV, NULL);
+ constraint(" - min uA:", uc_pdata->min_uA, NULL);
+ constraint(" - max uA:", uc_pdata->max_uA, NULL);
+ constraint(" - always on:", uc_pdata->always_on,
+ uc_pdata->always_on ? "true" : "false");
+ constraint(" - boot on:", uc_pdata->boot_on,
+ uc_pdata->boot_on ? "true" : "false");
+
+ mode_count = regulator_mode(dev, &modes);
+ constraint("* op modes:", mode_count, NULL);
+
+ for (i = 0; i < mode_count; i++, modes++)
+ constraint(" - mode id:", modes->id, modes->name);
+
+ return CMD_RET_SUCCESS;
+}
+
+static void do_status_detail(struct udevice *dev,
+ struct dm_regulator_uclass_plat *uc_pdata)
+{
+ int current, value, mode;
+ const char *mode_name;
+ bool enabled;
+
+ printf("Regulator %s status:\n", uc_pdata->name);
+
+ enabled = regulator_get_enable(dev);
+ constraint(" * enable:", enabled, enabled ? "true" : "false");
+
+ value = regulator_get_value(dev);
+ constraint(" * value uV:", value, NULL);
+
+ current = regulator_get_current(dev);
+ constraint(" * current uA:", current, NULL);
+
+ mode = regulator_get_mode(dev);
+ mode_name = get_mode_name(uc_pdata->mode, uc_pdata->mode_count, mode);
+ constraint(" * mode id:", mode, mode_name);
+}
+
+static void do_status_line(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *pdata;
+ int current, value, mode;
+ const char *mode_name;
+ bool enabled;
+
+ pdata = dev_get_uclass_plat(dev);
+ enabled = regulator_get_enable(dev);
+ value = regulator_get_value(dev);
+ current = regulator_get_current(dev);
+ mode = regulator_get_mode(dev);
+ mode_name = get_mode_name(pdata->mode, pdata->mode_count, mode);
+ printf("%-20s %-10s ", pdata->name, enabled ? "enabled" : "disabled");
+ if (value >= 0)
+ printf("%10d ", value);
+ else
+ printf("%10s ", "-");
+ if (current >= 0)
+ printf("%10d ", current);
+ else
+ printf("%10s ", "-");
+ if (mode >= 0)
+ printf("%-10s", mode_name);
+ else
+ printf("%-10s", "-");
+ printf("\n");
+}
+
+static int do_status(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct dm_regulator_uclass_plat *uc_pdata;
+ struct udevice *dev;
+ int ret;
+
+ if (currdev && (argc < 2 || strcmp(argv[1], "-a"))) {
+ ret = curr_dev_and_plat(&dev, &uc_pdata, true);
+ if (ret)
+ return CMD_RET_FAILURE;
+ do_status_detail(dev, uc_pdata);
+ return 0;
+ }
+
+ /* Show all of them in a list, probing them as needed */
+ printf("%-20s %-10s %10s %10s %-10s\n", "Name", "Enabled", "uV", "mA",
+ "Mode");
+ for (ret = uclass_first_device(UCLASS_REGULATOR, &dev); dev;
+ ret = uclass_next_device(&dev))
+ do_status_line(dev);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_value(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct dm_regulator_uclass_plat *uc_pdata;
+ int value;
+ int force;
+ int ret;
+
+ ret = curr_dev_and_plat(&dev, &uc_pdata, argc == 1);
+ if (ret)
+ return ret;
+
+ if (argc == 1) {
+ ret = regulator_get_value(dev);
+ if (ret < 0) {
+ printf("Regulator: %s - can't get the Voltage!\n",
+ uc_pdata->name);
+ return failure(ret);
+ }
+
+ printf("%d uV\n", ret);
+ return CMD_RET_SUCCESS;
+ }
+
+ if (argc == 3)
+ force = !strcmp("-f", argv[2]);
+ else
+ force = 0;
+
+ value = simple_strtoul(argv[1], NULL, 0);
+ if ((value < uc_pdata->min_uV || value > uc_pdata->max_uV) && !force) {
+ printf("Value exceeds regulator constraint limits %d..%d uV\n",
+ uc_pdata->min_uV, uc_pdata->max_uV);
+ return CMD_RET_FAILURE;
+ }
+
+ if (!force)
+ ret = regulator_set_value(dev, value);
+ else
+ ret = regulator_set_value_force(dev, value);
+ if (ret) {
+ printf("Regulator: %s - can't set the Voltage!\n",
+ uc_pdata->name);
+ return failure(ret);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_current(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct dm_regulator_uclass_plat *uc_pdata;
+ int current;
+ int ret;
+
+ ret = curr_dev_and_plat(&dev, &uc_pdata, argc == 1);
+ if (ret)
+ return ret;
+
+ if (argc == 1) {
+ ret = regulator_get_current(dev);
+ if (ret < 0) {
+ printf("Regulator: %s - can't get the Current!\n",
+ uc_pdata->name);
+ return failure(ret);
+ }
+
+ printf("%d uA\n", ret);
+ return CMD_RET_SUCCESS;
+ }
+
+ current = simple_strtoul(argv[1], NULL, 0);
+ if (current < uc_pdata->min_uA || current > uc_pdata->max_uA) {
+ printf("Current exceeds regulator constraint limits\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = regulator_set_current(dev, current);
+ if (ret) {
+ printf("Regulator: %s - can't set the Current!\n",
+ uc_pdata->name);
+ return failure(ret);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_mode(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct dm_regulator_uclass_plat *uc_pdata;
+ int mode;
+ int ret;
+
+ ret = curr_dev_and_plat(&dev, &uc_pdata, false);
+ if (ret)
+ return ret;
+
+ if (argc == 1) {
+ ret = regulator_get_mode(dev);
+ if (ret < 0) {
+ printf("Regulator: %s - can't get the operation mode!\n",
+ uc_pdata->name);
+ return failure(ret);
+ }
+
+ printf("mode id: %d\n", ret);
+ return CMD_RET_SUCCESS;
+ }
+
+ mode = simple_strtoul(argv[1], NULL, 0);
+
+ ret = regulator_set_mode(dev, mode);
+ if (ret) {
+ printf("Regulator: %s - can't set the operation mode!\n",
+ uc_pdata->name);
+ return failure(ret);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_enable(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct dm_regulator_uclass_plat *uc_pdata;
+ int ret;
+
+ ret = curr_dev_and_plat(&dev, &uc_pdata, true);
+ if (ret)
+ return ret;
+
+ ret = regulator_set_enable(dev, true);
+ if (ret) {
+ printf("Regulator: %s - can't enable!\n", uc_pdata->name);
+ return failure(ret);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_disable(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct dm_regulator_uclass_plat *uc_pdata;
+ int ret;
+
+ ret = curr_dev_and_plat(&dev, &uc_pdata, true);
+ if (ret)
+ return ret;
+
+ ret = regulator_set_enable(dev, false);
+ if (ret) {
+ printf("Regulator: %s - can't disable!\n", uc_pdata->name);
+ return failure(ret);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static struct cmd_tbl subcmd[] = {
+ U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""),
+ U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""),
+ U_BOOT_CMD_MKENT(info, 2, 1, do_info, "", ""),
+ U_BOOT_CMD_MKENT(status, 2, 1, do_status, "", ""),
+ U_BOOT_CMD_MKENT(value, 3, 1, do_value, "", ""),
+ U_BOOT_CMD_MKENT(current, 3, 1, do_current, "", ""),
+ U_BOOT_CMD_MKENT(mode, 2, 1, do_mode, "", ""),
+ U_BOOT_CMD_MKENT(enable, 1, 1, do_enable, "", ""),
+ U_BOOT_CMD_MKENT(disable, 1, 1, do_disable, "", ""),
+};
+
+static int do_regulator(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cmd;
+
+ argc--;
+ argv++;
+
+ cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd));
+ if (cmd == NULL || argc > cmd->maxargs)
+ return CMD_RET_USAGE;
+
+ return cmd->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(regulator, CONFIG_SYS_MAXARGS, 1, do_regulator,
+ "uclass operations",
+ "list - list UCLASS regulator devices\n"
+ "regulator dev [regulator-name] - show/[set] operating regulator device\n"
+ "regulator info - print constraints info\n"
+ "regulator status [-a] - print operating status [for all]\n"
+ "regulator value [val] [-f] - print/[set] voltage value [uV] (force)\n"
+ "regulator current [val] - print/[set] current value [uA]\n"
+ "regulator mode [id] - print/[set] operating mode id\n"
+ "regulator enable - enable the regulator output\n"
+ "regulator disable - disable the regulator output\n"
+);
diff --git a/roms/u-boot/cmd/reiser.c b/roms/u-boot/cmd/reiser.c
new file mode 100644
index 000000000..3db926f80
--- /dev/null
+++ b/roms/u-boot/cmd/reiser.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2003 - 2004
+ * Sysgo Real-Time Solutions, AG <www.elinos.com>
+ * Pavel Bartusek <pba@sysgo.com>
+ */
+
+/*
+ * Reiserfs support
+ */
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <linux/ctype.h>
+#include <asm/byteorder.h>
+#include <reiserfs.h>
+#include <part.h>
+
+#if !CONFIG_IS_ENABLED(DOS_PARTITION)
+#error DOS partition support must be selected
+#endif
+
+/* #define REISER_DEBUG */
+
+#ifdef REISER_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+int do_reiserls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *filename = "/";
+ int dev, part;
+ struct blk_desc *dev_desc = NULL;
+ struct disk_partition info;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
+ if (part < 0)
+ return 1;
+
+ if (argc == 4) {
+ filename = argv[3];
+ }
+
+ dev = dev_desc->devnum;
+ PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
+
+ reiserfs_set_blk_dev(dev_desc, &info);
+
+ if (!reiserfs_mount(info.size)) {
+ printf ("** Bad Reiserfs partition or disk - %s %d:%d **\n", argv[1], dev, part);
+ return 1;
+ }
+
+ if (reiserfs_ls (filename)) {
+ printf ("** Error reiserfs_ls() **\n");
+ return 1;
+ };
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ reiserls, 4, 1, do_reiserls,
+ "list files in a directory (default /)",
+ "<interface> <dev[:part]> [directory]\n"
+ " - list files from 'dev' on 'interface' in a 'directory'"
+);
+
+/******************************************************************************
+ * Reiserfs boot command intepreter. Derived from diskboot
+ */
+int do_reiserload(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *filename = NULL;
+ int dev, part;
+ ulong addr = 0, filelen;
+ struct disk_partition info;
+ struct blk_desc *dev_desc = NULL;
+ unsigned long count;
+ char *addr_str;
+
+ switch (argc) {
+ case 3:
+ addr_str = env_get("loadaddr");
+ if (addr_str != NULL) {
+ addr = simple_strtoul (addr_str, NULL, 16);
+ } else {
+ addr = CONFIG_SYS_LOAD_ADDR;
+ }
+ filename = env_get("bootfile");
+ count = 0;
+ break;
+ case 4:
+ addr = simple_strtoul (argv[3], NULL, 16);
+ filename = env_get("bootfile");
+ count = 0;
+ break;
+ case 5:
+ addr = simple_strtoul (argv[3], NULL, 16);
+ filename = argv[4];
+ count = 0;
+ break;
+ case 6:
+ addr = simple_strtoul (argv[3], NULL, 16);
+ filename = argv[4];
+ count = simple_strtoul (argv[5], NULL, 16);
+ break;
+
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ if (!filename) {
+ puts ("\n** No boot file defined **\n");
+ return 1;
+ }
+
+ part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
+ if (part < 0)
+ return 1;
+
+ dev = dev_desc->devnum;
+
+ printf("Loading file \"%s\" from %s device %d%c%c\n",
+ filename, argv[1], dev,
+ part ? ':' : ' ', part ? part + '0' : ' ');
+
+ reiserfs_set_blk_dev(dev_desc, &info);
+
+ if (!reiserfs_mount(info.size)) {
+ printf ("** Bad Reiserfs partition or disk - %s %d:%d **\n", argv[1], dev, part);
+ return 1;
+ }
+
+ filelen = reiserfs_open(filename);
+ if (filelen < 0) {
+ printf("** File not found %s **\n", filename);
+ return 1;
+ }
+ if ((count < filelen) && (count != 0)) {
+ filelen = count;
+ }
+
+ if (reiserfs_read((char *)addr, filelen) != filelen) {
+ printf("\n** Unable to read \"%s\" from %s %d:%d **\n", filename, argv[1], dev, part);
+ return 1;
+ }
+
+ /* Loading ok, update default load address */
+ image_load_addr = addr;
+
+ printf ("\n%ld bytes read\n", filelen);
+ env_set_hex("filesize", filelen);
+
+ return filelen;
+}
+
+U_BOOT_CMD(
+ reiserload, 6, 0, do_reiserload,
+ "load binary file from a Reiser filesystem",
+ "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
+ " - load binary file 'filename' from 'dev' on 'interface'\n"
+ " to address 'addr' from dos filesystem"
+);
diff --git a/roms/u-boot/cmd/remoteproc.c b/roms/u-boot/cmd/remoteproc.c
new file mode 100644
index 000000000..b3ddcebe3
--- /dev/null
+++ b/roms/u-boot/cmd/remoteproc.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015
+ * Texas Instruments Incorporated - http://www.ti.com/
+ */
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <remoteproc.h>
+
+/**
+ * print_remoteproc_list() - print all the remote processor devices
+ *
+ * Return: 0 if no error, else returns appropriate error value.
+ */
+static int print_remoteproc_list(void)
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret;
+ char *type;
+
+ ret = uclass_get(UCLASS_REMOTEPROC, &uc);
+ if (ret) {
+ printf("Cannot find Remote processor class\n");
+ return ret;
+ }
+
+ uclass_foreach_dev(dev, uc) {
+ struct dm_rproc_uclass_pdata *uc_pdata;
+ const struct dm_rproc_ops *ops = rproc_get_ops(dev);
+
+ uc_pdata = dev_get_uclass_plat(dev);
+
+ /* Do not print if rproc is not probed */
+ if (!(dev_get_flags(dev) & DM_FLAG_ACTIVATED))
+ continue;
+
+ switch (uc_pdata->mem_type) {
+ case RPROC_INTERNAL_MEMORY_MAPPED:
+ type = "internal memory mapped";
+ break;
+ default:
+ type = "unknown";
+ break;
+ }
+ printf("%d - Name:'%s' type:'%s' supports: %s%s%s%s%s%s\n",
+ dev_seq(dev),
+ uc_pdata->name,
+ type,
+ ops->load ? "load " : "",
+ ops->start ? "start " : "",
+ ops->stop ? "stop " : "",
+ ops->reset ? "reset " : "",
+ ops->is_running ? "is_running " : "",
+ ops->ping ? "ping " : "");
+ }
+ return 0;
+}
+
+/**
+ * do_rproc_init() - do basic initialization
+ * @cmdtp: unused
+ * @flag: unused
+ * @argc: unused
+ * @argv: unused
+ *
+ * Return: 0 if no error, else returns appropriate error value.
+ */
+static int do_rproc_init(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int id;
+
+ if (rproc_is_initialized()) {
+ printf("\tRemote Processors are already initialized\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc == 1) {
+ if (!rproc_init())
+ return 0;
+ printf("Few Remote Processors failed to be initialized\n");
+ } else if (argc == 2) {
+ id = (int)simple_strtoul(argv[1], NULL, 10);
+ if (!rproc_dev_init(id))
+ return 0;
+ printf("Remote Processor %d failed to be initialized\n", id);
+ }
+
+ return CMD_RET_FAILURE;
+}
+
+/**
+ * do_remoteproc_list() - print list of remote proc devices.
+ * @cmdtp: unused
+ * @flag: unused
+ * @argc: unused
+ * @argv: unused
+ *
+ * Return: 0 if no error, else returns appropriate error value.
+ */
+static int do_remoteproc_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (print_remoteproc_list())
+ return CMD_RET_FAILURE;
+
+ return 0;
+}
+
+/**
+ * do_remoteproc_load() - Load a remote processor with binary image
+ * @cmdtp: unused
+ * @flag: unused
+ * @argc: argument count for the load function
+ * @argv: arguments for the load function
+ *
+ * Return: 0 if no error, else returns appropriate error value.
+ */
+static int do_remoteproc_load(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr, size;
+ int id, ret;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ id = (int)simple_strtoul(argv[1], NULL, 10);
+ addr = simple_strtoul(argv[2], NULL, 16);
+
+ size = simple_strtoul(argv[3], NULL, 16);
+
+ if (!size) {
+ printf("\t Expect some size??\n");
+ return CMD_RET_USAGE;
+ }
+
+ ret = rproc_load(id, addr, size);
+ printf("Load Remote Processor %d with data@addr=0x%08lx %lu bytes:%s\n",
+ id, addr, size, ret ? " Failed!" : " Success!");
+
+ return ret ? CMD_RET_FAILURE : 0;
+}
+
+/**
+ * do_remoteproc_wrapper() - wrapper for various rproc commands
+ * @cmdtp: unused
+ * @flag: unused
+ * @argc: argument count for the rproc command
+ * @argv: arguments for the rproc command
+ *
+ * Most of the commands just take id as a parameter andinvoke various
+ * helper routines in remote processor core. by using a set of
+ * common checks, we can reduce the amount of code used for this.
+ *
+ * Return: 0 if no error, else returns appropriate error value.
+ */
+static int do_remoteproc_wrapper(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int id, ret = CMD_RET_USAGE;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ id = (int)simple_strtoul(argv[1], NULL, 10);
+
+ if (!strcmp(argv[0], "start")) {
+ ret = rproc_start(id);
+ } else if (!strcmp(argv[0], "stop")) {
+ ret = rproc_stop(id);
+ } else if (!strcmp(argv[0], "reset")) {
+ ret = rproc_reset(id);
+ } else if (!strcmp(argv[0], "is_running")) {
+ ret = rproc_is_running(id);
+ if (!ret) {
+ printf("Remote processor is Running\n");
+ } else if (ret == 1) {
+ printf("Remote processor is NOT Running\n");
+ ret = 0;
+ }
+ /* Else error.. */
+ } else if (!strcmp(argv[0], "ping")) {
+ ret = rproc_ping(id);
+ if (!ret) {
+ printf("Remote processor responds 'Pong'\n");
+ } else if (ret == 1) {
+ printf("No response from Remote processor\n");
+ ret = 0;
+ }
+ /* Else error.. */
+ }
+
+ if (ret < 0)
+ printf("Operation Failed with error (%d)\n", ret);
+
+ return ret ? CMD_RET_FAILURE : 0;
+}
+
+static struct cmd_tbl cmd_remoteproc_sub[] = {
+ U_BOOT_CMD_MKENT(init, 1, 1, do_rproc_init,
+ "Enumerate and initialize the remote processor(s)",
+ "id - ID of the remote processor\n"
+ "If id is not passed, initialize all the remote processors"),
+ U_BOOT_CMD_MKENT(list, 0, 1, do_remoteproc_list,
+ "list remote processors", ""),
+ U_BOOT_CMD_MKENT(load, 5, 1, do_remoteproc_load,
+ "Load remote processor with provided image",
+ "<id> [addr] [size]\n"
+ "- id: ID of the remote processor(see 'list' cmd)\n"
+ "- addr: Address in memory of the image to loadup\n"
+ "- size: Size of the image to loadup\n"),
+ U_BOOT_CMD_MKENT(start, 1, 1, do_remoteproc_wrapper,
+ "Start remote processor",
+ "id - ID of the remote processor (see 'list' cmd)\n"),
+ U_BOOT_CMD_MKENT(stop, 1, 1, do_remoteproc_wrapper,
+ "Stop remote processor",
+ "id - ID of the remote processor (see 'list' cmd)\n"),
+ U_BOOT_CMD_MKENT(reset, 1, 1, do_remoteproc_wrapper,
+ "Reset remote processor",
+ "id - ID of the remote processor (see 'list' cmd)\n"),
+ U_BOOT_CMD_MKENT(is_running, 1, 1, do_remoteproc_wrapper,
+ "Check to see if remote processor is running\n",
+ "id - ID of the remote processor (see 'list' cmd)\n"),
+ U_BOOT_CMD_MKENT(ping, 1, 1, do_remoteproc_wrapper,
+ "Ping to communicate with remote processor\n",
+ "id - ID of the remote processor (see 'list' cmd)\n"),
+};
+
+/**
+ * do_remoteproc() - (replace: short desc)
+ * @cmdtp: unused
+ * @flag: unused
+ * @argc: argument count
+ * @argv: argument list
+ *
+ * parses up the command table to invoke the correct command.
+ *
+ * Return: 0 if no error, else returns appropriate error value.
+ */
+static int do_remoteproc(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c = NULL;
+
+ /* Strip off leading 'rproc' command argument */
+ argc--;
+ argv++;
+
+ if (argc)
+ c = find_cmd_tbl(argv[0], cmd_remoteproc_sub,
+ ARRAY_SIZE(cmd_remoteproc_sub));
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(rproc, 5, 1, do_remoteproc,
+ "Control operation of remote processors in an SoC",
+ " [init|list|load|start|stop|reset|is_running|ping]\n"
+ "\t\t Where:\n"
+ "\t\t[addr] is a memory address\n"
+ "\t\t<id> is a numerical identifier for the remote processor\n"
+ "\t\t provided by 'list' command.\n"
+ "\t\tNote: Remote processors must be initalized prior to usage\n"
+ "\t\tNote: Services are dependent on the driver capability\n"
+ "\t\t 'list' command shows the capability of each device\n"
+ "\n\tSubcommands:\n"
+ "\tinit <id> - Enumerate and initalize the remote processor.\n"
+ "\t if id is not passed, initialize all the remote prcessors\n"
+ "\tlist - list available remote processors\n"
+ "\tload <id> [addr] [size]- Load the remote processor with binary\n"
+ "\t image stored at address [addr] in memory\n"
+ "\tstart <id> - Start the remote processor(must be loaded)\n"
+ "\tstop <id> - Stop the remote processor\n"
+ "\treset <id> - Reset the remote processor\n"
+ "\tis_running <id> - Reports if the remote processor is running\n"
+ "\tping <id> - Ping the remote processor for communication\n");
diff --git a/roms/u-boot/cmd/riscv/Makefile b/roms/u-boot/cmd/riscv/Makefile
new file mode 100644
index 000000000..1e6ac364e
--- /dev/null
+++ b/roms/u-boot/cmd/riscv/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_CMD_EXCEPTION) += exception.o
+obj-$(CONFIG_CMD_SBI) += sbi.o
diff --git a/roms/u-boot/cmd/riscv/exception.c b/roms/u-boot/cmd/riscv/exception.c
new file mode 100644
index 000000000..7a08061d1
--- /dev/null
+++ b/roms/u-boot/cmd/riscv/exception.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The 'exception' command can be used for testing exception handling.
+ *
+ * Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_ebreak(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ asm volatile ("ebreak\n");
+ return CMD_RET_FAILURE;
+}
+
+static int do_unaligned(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ asm volatile (
+ "auipc a1, 0\n"
+ "ori a1, a1, 3\n"
+ "lw a2, (0)(a1)\n"
+ );
+ printf("The system supports unaligned access.\n");
+ return CMD_RET_SUCCESS;
+}
+
+static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ asm volatile (".word 0xffffffff\n");
+ return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_sub[] = {
+ U_BOOT_CMD_MKENT(ebreak, CONFIG_SYS_MAXARGS, 1, do_ebreak,
+ "", ""),
+ U_BOOT_CMD_MKENT(unaligned, CONFIG_SYS_MAXARGS, 1, do_unaligned,
+ "", ""),
+ U_BOOT_CMD_MKENT(undefined, CONFIG_SYS_MAXARGS, 1, do_undefined,
+ "", ""),
+};
+
+static char exception_help_text[] =
+ "<ex>\n"
+ " The following exceptions are available:\n"
+ " ebreak - breakpoint\n"
+ " undefined - illegal instruction\n"
+ " unaligned - load address misaligned\n"
+ ;
+
+#include <exception.h>
diff --git a/roms/u-boot/cmd/riscv/sbi.c b/roms/u-boot/cmd/riscv/sbi.c
new file mode 100644
index 000000000..90c0811e1
--- /dev/null
+++ b/roms/u-boot/cmd/riscv/sbi.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The 'sbi' command displays information about the SBI implementation.
+ *
+ * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/sbi.h>
+
+struct sbi_imp {
+ const long id;
+ const char *name;
+};
+
+struct sbi_ext {
+ const u32 id;
+ const char *name;
+};
+
+static struct sbi_imp implementations[] = {
+ { 0, "Berkeley Boot Loader (BBL)" },
+ { 1, "OpenSBI" },
+ { 2, "Xvisor" },
+ { 3, "KVM" },
+ { 4, "RustSBI" },
+ { 5, "Diosix" },
+};
+
+static struct sbi_ext extensions[] = {
+ { 0x00000000, "sbi_set_timer" },
+ { 0x00000001, "sbi_console_putchar" },
+ { 0x00000002, "sbi_console_getchar" },
+ { 0x00000003, "sbi_clear_ipi" },
+ { 0x00000004, "sbi_send_ipi" },
+ { 0x00000005, "sbi_remote_fence_i" },
+ { 0x00000006, "sbi_remote_sfence_vma" },
+ { 0x00000007, "sbi_remote_sfence_vma_asid" },
+ { 0x00000008, "sbi_shutdown" },
+ { 0x00000010, "SBI Base Functionality" },
+ { 0x54494D45, "Timer Extension" },
+ { 0x00735049, "IPI Extension" },
+ { 0x52464E43, "RFENCE Extension" },
+ { 0x0048534D, "Hart State Management Extension" },
+ { 0x53525354, "System Reset Extension" },
+};
+
+static int do_sbi(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int i;
+ long ret;
+
+ ret = sbi_get_spec_version();
+ if (ret >= 0)
+ printf("SBI %ld.%ld\n", ret >> 24, ret & 0xffffff);
+ ret = sbi_get_impl_id();
+ if (ret >= 0) {
+ for (i = 0; i < ARRAY_SIZE(implementations); ++i) {
+ if (ret == implementations[i].id) {
+ printf("%s\n", implementations[i].name);
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(implementations))
+ printf("Unknown implementation ID %ld\n", ret);
+ }
+ printf("Extensions:\n");
+ for (i = 0; i < ARRAY_SIZE(extensions); ++i) {
+ ret = sbi_probe_extension(extensions[i].id);
+ if (ret > 0)
+ printf(" %s\n", extensions[i].name);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char sbi_help_text[] =
+ "- display SBI spec version, implementation, and available extensions";
+
+#endif
+
+U_BOOT_CMD_COMPLETE(
+ sbi, 1, 0, do_sbi,
+ "display SBI information",
+ sbi_help_text, NULL
+);
diff --git a/roms/u-boot/cmd/rng.c b/roms/u-boot/cmd/rng.c
new file mode 100644
index 000000000..9747c11be
--- /dev/null
+++ b/roms/u-boot/cmd/rng.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The 'rng' command prints bytes from the hardware random number generator.
+ *
+ * Copyright (c) 2019, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <hexdump.h>
+#include <malloc.h>
+#include <rng.h>
+
+static int do_rng(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ size_t n = 0x40;
+ struct udevice *dev;
+ void *buf;
+ int ret = CMD_RET_SUCCESS;
+
+ if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
+ printf("No RNG device\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc >= 2)
+ n = simple_strtoul(argv[1], NULL, 16);
+
+ buf = malloc(n);
+ if (!buf) {
+ printf("Out of memory\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (dm_rng_read(dev, buf, n)) {
+ printf("Reading RNG failed\n");
+ ret = CMD_RET_FAILURE;
+ } else {
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, n);
+ }
+
+ free(buf);
+
+ return ret;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char rng_help_text[] =
+ "[n]\n"
+ " - print n random bytes\n";
+#endif
+
+U_BOOT_CMD(
+ rng, 2, 0, do_rng,
+ "print bytes from the hardware random number generator",
+ rng_help_text
+);
diff --git a/roms/u-boot/cmd/rockusb.c b/roms/u-boot/cmd/rockusb.c
new file mode 100644
index 000000000..f181ec611
--- /dev/null
+++ b/roms/u-boot/cmd/rockusb.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Eddie Cai <eddie.cai.linux@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <g_dnl.h>
+#include <usb.h>
+#include <asm/arch-rockchip/f_rockusb.h>
+
+static int do_rockusb(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int controller_index, dev_index;
+ char *usb_controller;
+ char *devtype;
+ char *devnum;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ usb_controller = argv[1];
+ controller_index = simple_strtoul(usb_controller, NULL, 0);
+
+ if (argc >= 4) {
+ devtype = argv[2];
+ devnum = argv[3];
+ } else {
+ return CMD_RET_USAGE;
+ }
+ dev_index = simple_strtoul(devnum, NULL, 0);
+ rockusb_dev_init(devtype, dev_index);
+
+ ret = usb_gadget_initialize(controller_index);
+ if (ret) {
+ printf("USB init failed: %d\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ g_dnl_clear_detach();
+ ret = g_dnl_register("usb_dnl_rockusb");
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ if (!g_dnl_board_usb_cable_connected()) {
+ puts("\rUSB cable not detected, Command exit.\n");
+ ret = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ while (1) {
+ if (g_dnl_detach())
+ break;
+ if (ctrlc())
+ break;
+ usb_gadget_handle_interrupts(controller_index);
+ }
+ ret = CMD_RET_SUCCESS;
+
+exit:
+ g_dnl_unregister();
+ g_dnl_clear_detach();
+ usb_gadget_release(controller_index);
+
+ return ret;
+}
+
+U_BOOT_CMD(rockusb, 4, 1, do_rockusb,
+ "use the rockusb protocol",
+ "<USB_controller> <devtype> <dev[:part]> e.g. rockusb 0 mmc 0\n"
+);
diff --git a/roms/u-boot/cmd/rtc.c b/roms/u-boot/cmd/rtc.c
new file mode 100644
index 000000000..b4f61b2e8
--- /dev/null
+++ b/roms/u-boot/cmd/rtc.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <hexdump.h>
+#include <i2c.h>
+#include <mapmem.h>
+#include <rtc.h>
+
+#define MAX_RTC_BYTES 32
+
+static int do_rtc_read(struct udevice *dev, int argc, char * const argv[])
+{
+ u8 buf[MAX_RTC_BYTES];
+ int reg, len, ret, r;
+
+ if (argc < 2 || argc > 3)
+ return CMD_RET_USAGE;
+
+ reg = simple_strtoul(argv[0], NULL, 16);
+ len = simple_strtoul(argv[1], NULL, 16);
+
+ if (argc == 3) {
+ u8 *addr;
+
+ addr = map_sysmem(simple_strtoul(argv[2], NULL, 16), len);
+ ret = dm_rtc_read(dev, reg, addr, len);
+ unmap_sysmem(addr);
+ if (ret) {
+ printf("dm_rtc_read() failed: %d\n", ret);
+ return CMD_RET_FAILURE;
+ }
+ return CMD_RET_SUCCESS;
+ }
+
+ while (len) {
+ r = min_t(int, len, sizeof(buf));
+ ret = dm_rtc_read(dev, reg, buf, r);
+ if (ret) {
+ printf("dm_rtc_read() failed: %d\n", ret);
+ return CMD_RET_FAILURE;
+ }
+ print_buffer(reg, buf, 1, r, 0);
+ len -= r;
+ reg += r;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_rtc_write(struct udevice *dev, int argc, char * const argv[])
+{
+ u8 buf[MAX_RTC_BYTES];
+ int reg, len, ret;
+ const char *s;
+ int slen;
+
+ if (argc < 2 || argc > 3)
+ return CMD_RET_USAGE;
+
+ reg = simple_strtoul(argv[0], NULL, 16);
+
+ if (argc == 3) {
+ u8 *addr;
+
+ len = simple_strtoul(argv[1], NULL, 16);
+ addr = map_sysmem(simple_strtoul(argv[2], NULL, 16), len);
+ ret = dm_rtc_write(dev, reg, addr, len);
+ unmap_sysmem(addr);
+ if (ret) {
+ printf("dm_rtc_write() failed: %d\n", ret);
+ return CMD_RET_FAILURE;
+ }
+ return CMD_RET_SUCCESS;
+ }
+
+ s = argv[1];
+ slen = strlen(s);
+
+ if (slen % 2) {
+ printf("invalid hex string\n");
+ return CMD_RET_FAILURE;
+ }
+
+ while (slen) {
+ len = min_t(int, slen / 2, sizeof(buf));
+ if (hex2bin(buf, s, len)) {
+ printf("invalid hex string\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = dm_rtc_write(dev, reg, buf, len);
+ if (ret) {
+ printf("dm_rtc_write() failed: %d\n", ret);
+ return CMD_RET_FAILURE;
+ }
+ s += 2 * len;
+ slen -= 2 * len;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+int do_rtc(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+ static int curr_rtc;
+ struct udevice *dev;
+ int ret, idx;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ argc--;
+ argv++;
+
+ if (!strcmp(argv[0], "list")) {
+ struct uclass *uc;
+
+ idx = 0;
+ uclass_id_foreach_dev(UCLASS_RTC, dev, uc) {
+ printf("RTC #%d - %s\n", idx++, dev->name);
+ }
+ if (!idx) {
+ printf("*** no RTC devices available ***\n");
+ return CMD_RET_FAILURE;
+ }
+ return CMD_RET_SUCCESS;
+ }
+
+ idx = curr_rtc;
+ if (!strcmp(argv[0], "dev") && argc >= 2)
+ idx = simple_strtoul(argv[1], NULL, 10);
+
+ ret = uclass_get_device(UCLASS_RTC, idx, &dev);
+ if (ret) {
+ printf("Cannot find RTC #%d: err=%d\n", idx, ret);
+ return CMD_RET_FAILURE;
+ }
+
+ if (!strcmp(argv[0], "dev")) {
+ /* Show the existing or newly selected RTC */
+ if (argc >= 2)
+ curr_rtc = idx;
+ printf("RTC #%d - %s\n", idx, dev->name);
+ return CMD_RET_SUCCESS;
+ }
+
+ if (!strcmp(argv[0], "read"))
+ return do_rtc_read(dev, argc - 1, argv + 1);
+
+ if (!strcmp(argv[0], "write"))
+ return do_rtc_write(dev, argc - 1, argv + 1);
+
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+ rtc, 5, 0, do_rtc,
+ "RTC subsystem",
+ "list - show available rtc devices\n"
+ "rtc dev [n] - show or set current rtc device\n"
+ "rtc read <reg> <count> - read and display 8-bit registers starting at <reg>\n"
+ "rtc read <reg> <count> <addr> - read 8-bit registers starting at <reg> to memory <addr>\n"
+ "rtc write <reg> <hexstring> - write 8-bit registers starting at <reg>\n"
+ "rtc write <reg> <count> <addr> - write from memory <addr> to 8-bit registers starting at <reg>\n"
+);
diff --git a/roms/u-boot/cmd/sandbox/Makefile b/roms/u-boot/cmd/sandbox/Makefile
new file mode 100644
index 000000000..24df023ec
--- /dev/null
+++ b/roms/u-boot/cmd/sandbox/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_CMD_EXCEPTION) += exception.o
diff --git a/roms/u-boot/cmd/sandbox/exception.c b/roms/u-boot/cmd/sandbox/exception.c
new file mode 100644
index 000000000..1aa1d673a
--- /dev/null
+++ b/roms/u-boot/cmd/sandbox/exception.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The 'exception' command can be used for testing exception handling.
+ *
+ * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_sigsegv(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u8 *ptr = NULL;
+
+ *ptr = 0;
+ return CMD_RET_FAILURE;
+}
+
+static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ asm volatile (".word 0xffff\n");
+ return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_sub[] = {
+ U_BOOT_CMD_MKENT(sigsegv, CONFIG_SYS_MAXARGS, 1, do_sigsegv,
+ "", ""),
+ U_BOOT_CMD_MKENT(undefined, CONFIG_SYS_MAXARGS, 1, do_undefined,
+ "", ""),
+};
+
+static char exception_help_text[] =
+ "<ex>\n"
+ " The following exceptions are available:\n"
+ " undefined - undefined instruction\n"
+ " sigsegv - illegal memory access\n"
+ ;
+
+#include <exception.h>
diff --git a/roms/u-boot/cmd/sata.c b/roms/u-boot/cmd/sata.c
new file mode 100644
index 000000000..aa396c1bb
--- /dev/null
+++ b/roms/u-boot/cmd/sata.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2000-2005, DENX Software Engineering
+ * Wolfgang Denk <wd@denx.de>
+ * Copyright (C) Procsys. All rights reserved.
+ * Mushtaq Khan <mushtaq_k@procsys.com>
+ * <mushtaqk_921@yahoo.co.in>
+ * Copyright (C) 2008 Freescale Semiconductor, Inc.
+ * Dave Liu <daveliu@freescale.com>
+ */
+
+#include <common.h>
+#include <ahci.h>
+#include <blk.h>
+#include <dm.h>
+#include <command.h>
+#include <part.h>
+#include <sata.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+static int sata_curr_device = -1;
+
+int sata_remove(int devnum)
+{
+#ifdef CONFIG_AHCI
+ struct udevice *dev;
+ int rc;
+
+ blk_unbind_all(IF_TYPE_SATA);
+
+ rc = uclass_find_device(UCLASS_AHCI, devnum, &dev);
+ if (!rc && !dev)
+ rc = uclass_find_first_device(UCLASS_AHCI, &dev);
+ if (rc || !dev) {
+ printf("Cannot find SATA device %d (err=%d)\n", devnum, rc);
+ return CMD_RET_FAILURE;
+ }
+
+ rc = device_remove(dev, DM_REMOVE_NORMAL);
+ if (rc) {
+ printf("Cannot remove SATA device '%s' (err=%d)\n", dev->name,
+ rc);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+#else
+ return sata_stop();
+#endif
+}
+
+int sata_probe(int devnum)
+{
+#ifdef CONFIG_AHCI
+ struct udevice *dev;
+ int rc;
+
+ rc = uclass_get_device(UCLASS_AHCI, devnum, &dev);
+ if (rc)
+ rc = uclass_find_first_device(UCLASS_AHCI, &dev);
+ if (rc) {
+ printf("Cannot probe SATA device %d (err=%d)\n", devnum, rc);
+ return CMD_RET_FAILURE;
+ }
+ if (!dev) {
+ printf("No SATA device found!\n");
+ return CMD_RET_FAILURE;
+ }
+ rc = sata_scan(dev);
+ if (rc) {
+ printf("Cannot scan SATA device %d (err=%d)\n", devnum, rc);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+#else
+ return sata_initialize() < 0 ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+#endif
+}
+
+static int do_sata(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int rc = 0;
+
+ if (argc >= 2) {
+ int devnum = 0;
+
+ if (argc == 3)
+ devnum = (int)simple_strtoul(argv[2], NULL, 10);
+ if (!strcmp(argv[1], "stop"))
+ return sata_remove(devnum);
+
+ if (!strcmp(argv[1], "init")) {
+ if (sata_curr_device != -1) {
+ rc = sata_remove(devnum);
+ if (rc)
+ return rc;
+ }
+
+ return sata_probe(devnum);
+ }
+ }
+
+ /* If the user has not yet run `sata init`, do it now */
+ if (sata_curr_device == -1) {
+ rc = sata_probe(0);
+ if (rc)
+ return rc;
+ sata_curr_device = 0;
+ }
+
+ return blk_common_cmd(argc, argv, IF_TYPE_SATA, &sata_curr_device);
+}
+
+U_BOOT_CMD(
+ sata, 5, 1, do_sata,
+ "SATA sub system",
+ "init - init SATA sub system\n"
+ "sata stop [dev] - disable SATA sub system or device\n"
+ "sata info - show available SATA devices\n"
+ "sata device [dev] - show or set current device\n"
+ "sata part [dev] - print partition table\n"
+ "sata read addr blk# cnt\n"
+ "sata write addr blk# cnt"
+);
diff --git a/roms/u-boot/cmd/sb.c b/roms/u-boot/cmd/sb.c
new file mode 100644
index 000000000..0d55818e3
--- /dev/null
+++ b/roms/u-boot/cmd/sb.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018, Google Inc.
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <spl.h>
+#include <asm/global_data.h>
+#include <asm/state.h>
+
+static int do_sb_handoff(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+#if CONFIG_IS_ENABLED(HANDOFF)
+ if (gd->spl_handoff)
+ printf("SPL handoff magic %lx\n", gd->spl_handoff->arch.magic);
+ else
+ printf("SPL handoff info not received\n");
+
+ return 0;
+#else
+ printf("Command not supported\n");
+
+ return CMD_RET_USAGE;
+#endif
+}
+
+static int do_sb_state(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct sandbox_state *state;
+
+ state = state_get_current();
+ state_show(state);
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_sb_sub[] = {
+ U_BOOT_CMD_MKENT(handoff, 1, 0, do_sb_handoff, "", ""),
+ U_BOOT_CMD_MKENT(state, 1, 0, do_sb_state, "", ""),
+};
+
+static int do_sb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ /* Skip past 'sb' */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], cmd_sb_sub, ARRAY_SIZE(cmd_sb_sub));
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+ sb, 8, 1, do_sb,
+ "Sandbox status commands",
+ "handoff - Show handoff data received from SPL\n"
+ "sb state - Show sandbox state"
+);
diff --git a/roms/u-boot/cmd/scp03.c b/roms/u-boot/cmd/scp03.c
new file mode 100644
index 000000000..655e0bba0
--- /dev/null
+++ b/roms/u-boot/cmd/scp03.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2021, Foundries.IO
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <scp03.h>
+
+int do_scp03_enable(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ if (tee_enable_scp03()) {
+ printf("TEE failed to enable SCP03\n");
+ return CMD_RET_FAILURE;
+ }
+
+ printf("SCP03 is enabled\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+int do_scp03_provision(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ if (tee_provision_scp03()) {
+ printf("TEE failed to provision SCP03 keys\n");
+ return CMD_RET_FAILURE;
+ }
+
+ printf("SCP03 is provisioned\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+static char text[] =
+ "provides a command to enable SCP03 and provision the SCP03 keys\n"
+ " enable - enable SCP03 on the TEE\n"
+ " provision - provision SCP03 on the TEE\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(scp03, "Secure Channel Protocol 03 control", text,
+ U_BOOT_SUBCMD_MKENT(enable, 1, 1, do_scp03_enable),
+ U_BOOT_SUBCMD_MKENT(provision, 1, 1, do_scp03_provision));
+
diff --git a/roms/u-boot/cmd/scsi.c b/roms/u-boot/cmd/scsi.c
new file mode 100644
index 000000000..5f710d289
--- /dev/null
+++ b/roms/u-boot/cmd/scsi.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ */
+
+/*
+ * SCSI support.
+ */
+#include <common.h>
+#include <blk.h>
+#include <command.h>
+#include <scsi.h>
+
+static int scsi_curr_dev; /* current device */
+
+/*
+ * scsi boot command intepreter. Derived from diskboot
+ */
+static int do_scsiboot(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return common_diskboot(cmdtp, "scsi", argc, argv);
+}
+
+/*
+ * scsi command intepreter
+ */
+static int do_scsi(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+
+ if (argc == 2) {
+ if (strncmp(argv[1], "res", 3) == 0) {
+ printf("\nReset SCSI\n");
+#ifndef CONFIG_DM_SCSI
+ scsi_bus_reset(NULL);
+#endif
+ ret = scsi_scan(true);
+ if (ret)
+ return CMD_RET_FAILURE;
+ return ret;
+ }
+ if (strncmp(argv[1], "scan", 4) == 0) {
+ ret = scsi_scan(true);
+ if (ret)
+ return CMD_RET_FAILURE;
+ return ret;
+ }
+ }
+
+ return blk_common_cmd(argc, argv, IF_TYPE_SCSI, &scsi_curr_dev);
+}
+
+U_BOOT_CMD(
+ scsi, 5, 1, do_scsi,
+ "SCSI sub-system",
+ "reset - reset SCSI controller\n"
+ "scsi info - show available SCSI devices\n"
+ "scsi scan - (re-)scan SCSI bus\n"
+ "scsi device [dev] - show or set current device\n"
+ "scsi part [dev] - print partition table of one or all SCSI devices\n"
+ "scsi read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
+ " to memory address `addr'\n"
+ "scsi write addr blk# cnt - write `cnt' blocks starting at block\n"
+ " `blk#' from memory address `addr'"
+);
+
+U_BOOT_CMD(
+ scsiboot, 3, 1, do_scsiboot,
+ "boot from SCSI device",
+ "loadAddr dev:part"
+);
diff --git a/roms/u-boot/cmd/setexpr.c b/roms/u-boot/cmd/setexpr.c
new file mode 100644
index 000000000..e828be397
--- /dev/null
+++ b/roms/u-boot/cmd/setexpr.c
@@ -0,0 +1,518 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2013 Wolfgang Denk <wd@denx.de>
+ */
+
+/*
+ * This file provides a shell like 'expr' function to return.
+ */
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <env.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <linux/sizes.h>
+
+/**
+ * struct expr_arg: Holds an argument to an expression
+ *
+ * @ival: Integer value (if width is not CMD_DATA_SIZE_STR)
+ * @sval: String value (if width is CMD_DATA_SIZE_STR)
+ */
+struct expr_arg {
+ union {
+ ulong ival;
+ char *sval;
+ };
+};
+
+static int get_arg(char *s, int w, struct expr_arg *argp)
+{
+ struct expr_arg arg;
+
+ /*
+ * If the parameter starts with a '*' then assume it is a pointer to
+ * the value we want.
+ */
+ if (s[0] == '*') {
+ ulong *p;
+ ulong addr;
+ ulong val;
+ int len;
+ char *str;
+
+ addr = simple_strtoul(&s[1], NULL, 16);
+ switch (w) {
+ case 1:
+ p = map_sysmem(addr, sizeof(uchar));
+ val = (ulong)*(uchar *)p;
+ unmap_sysmem(p);
+ arg.ival = val;
+ break;
+ case 2:
+ p = map_sysmem(addr, sizeof(ushort));
+ val = (ulong)*(ushort *)p;
+ unmap_sysmem(p);
+ arg.ival = val;
+ break;
+ case CMD_DATA_SIZE_STR:
+ p = map_sysmem(addr, SZ_64K);
+
+ /* Maximum string length of 64KB plus terminator */
+ len = strnlen((char *)p, SZ_64K) + 1;
+ str = malloc(len);
+ if (!str) {
+ printf("Out of memory\n");
+ return -ENOMEM;
+ }
+ memcpy(str, p, len);
+ str[len - 1] = '\0';
+ unmap_sysmem(p);
+ arg.sval = str;
+ break;
+ case 4:
+ p = map_sysmem(addr, sizeof(u32));
+ val = *(u32 *)p;
+ unmap_sysmem(p);
+ arg.ival = val;
+ break;
+ default:
+ p = map_sysmem(addr, sizeof(ulong));
+ val = *p;
+ unmap_sysmem(p);
+ arg.ival = val;
+ break;
+ }
+ } else {
+ if (w == CMD_DATA_SIZE_STR)
+ return -EINVAL;
+ arg.ival = simple_strtoul(s, NULL, 16);
+ }
+ *argp = arg;
+
+ return 0;
+}
+
+#ifdef CONFIG_REGEX
+
+#include <slre.h>
+
+/*
+ * memstr - Find the first substring in memory
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ *
+ * Similar to and based on strstr(),
+ * but strings do not need to be NUL terminated.
+ */
+static char *memstr(const char *s1, int l1, const char *s2, int l2)
+{
+ if (!l2)
+ return (char *)s1;
+
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1, s2, l2))
+ return (char *)s1;
+ s1++;
+ }
+ return NULL;
+}
+
+/**
+ * substitute() - Substitute part of one string with another
+ *
+ * This updates @string so that the first occurrence of @old is replaced with
+ * @new
+ *
+ * @string: String buffer containing string to update at the start
+ * @slen: Pointer to current string length, updated on success
+ * @ssize: Size of string buffer
+ * @old: Old string to find in the buffer (no terminator needed)
+ * @olen: Length of @old excluding terminator
+ * @new: New string to replace @old with
+ * @nlen: Length of @new excluding terminator
+ * @return pointer to immediately after the copied @new in @string, or NULL if
+ * no replacement took place
+ */
+static char *substitute(char *string, int *slen, int ssize,
+ const char *old, int olen, const char *new, int nlen)
+{
+ char *p = memstr(string, *slen, old, olen);
+
+ if (p == NULL)
+ return NULL;
+
+ debug("## Match at pos %ld: match len %d, subst len %d\n",
+ (long)(p - string), olen, nlen);
+
+ /* make sure replacement matches */
+ if (*slen + nlen - olen > ssize) {
+ printf("## error: substitution buffer overflow\n");
+ return NULL;
+ }
+
+ /* move tail if needed */
+ if (olen != nlen) {
+ int tail, len;
+
+ len = (olen > nlen) ? olen : nlen;
+
+ tail = ssize - (p + len - string);
+
+ debug("## tail len %d\n", tail);
+
+ memmove(p + nlen, p + olen, tail);
+ }
+
+ /* insert substitute */
+ memcpy(p, new, nlen);
+
+ *slen += nlen - olen;
+
+ return p + nlen;
+}
+
+int setexpr_regex_sub(char *data, uint data_size, char *nbuf, uint nbuf_size,
+ const char *r, const char *s, bool global)
+{
+ struct slre slre;
+ char *datap = data;
+ int res, len, nlen, loop;
+
+ if (slre_compile(&slre, r) == 0) {
+ printf("Error compiling regex: %s\n", slre.err_str);
+ return 1;
+ }
+
+ len = strlen(data);
+ for (loop = 0;; loop++) {
+ struct cap caps[slre.num_caps + 2];
+ const char *old;
+ char *np;
+ int i, olen;
+
+ (void) memset(caps, 0, sizeof(caps));
+
+ res = slre_match(&slre, datap, len - (datap - data), caps);
+
+ debug("Result: %d\n", res);
+
+ for (i = 0; i <= slre.num_caps; i++) {
+ if (caps[i].len > 0) {
+ debug("Substring %d: [%.*s]\n", i,
+ caps[i].len, caps[i].ptr);
+ }
+ }
+
+ if (res == 0) {
+ if (loop == 0) {
+ printf("%s: No match\n", data);
+ return 1;
+ } else {
+ break;
+ }
+ }
+
+ debug("## MATCH ## %s\n", data);
+
+ if (!s)
+ return 1;
+
+ old = caps[0].ptr;
+ olen = caps[0].len;
+ nlen = strlen(s);
+
+ if (nlen + 1 >= nbuf_size) {
+ printf("## error: pattern buffer overflow: have %d, need %d\n",
+ nbuf_size, nlen + 1);
+ return 1;
+ }
+ strcpy(nbuf, s);
+
+ debug("## SUBST(1) ## %s\n", nbuf);
+
+ /*
+ * Handle back references
+ *
+ * Support for \0 ... \9, where \0 is the
+ * whole matched pattern (similar to &).
+ *
+ * Implementation is a bit simpleminded as
+ * backrefs are substituted sequentially, one
+ * by one. This will lead to somewhat
+ * unexpected results if the replacement
+ * strings contain any \N strings then then
+ * may get substitued, too. We accept this
+ * restriction for the sake of simplicity.
+ */
+ for (i = 0; i < 10; ++i) {
+ char backref[2] = {
+ '\\',
+ '0',
+ };
+
+ if (caps[i].len == 0)
+ break;
+
+ backref[1] += i;
+
+ debug("## BACKREF %d: replace \"%.*s\" by \"%.*s\" in \"%s\"\n",
+ i,
+ 2, backref,
+ caps[i].len, caps[i].ptr,
+ nbuf);
+
+ for (np = nbuf;;) {
+ char *p = memstr(np, nlen, backref, 2);
+
+ if (p == NULL)
+ break;
+
+ np = substitute(np, &nlen,
+ nbuf_size - (np - nbuf),
+ backref, 2,
+ caps[i].ptr, caps[i].len);
+
+ if (np == NULL)
+ return 1;
+ }
+ }
+ debug("## SUBST(2) ## %s\n", nbuf);
+
+ datap = substitute(datap, &len, data_size - (datap - data),
+ old, olen, nbuf, nlen);
+
+ if (datap == NULL)
+ return 1;
+
+ debug("## REMAINDER: %s\n", datap);
+
+ debug("## RESULT: %s\n", data);
+
+ if (!global)
+ break;
+ }
+ debug("## FINAL (now env_set()) : %s\n", data);
+
+ return 0;
+}
+
+#define SLRE_BUFSZ 16384
+#define SLRE_PATSZ 4096
+
+/*
+ * Perform regex operations on a environment variable
+ *
+ * Returns 0 if OK, 1 in case of errors.
+ */
+static int regex_sub_var(const char *name, const char *r, const char *s,
+ const char *t, int global)
+{
+ struct slre slre;
+ char data[SLRE_BUFSZ];
+ char nbuf[SLRE_PATSZ];
+ const char *value;
+ int len;
+ int ret;
+
+ if (!name)
+ return 1;
+
+ if (slre_compile(&slre, r) == 0) {
+ printf("Error compiling regex: %s\n", slre.err_str);
+ return 1;
+ }
+
+ if (!t) {
+ value = env_get(name);
+ if (!value) {
+ printf("## Error: variable \"%s\" not defined\n", name);
+ return 1;
+ }
+ t = value;
+ }
+
+ debug("REGEX on %s=%s\n", name, t);
+ debug("REGEX=\"%s\", SUBST=\"%s\", GLOBAL=%d\n", r, s ? s : "<NULL>",
+ global);
+
+ len = strlen(t);
+ if (len + 1 > SLRE_BUFSZ) {
+ printf("## error: subst buffer overflow: have %d, need %d\n",
+ SLRE_BUFSZ, len + 1);
+ return 1;
+ }
+
+ strcpy(data, t);
+
+ ret = setexpr_regex_sub(data, SLRE_BUFSZ, nbuf, SLRE_PATSZ, r, s,
+ global);
+ if (ret)
+ return 1;
+
+ printf("%s=%s\n", name, data);
+
+ return env_set(name, data);
+}
+#endif
+
+static int do_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct expr_arg aval, bval;
+ ulong value;
+ int ret = 0;
+ int w;
+
+ /*
+ * We take 3, 5, or 6 arguments:
+ * 3 : setexpr name value
+ * 5 : setexpr name val1 op val2
+ * setexpr name [g]sub r s
+ * 6 : setexpr name [g]sub r s t
+ */
+
+ /* > 6 already tested by max command args */
+ if ((argc < 3) || (argc == 4))
+ return CMD_RET_USAGE;
+
+ w = cmd_get_data_size(argv[0], 4);
+
+ if (get_arg(argv[2], w, &aval))
+ return CMD_RET_FAILURE;
+
+ /* plain assignment: "setexpr name value" */
+ if (argc == 3) {
+ if (w == CMD_DATA_SIZE_STR) {
+ ret = env_set(argv[1], aval.sval);
+ free(aval.sval);
+ } else {
+ ret = env_set_hex(argv[1], aval.ival);
+ }
+
+ return ret;
+ }
+
+ /* 5 or 6 args (6 args only with [g]sub) */
+#ifdef CONFIG_REGEX
+ /*
+ * rexep handling: "setexpr name [g]sub r s [t]"
+ * with 5 args, "t" will be NULL
+ */
+ if (strcmp(argv[2], "gsub") == 0)
+ return regex_sub_var(argv[1], argv[3], argv[4], argv[5], 1);
+
+ if (strcmp(argv[2], "sub") == 0)
+ return regex_sub_var(argv[1], argv[3], argv[4], argv[5], 0);
+#endif
+
+ /* standard operators: "setexpr name val1 op val2" */
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ if (strlen(argv[3]) != 1)
+ return CMD_RET_USAGE;
+
+ if (get_arg(argv[4], w, &bval)) {
+ if (w == CMD_DATA_SIZE_STR)
+ free(aval.sval);
+ return CMD_RET_FAILURE;
+ }
+
+ if (w == CMD_DATA_SIZE_STR) {
+ int len;
+ char *str;
+
+ switch (argv[3][0]) {
+ case '+':
+ len = strlen(aval.sval) + strlen(bval.sval) + 1;
+ str = malloc(len);
+ if (!str) {
+ printf("Out of memory\n");
+ ret = CMD_RET_FAILURE;
+ } else {
+ /* These were copied out and checked earlier */
+ strcpy(str, aval.sval);
+ strcat(str, bval.sval);
+ ret = env_set(argv[1], str);
+ if (ret)
+ printf("Could not set var\n");
+ free(str);
+ }
+ break;
+ default:
+ printf("invalid op\n");
+ ret = 1;
+ }
+ } else {
+ ulong a = aval.ival;
+ ulong b = bval.ival;
+
+ switch (argv[3][0]) {
+ case '|':
+ value = a | b;
+ break;
+ case '&':
+ value = a & b;
+ break;
+ case '+':
+ value = a + b;
+ break;
+ case '^':
+ value = a ^ b;
+ break;
+ case '-':
+ value = a - b;
+ break;
+ case '*':
+ value = a * b;
+ break;
+ case '/':
+ value = a / b;
+ break;
+ case '%':
+ value = a % b;
+ break;
+ default:
+ printf("invalid op\n");
+ return 1;
+ }
+
+ env_set_hex(argv[1], value);
+ }
+
+ if (w == CMD_DATA_SIZE_STR) {
+ free(aval.sval);
+ free(bval.sval);
+ }
+
+ return ret;
+}
+
+U_BOOT_CMD(
+ setexpr, 6, 0, do_setexpr,
+ "set environment variable as the result of eval expression",
+ "[.b, .w, .l, .s] name [*]value1 <op> [*]value2\n"
+ " - set environment variable 'name' to the result of the evaluated\n"
+ " expression specified by <op>. <op> can be &, |, ^, +, -, *, /, %\n"
+ " (for strings only + is supported)\n"
+ " size argument is only meaningful if value1 and/or value2 are\n"
+ " memory addresses (*)\n"
+ "setexpr[.b, .w, .l] name [*]value\n"
+ " - load a value into a variable"
+#ifdef CONFIG_REGEX
+ "\n"
+ "setexpr name gsub r s [t]\n"
+ " - For each substring matching the regular expression <r> in the\n"
+ " string <t>, substitute the string <s>. The result is\n"
+ " assigned to <name>. If <t> is not supplied, use the old\n"
+ " value of <name>\n"
+ "setexpr name sub r s [t]\n"
+ " - Just like gsub(), but replace only the first matching substring"
+#endif
+);
diff --git a/roms/u-boot/cmd/sf.c b/roms/u-boot/cmd/sf.c
new file mode 100644
index 000000000..46346fb9d
--- /dev/null
+++ b/roms/u-boot/cmd/sf.c
@@ -0,0 +1,627 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Command for accessing SPI flash.
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ */
+
+#include <common.h>
+#include <command.h>
+#include <div64.h>
+#include <dm.h>
+#include <flash.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <asm/cache.h>
+#include <jffs2/jffs2.h>
+#include <linux/mtd/mtd.h>
+
+#include <asm/io.h>
+#include <dm/device-internal.h>
+
+#include "legacy-mtd-utils.h"
+
+static struct spi_flash *flash;
+
+/*
+ * This function computes the length argument for the erase command.
+ * The length on which the command is to operate can be given in two forms:
+ * 1. <cmd> offset len - operate on <'offset', 'len')
+ * 2. <cmd> offset +len - operate on <'offset', 'round_up(len)')
+ * If the second form is used and the length doesn't fall on the
+ * sector boundary, than it will be adjusted to the next sector boundary.
+ * If it isn't in the flash, the function will fail (return -1).
+ * Input:
+ * arg: length specification (i.e. both command arguments)
+ * Output:
+ * len: computed length for operation
+ * Return:
+ * 1: success
+ * -1: failure (bad format, bad address).
+ */
+static int sf_parse_len_arg(char *arg, ulong *len)
+{
+ char *ep;
+ char round_up_len; /* indicates if the "+length" form used */
+ ulong len_arg;
+
+ round_up_len = 0;
+ if (*arg == '+') {
+ round_up_len = 1;
+ ++arg;
+ }
+
+ len_arg = simple_strtoul(arg, &ep, 16);
+ if (ep == arg || *ep != '\0')
+ return -1;
+
+ if (round_up_len && flash->sector_size > 0)
+ *len = ROUND(len_arg, flash->sector_size);
+ else
+ *len = len_arg;
+
+ return 1;
+}
+
+/**
+ * This function takes a byte length and a delta unit of time to compute the
+ * approximate bytes per second
+ *
+ * @param len amount of bytes currently processed
+ * @param start_ms start time of processing in ms
+ * @return bytes per second if OK, 0 on error
+ */
+static ulong bytes_per_second(unsigned int len, ulong start_ms)
+{
+ /* less accurate but avoids overflow */
+ if (len >= ((unsigned int) -1) / 1024)
+ return len / (max(get_timer(start_ms) / 1024, 1UL));
+ else
+ return 1024 * len / max(get_timer(start_ms), 1UL);
+}
+
+static int do_spi_flash_probe(int argc, char *const argv[])
+{
+ unsigned int bus = CONFIG_SF_DEFAULT_BUS;
+ unsigned int cs = CONFIG_SF_DEFAULT_CS;
+ /* In DM mode, defaults speed and mode will be taken from DT */
+ unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
+ unsigned int mode = CONFIG_SF_DEFAULT_MODE;
+ char *endp;
+#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
+ struct udevice *new, *bus_dev;
+ int ret;
+#else
+ struct spi_flash *new;
+#endif
+
+ if (argc >= 2) {
+ cs = simple_strtoul(argv[1], &endp, 0);
+ if (*argv[1] == 0 || (*endp != 0 && *endp != ':'))
+ return -1;
+ if (*endp == ':') {
+ if (endp[1] == 0)
+ return -1;
+
+ bus = cs;
+ cs = simple_strtoul(endp + 1, &endp, 0);
+ if (*endp != 0)
+ return -1;
+ }
+ }
+
+ if (argc >= 3) {
+ speed = simple_strtoul(argv[2], &endp, 0);
+ if (*argv[2] == 0 || *endp != 0)
+ return -1;
+ }
+ if (argc >= 4) {
+ mode = simple_strtoul(argv[3], &endp, 16);
+ if (*argv[3] == 0 || *endp != 0)
+ return -1;
+ }
+
+#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
+ /* Remove the old device, otherwise probe will just be a nop */
+ ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new);
+ if (!ret) {
+ device_remove(new, DM_REMOVE_NORMAL);
+ }
+ flash = NULL;
+ ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new);
+ if (ret) {
+ printf("Failed to initialize SPI flash at %u:%u (error %d)\n",
+ bus, cs, ret);
+ return 1;
+ }
+
+ flash = dev_get_uclass_priv(new);
+#else
+ if (flash)
+ spi_flash_free(flash);
+
+ new = spi_flash_probe(bus, cs, speed, mode);
+ flash = new;
+ if (!new) {
+ printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+/**
+ * Write a block of data to SPI flash, first checking if it is different from
+ * what is already there.
+ *
+ * If the data being written is the same, then *skipped is incremented by len.
+ *
+ * @param flash flash context pointer
+ * @param offset flash offset to write
+ * @param len number of bytes to write
+ * @param buf buffer to write from
+ * @param cmp_buf read buffer to use to compare data
+ * @param skipped Count of skipped data (incremented by this function)
+ * @return NULL if OK, else a string containing the stage which failed
+ */
+static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
+ size_t len, const char *buf, char *cmp_buf, size_t *skipped)
+{
+ char *ptr = (char *)buf;
+
+ debug("offset=%#x, sector_size=%#x, len=%#zx\n",
+ offset, flash->sector_size, len);
+ /* Read the entire sector so to allow for rewriting */
+ if (spi_flash_read(flash, offset, flash->sector_size, cmp_buf))
+ return "read";
+ /* Compare only what is meaningful (len) */
+ if (memcmp(cmp_buf, buf, len) == 0) {
+ debug("Skip region %x size %zx: no change\n",
+ offset, len);
+ *skipped += len;
+ return NULL;
+ }
+ /* Erase the entire sector */
+ if (spi_flash_erase(flash, offset, flash->sector_size))
+ return "erase";
+ /* If it's a partial sector, copy the data into the temp-buffer */
+ if (len != flash->sector_size) {
+ memcpy(cmp_buf, buf, len);
+ ptr = cmp_buf;
+ }
+ /* Write one complete sector */
+ if (spi_flash_write(flash, offset, flash->sector_size, ptr))
+ return "write";
+
+ return NULL;
+}
+
+/**
+ * Update an area of SPI flash by erasing and writing any blocks which need
+ * to change. Existing blocks with the correct data are left unchanged.
+ *
+ * @param flash flash context pointer
+ * @param offset flash offset to write
+ * @param len number of bytes to write
+ * @param buf buffer to write from
+ * @return 0 if ok, 1 on error
+ */
+static int spi_flash_update(struct spi_flash *flash, u32 offset,
+ size_t len, const char *buf)
+{
+ const char *err_oper = NULL;
+ char *cmp_buf;
+ const char *end = buf + len;
+ size_t todo; /* number of bytes to do in this pass */
+ size_t skipped = 0; /* statistics */
+ const ulong start_time = get_timer(0);
+ size_t scale = 1;
+ const char *start_buf = buf;
+ ulong delta;
+
+ if (end - buf >= 200)
+ scale = (end - buf) / 100;
+ cmp_buf = memalign(ARCH_DMA_MINALIGN, flash->sector_size);
+ if (cmp_buf) {
+ ulong last_update = get_timer(0);
+
+ for (; buf < end && !err_oper; buf += todo, offset += todo) {
+ todo = min_t(size_t, end - buf, flash->sector_size);
+ if (get_timer(last_update) > 100) {
+ printf(" \rUpdating, %zu%% %lu B/s",
+ 100 - (end - buf) / scale,
+ bytes_per_second(buf - start_buf,
+ start_time));
+ last_update = get_timer(0);
+ }
+ err_oper = spi_flash_update_block(flash, offset, todo,
+ buf, cmp_buf, &skipped);
+ }
+ } else {
+ err_oper = "malloc";
+ }
+ free(cmp_buf);
+ putc('\r');
+ if (err_oper) {
+ printf("SPI flash failed in %s step\n", err_oper);
+ return 1;
+ }
+
+ delta = get_timer(start_time);
+ printf("%zu bytes written, %zu bytes skipped", len - skipped,
+ skipped);
+ printf(" in %ld.%lds, speed %ld B/s\n",
+ delta / 1000, delta % 1000, bytes_per_second(len, start_time));
+
+ return 0;
+}
+
+static int do_spi_flash_read_write(int argc, char *const argv[])
+{
+ unsigned long addr;
+ void *buf;
+ char *endp;
+ int ret = 1;
+ int dev = 0;
+ loff_t offset, len, maxsize;
+
+ if (argc < 3)
+ return -1;
+
+ addr = simple_strtoul(argv[1], &endp, 16);
+ if (*argv[1] == 0 || *endp != 0)
+ return -1;
+
+ if (mtd_arg_off_size(argc - 2, &argv[2], &dev, &offset, &len,
+ &maxsize, MTD_DEV_TYPE_NOR, flash->size))
+ return -1;
+
+ /* Consistency checking */
+ if (offset + len > flash->size) {
+ printf("ERROR: attempting %s past flash size (%#x)\n",
+ argv[0], flash->size);
+ return 1;
+ }
+
+ buf = map_physmem(addr, len, MAP_WRBACK);
+ if (!buf && addr) {
+ puts("Failed to map physical memory\n");
+ return 1;
+ }
+
+ if (strcmp(argv[0], "update") == 0) {
+ ret = spi_flash_update(flash, offset, len, buf);
+ } else if (strncmp(argv[0], "read", 4) == 0 ||
+ strncmp(argv[0], "write", 5) == 0) {
+ int read;
+
+ read = strncmp(argv[0], "read", 4) == 0;
+ if (read)
+ ret = spi_flash_read(flash, offset, len, buf);
+ else
+ ret = spi_flash_write(flash, offset, len, buf);
+
+ printf("SF: %zu bytes @ %#x %s: ", (size_t)len, (u32)offset,
+ read ? "Read" : "Written");
+ if (ret)
+ printf("ERROR %d\n", ret);
+ else
+ printf("OK\n");
+ }
+
+ unmap_physmem(buf, len);
+
+ return ret == 0 ? 0 : 1;
+}
+
+static int do_spi_flash_erase(int argc, char *const argv[])
+{
+ int ret;
+ int dev = 0;
+ loff_t offset, len, maxsize;
+ ulong size;
+
+ if (argc < 3)
+ return -1;
+
+ if (mtd_arg_off(argv[1], &dev, &offset, &len, &maxsize,
+ MTD_DEV_TYPE_NOR, flash->size))
+ return -1;
+
+ ret = sf_parse_len_arg(argv[2], &size);
+ if (ret != 1)
+ return -1;
+
+ /* Consistency checking */
+ if (offset + size > flash->size) {
+ printf("ERROR: attempting %s past flash size (%#x)\n",
+ argv[0], flash->size);
+ return 1;
+ }
+
+ ret = spi_flash_erase(flash, offset, size);
+ printf("SF: %zu bytes @ %#x Erased: ", (size_t)size, (u32)offset);
+ if (ret)
+ printf("ERROR %d\n", ret);
+ else
+ printf("OK\n");
+
+ return ret == 0 ? 0 : 1;
+}
+
+static int do_spi_protect(int argc, char *const argv[])
+{
+ int ret = 0;
+ loff_t start, len;
+ bool prot = false;
+
+ if (argc != 4)
+ return -1;
+
+ if (!str2off(argv[2], &start)) {
+ puts("start sector is not a valid number\n");
+ return 1;
+ }
+
+ if (!str2off(argv[3], &len)) {
+ puts("len is not a valid number\n");
+ return 1;
+ }
+
+ if (strcmp(argv[1], "lock") == 0)
+ prot = true;
+ else if (strcmp(argv[1], "unlock") == 0)
+ prot = false;
+ else
+ return -1; /* Unknown parameter */
+
+ ret = spi_flash_protect(flash, start, len, prot);
+
+ return ret == 0 ? 0 : 1;
+}
+
+#ifdef CONFIG_CMD_SF_TEST
+enum {
+ STAGE_ERASE,
+ STAGE_CHECK,
+ STAGE_WRITE,
+ STAGE_READ,
+
+ STAGE_COUNT,
+};
+
+static char *stage_name[STAGE_COUNT] = {
+ "erase",
+ "check",
+ "write",
+ "read",
+};
+
+struct test_info {
+ int stage;
+ int bytes;
+ unsigned base_ms;
+ unsigned time_ms[STAGE_COUNT];
+};
+
+static void show_time(struct test_info *test, int stage)
+{
+ uint64_t speed; /* KiB/s */
+ int bps; /* Bits per second */
+
+ speed = (long long)test->bytes * 1000;
+ if (test->time_ms[stage])
+ do_div(speed, test->time_ms[stage] * 1024);
+ bps = speed * 8;
+
+ printf("%d %s: %u ticks, %d KiB/s %d.%03d Mbps\n", stage,
+ stage_name[stage], test->time_ms[stage],
+ (int)speed, bps / 1000, bps % 1000);
+}
+
+static void spi_test_next_stage(struct test_info *test)
+{
+ test->time_ms[test->stage] = get_timer(test->base_ms);
+ show_time(test, test->stage);
+ test->base_ms = get_timer(0);
+ test->stage++;
+}
+
+/**
+ * Run a test on the SPI flash
+ *
+ * @param flash SPI flash to use
+ * @param buf Source buffer for data to write
+ * @param len Size of data to read/write
+ * @param offset Offset within flash to check
+ * @param vbuf Verification buffer
+ * @return 0 if ok, -1 on error
+ */
+static int spi_flash_test(struct spi_flash *flash, uint8_t *buf, ulong len,
+ ulong offset, uint8_t *vbuf)
+{
+ struct test_info test;
+ int err, i;
+
+ printf("SPI flash test:\n");
+ memset(&test, '\0', sizeof(test));
+ test.base_ms = get_timer(0);
+ test.bytes = len;
+ err = spi_flash_erase(flash, offset, len);
+ if (err) {
+ printf("Erase failed (err = %d)\n", err);
+ return -1;
+ }
+ spi_test_next_stage(&test);
+
+ err = spi_flash_read(flash, offset, len, vbuf);
+ if (err) {
+ printf("Check read failed (err = %d)\n", err);
+ return -1;
+ }
+ for (i = 0; i < len; i++) {
+ if (vbuf[i] != 0xff) {
+ printf("Check failed at %d\n", i);
+ print_buffer(i, vbuf + i, 1,
+ min_t(uint, len - i, 0x40), 0);
+ return -1;
+ }
+ }
+ spi_test_next_stage(&test);
+
+ err = spi_flash_write(flash, offset, len, buf);
+ if (err) {
+ printf("Write failed (err = %d)\n", err);
+ return -1;
+ }
+ memset(vbuf, '\0', len);
+ spi_test_next_stage(&test);
+
+ err = spi_flash_read(flash, offset, len, vbuf);
+ if (err) {
+ printf("Read failed (ret = %d)\n", err);
+ return -1;
+ }
+ spi_test_next_stage(&test);
+
+ for (i = 0; i < len; i++) {
+ if (buf[i] != vbuf[i]) {
+ printf("Verify failed at %d, good data:\n", i);
+ print_buffer(i, buf + i, 1,
+ min_t(uint, len - i, 0x40), 0);
+ printf("Bad data:\n");
+ print_buffer(i, vbuf + i, 1,
+ min_t(uint, len - i, 0x40), 0);
+ return -1;
+ }
+ }
+ printf("Test passed\n");
+ for (i = 0; i < STAGE_COUNT; i++)
+ show_time(&test, i);
+
+ return 0;
+}
+
+static int do_spi_flash_test(int argc, char *const argv[])
+{
+ unsigned long offset;
+ unsigned long len;
+ uint8_t *buf, *from;
+ char *endp;
+ uint8_t *vbuf;
+ int ret;
+
+ if (argc < 3)
+ return -1;
+ offset = simple_strtoul(argv[1], &endp, 16);
+ if (*argv[1] == 0 || *endp != 0)
+ return -1;
+ len = simple_strtoul(argv[2], &endp, 16);
+ if (*argv[2] == 0 || *endp != 0)
+ return -1;
+
+ vbuf = memalign(ARCH_DMA_MINALIGN, len);
+ if (!vbuf) {
+ printf("Cannot allocate memory (%lu bytes)\n", len);
+ return 1;
+ }
+ buf = memalign(ARCH_DMA_MINALIGN, len);
+ if (!buf) {
+ free(vbuf);
+ printf("Cannot allocate memory (%lu bytes)\n", len);
+ return 1;
+ }
+
+ from = map_sysmem(CONFIG_SYS_TEXT_BASE, 0);
+ memcpy(buf, from, len);
+ ret = spi_flash_test(flash, buf, len, offset, vbuf);
+ free(vbuf);
+ free(buf);
+ if (ret) {
+ printf("Test failed\n");
+ return 1;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_CMD_SF_TEST */
+
+static int do_spi_flash(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *cmd;
+ int ret;
+
+ /* need at least two arguments */
+ if (argc < 2)
+ goto usage;
+
+ cmd = argv[1];
+ --argc;
+ ++argv;
+
+ if (strcmp(cmd, "probe") == 0) {
+ ret = do_spi_flash_probe(argc, argv);
+ goto done;
+ }
+
+ /* The remaining commands require a selected device */
+ if (!flash) {
+ puts("No SPI flash selected. Please run `sf probe'\n");
+ return 1;
+ }
+
+ if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0 ||
+ strcmp(cmd, "update") == 0)
+ ret = do_spi_flash_read_write(argc, argv);
+ else if (strcmp(cmd, "erase") == 0)
+ ret = do_spi_flash_erase(argc, argv);
+ else if (strcmp(cmd, "protect") == 0)
+ ret = do_spi_protect(argc, argv);
+#ifdef CONFIG_CMD_SF_TEST
+ else if (!strcmp(cmd, "test"))
+ ret = do_spi_flash_test(argc, argv);
+#endif
+ else
+ ret = -1;
+
+done:
+ if (ret != -1)
+ return ret;
+
+usage:
+ return CMD_RET_USAGE;
+}
+
+#ifdef CONFIG_CMD_SF_TEST
+#define SF_TEST_HELP "\nsf test offset len " \
+ "- run a very basic destructive test"
+#else
+#define SF_TEST_HELP
+#endif
+
+U_BOOT_CMD(
+ sf, 5, 1, do_spi_flash,
+ "SPI flash sub-system",
+ "probe [[bus:]cs] [hz] [mode] - init flash device on given SPI bus\n"
+ " and chip select\n"
+ "sf read addr offset|partition len - read `len' bytes starting at\n"
+ " `offset' or from start of mtd\n"
+ " `partition'to memory at `addr'\n"
+ "sf write addr offset|partition len - write `len' bytes from memory\n"
+ " at `addr' to flash at `offset'\n"
+ " or to start of mtd `partition'\n"
+ "sf erase offset|partition [+]len - erase `len' bytes from `offset'\n"
+ " or from start of mtd `partition'\n"
+ " `+len' round up `len' to block size\n"
+ "sf update addr offset|partition len - erase and write `len' bytes from memory\n"
+ " at `addr' to flash at `offset'\n"
+ " or to start of mtd `partition'\n"
+ "sf protect lock/unlock sector len - protect/unprotect 'len' bytes starting\n"
+ " at address 'sector'\n"
+ SF_TEST_HELP
+);
diff --git a/roms/u-boot/cmd/sha1sum.c b/roms/u-boot/cmd/sha1sum.c
new file mode 100644
index 000000000..bcc665a5a
--- /dev/null
+++ b/roms/u-boot/cmd/sha1sum.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011
+ * Joe Hershberger, National Instruments, joe.hershberger@ni.com
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <hash.h>
+#include <u-boot/sha1.h>
+
+int do_sha1sum(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int flags = HASH_FLAG_ENV;
+ int ac;
+ char * const *av;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ av = argv + 1;
+ ac = argc - 1;
+#ifdef CONFIG_SHA1SUM_VERIFY
+ if (strcmp(*av, "-v") == 0) {
+ flags |= HASH_FLAG_VERIFY;
+ av++;
+ ac--;
+ }
+#endif
+
+ return hash_command("sha1", flags, cmdtp, flag, ac, av);
+}
+
+#ifdef CONFIG_SHA1SUM_VERIFY
+U_BOOT_CMD(
+ sha1sum, 5, 1, do_sha1sum,
+ "compute SHA1 message digest",
+ "address count [[*]sum]\n"
+ " - compute SHA1 message digest [save to sum]\n"
+ "sha1sum -v address count [*]sum\n"
+ " - verify sha1sum of memory area"
+);
+#else
+U_BOOT_CMD(
+ sha1sum, 4, 1, do_sha1sum,
+ "compute SHA1 message digest",
+ "address count [[*]sum]\n"
+ " - compute SHA1 message digest [save to sum]"
+);
+#endif
diff --git a/roms/u-boot/cmd/sleep.c b/roms/u-boot/cmd/sleep.c
new file mode 100644
index 000000000..1fff400c7
--- /dev/null
+++ b/roms/u-boot/cmd/sleep.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <linux/delay.h>
+
+static int do_sleep(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong start = get_timer(0);
+ ulong mdelay = 0;
+ ulong delay;
+ char *frpart;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ delay = simple_strtoul(argv[1], NULL, 10) * CONFIG_SYS_HZ;
+
+ frpart = strchr(argv[1], '.');
+
+ if (frpart) {
+ uint mult = CONFIG_SYS_HZ / 10;
+ for (frpart++; *frpart != '\0' && mult > 0; frpart++) {
+ if (*frpart < '0' || *frpart > '9') {
+ mdelay = 0;
+ break;
+ }
+ mdelay += (*frpart - '0') * mult;
+ mult /= 10;
+ }
+ }
+
+ delay += mdelay;
+
+ while (get_timer(start) < delay) {
+ if (ctrlc())
+ return CMD_RET_FAILURE;
+
+ udelay(100);
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ sleep , 2, 1, do_sleep,
+ "delay execution for some time",
+ "N\n"
+ " - delay execution for N seconds (N is _decimal_ and can be\n"
+ " fractional)"
+);
diff --git a/roms/u-boot/cmd/smccc.c b/roms/u-boot/cmd/smccc.c
new file mode 100644
index 000000000..0b19f6c68
--- /dev/null
+++ b/roms/u-boot/cmd/smccc.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018
+ * Michalis Pappas <mpappas@fastmail.fm>
+ */
+#include <asm/psci.h>
+#include <common.h>
+#include <command.h>
+#include <linux/arm-smccc.h>
+#include <linux/compiler.h>
+#include <linux/psci.h>
+
+static int do_call(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct arm_smccc_res res;
+
+ unsigned long fid;
+
+ unsigned long a1;
+ unsigned long a2;
+ unsigned long a3;
+ unsigned long a4;
+ unsigned long a5;
+ unsigned long a6;
+ unsigned long a7;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ fid = simple_strtoul(argv[1], NULL, 16);
+
+ a1 = argc > 2 ? simple_strtoul(argv[2], NULL, 16) : 0;
+ a2 = argc > 3 ? simple_strtoul(argv[3], NULL, 16) : 0;
+ a3 = argc > 4 ? simple_strtoul(argv[4], NULL, 16) : 0;
+ a4 = argc > 5 ? simple_strtoul(argv[5], NULL, 16) : 0;
+ a5 = argc > 6 ? simple_strtoul(argv[6], NULL, 16) : 0;
+ a6 = argc > 7 ? simple_strtoul(argv[7], NULL, 16) : 0;
+ a7 = argc > 8 ? simple_strtoul(argv[8], NULL, 16) : 0;
+
+ if (!strcmp(argv[0], "smc"))
+ arm_smccc_smc(fid, a1, a2, a3, a4, a5, a6, a7, &res);
+ else
+ arm_smccc_hvc(fid, a1, a2, a3, a4, a5, a6, a7, &res);
+
+ printf("Res: %ld %ld %ld %ld\n", res.a0, res.a1, res.a2, res.a3);
+
+ return 0;
+}
+
+#ifdef CONFIG_CMD_SMC
+U_BOOT_CMD(
+ smc, 8, 2, do_call,
+ "Issue a Secure Monitor Call",
+ "<fid> [arg1 ... arg6] [id]\n"
+ " - fid Function ID\n"
+ " - arg SMC arguments, passed to X1-X6 (default to zero)\n"
+ " - id Secure OS ID / Session ID, passed to W7 (defaults to zero)\n"
+);
+#endif
+
+#ifdef CONFIG_CMD_HVC
+U_BOOT_CMD(
+ hvc, 8, 2, do_call,
+ "Issue a Hypervisor Call",
+ "<fid> [arg1...arg7] [id]\n"
+ " - fid Function ID\n"
+ " - arg HVC arguments, passed to X1-X6 (default to zero)\n"
+ " - id Session ID, passed to W7 (defaults to zero)\n"
+);
+#endif
+
diff --git a/roms/u-boot/cmd/sound.c b/roms/u-boot/cmd/sound.c
new file mode 100644
index 000000000..fdcde3653
--- /dev/null
+++ b/roms/u-boot/cmd/sound.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Rajeshwari Shinde <rajeshwari.s@samsung.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <sound.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Initilaise sound subsystem */
+static int do_init(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_SOUND, &dev);
+ if (!ret)
+ ret = sound_setup(dev);
+ if (ret) {
+ printf("Initialise Audio driver failed (ret=%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
+/* play sound from buffer */
+static int do_play(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int ret = 0;
+ int msec = 1000;
+ int freq = 400;
+
+ if (argc > 1)
+ msec = simple_strtoul(argv[1], NULL, 10);
+ if (argc > 2)
+ freq = simple_strtoul(argv[2], NULL, 10);
+
+ ret = uclass_first_device_err(UCLASS_SOUND, &dev);
+ if (!ret)
+ ret = sound_beep(dev, msec, freq);
+ if (ret) {
+ printf("Sound device failed to play (err=%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_sound_sub[] = {
+ U_BOOT_CMD_MKENT(init, 0, 1, do_init, "", ""),
+ U_BOOT_CMD_MKENT(play, 2, 1, do_play, "", ""),
+};
+
+/* process sound command */
+static int do_sound(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c;
+
+ if (argc < 1)
+ return CMD_RET_USAGE;
+
+ /* Strip off leading 'sound' command argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], &cmd_sound_sub[0], ARRAY_SIZE(cmd_sound_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+ sound, 4, 1, do_sound,
+ "sound sub-system",
+ "init - initialise the sound driver\n"
+ "sound play [len] [freq] - play a sound for len ms at freq hz\n"
+);
diff --git a/roms/u-boot/cmd/source.c b/roms/u-boot/cmd/source.c
new file mode 100644
index 000000000..71f71528a
--- /dev/null
+++ b/roms/u-boot/cmd/source.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2001
+ * Kyle Harris, kharris@nexus-tech.net
+ */
+
+/*
+ * The "source" command allows to define "script images", i. e. files
+ * that contain command sequences that can be executed by the command
+ * interpreter. It returns the exit status of the last command
+ * executed from the script. This is very similar to running a shell
+ * script in a UNIX shell, hence the name for the command.
+ */
+
+/* #define DEBUG */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <log.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_FIT)
+/**
+ * get_default_image() - Return default property from /images
+ *
+ * Return: Pointer to value of default property (or NULL)
+ */
+static const char *get_default_image(const void *fit)
+{
+ int images_noffset;
+
+ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+ if (images_noffset < 0)
+ return NULL;
+
+ return fdt_getprop(fit, images_noffset, FIT_DEFAULT_PROP, NULL);
+}
+#endif
+
+int image_source_script(ulong addr, const char *fit_uname)
+{
+ ulong len;
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ const image_header_t *hdr;
+#endif
+ u32 *data;
+ int verify;
+ void *buf;
+#if defined(CONFIG_FIT)
+ const void* fit_hdr;
+ int noffset;
+ const void *fit_data;
+ size_t fit_len;
+#endif
+
+ verify = env_get_yesno("verify");
+
+ buf = map_sysmem(addr, 0);
+ switch (genimg_get_format(buf)) {
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ case IMAGE_FORMAT_LEGACY:
+ hdr = buf;
+
+ if (!image_check_magic (hdr)) {
+ puts ("Bad magic number\n");
+ return 1;
+ }
+
+ if (!image_check_hcrc (hdr)) {
+ puts ("Bad header crc\n");
+ return 1;
+ }
+
+ if (verify) {
+ if (!image_check_dcrc (hdr)) {
+ puts ("Bad data crc\n");
+ return 1;
+ }
+ }
+
+ if (!image_check_type (hdr, IH_TYPE_SCRIPT)) {
+ puts ("Bad image type\n");
+ return 1;
+ }
+
+ /* get length of script */
+ data = (u32 *)image_get_data (hdr);
+
+ if ((len = uimage_to_cpu (*data)) == 0) {
+ puts ("Empty Script\n");
+ return 1;
+ }
+
+ /*
+ * scripts are just multi-image files with one component, seek
+ * past the zero-terminated sequence of image lengths to get
+ * to the actual image data
+ */
+ while (*data++);
+ break;
+#endif
+#if defined(CONFIG_FIT)
+ case IMAGE_FORMAT_FIT:
+ fit_hdr = buf;
+ if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
+ puts ("Bad FIT image format\n");
+ return 1;
+ }
+
+ if (!fit_uname)
+ fit_uname = get_default_image(fit_hdr);
+
+ if (!fit_uname) {
+ puts("No FIT subimage unit name\n");
+ return 1;
+ }
+
+ /* get script component image node offset */
+ noffset = fit_image_get_node (fit_hdr, fit_uname);
+ if (noffset < 0) {
+ printf ("Can't find '%s' FIT subimage\n", fit_uname);
+ return 1;
+ }
+
+ if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) {
+ puts ("Not a image image\n");
+ return 1;
+ }
+
+ /* verify integrity */
+ if (verify) {
+ if (!fit_image_verify(fit_hdr, noffset)) {
+ puts ("Bad Data Hash\n");
+ return 1;
+ }
+ }
+
+ /* get script subimage data address and length */
+ if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) {
+ puts ("Could not find script subimage data\n");
+ return 1;
+ }
+
+ data = (u32 *)fit_data;
+ len = (ulong)fit_len;
+ break;
+#endif
+ default:
+ puts ("Wrong image format for \"source\" command\n");
+ return 1;
+ }
+
+ debug("** Script length: %ld\n", len);
+ return run_command_list((char *)data, len, 0);
+}
+
+/**************************************************/
+#if defined(CONFIG_CMD_SOURCE)
+static int do_source(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong addr;
+ int rcode;
+ const char *fit_uname = NULL;
+
+ /* Find script image */
+ if (argc < 2) {
+ addr = CONFIG_SYS_LOAD_ADDR;
+ debug("* source: default load address = 0x%08lx\n", addr);
+#if defined(CONFIG_FIT)
+ } else if (fit_parse_subimage(argv[1], image_load_addr, &addr,
+ &fit_uname)) {
+ debug("* source: subimage '%s' from FIT image at 0x%08lx\n",
+ fit_uname, addr);
+#endif
+ } else {
+ addr = simple_strtoul(argv[1], NULL, 16);
+ debug("* source: cmdline image address = 0x%08lx\n", addr);
+ }
+
+ printf ("## Executing script at %08lx\n", addr);
+ rcode = image_source_script(addr, fit_uname);
+ return rcode;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char source_help_text[] =
+ "[addr]\n"
+ "\t- run script starting at addr\n"
+ "\t- A valid image header must be present"
+#if defined(CONFIG_FIT)
+ "\n"
+ "For FIT format uImage addr must include subimage\n"
+ "unit name in the form of addr:<subimg_uname>"
+#endif
+ "";
+#endif
+
+U_BOOT_CMD(
+ source, 2, 0, do_source,
+ "run script from memory", source_help_text
+);
+#endif
diff --git a/roms/u-boot/cmd/spi.c b/roms/u-boot/cmd/spi.c
new file mode 100644
index 000000000..4aea19141
--- /dev/null
+++ b/roms/u-boot/cmd/spi.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2002
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ */
+
+/*
+ * SPI Read/Write Utilities
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <errno.h>
+#include <spi.h>
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+#ifndef MAX_SPI_BYTES
+# define MAX_SPI_BYTES 32 /* Maximum number of bytes we can handle */
+#endif
+
+/*
+ * Values from last command.
+ */
+static unsigned int bus;
+static unsigned int cs;
+static unsigned int mode;
+static unsigned int freq;
+static int bitlen;
+static uchar dout[MAX_SPI_BYTES];
+static uchar din[MAX_SPI_BYTES];
+
+static int do_spi_xfer(int bus, int cs)
+{
+ struct spi_slave *slave;
+ int ret = 0;
+
+#if CONFIG_IS_ENABLED(DM_SPI)
+ char name[30], *str;
+ struct udevice *dev;
+
+ snprintf(name, sizeof(name), "generic_%d:%d", bus, cs);
+ str = strdup(name);
+ if (!str)
+ return -ENOMEM;
+ ret = spi_get_bus_and_cs(bus, cs, freq, mode, "spi_generic_drv",
+ str, &dev, &slave);
+ if (ret)
+ return ret;
+#else
+ slave = spi_setup_slave(bus, cs, freq, mode);
+ if (!slave) {
+ printf("Invalid device %d:%d\n", bus, cs);
+ return -EINVAL;
+ }
+#endif
+
+ ret = spi_claim_bus(slave);
+ if (ret)
+ goto done;
+ ret = spi_xfer(slave, bitlen, dout, din,
+ SPI_XFER_BEGIN | SPI_XFER_END);
+#if !CONFIG_IS_ENABLED(DM_SPI)
+ /* We don't get an error code in this case */
+ if (ret)
+ ret = -EIO;
+#endif
+ if (ret) {
+ printf("Error %d during SPI transaction\n", ret);
+ } else {
+ int j;
+
+ for (j = 0; j < ((bitlen + 7) / 8); j++)
+ printf("%02X", din[j]);
+ printf("\n");
+ }
+done:
+ spi_release_bus(slave);
+#if !CONFIG_IS_ENABLED(DM_SPI)
+ spi_free_slave(slave);
+#endif
+
+ return ret;
+}
+
+/*
+ * SPI read/write
+ *
+ * Syntax:
+ * spi {dev} {num_bits} {dout}
+ * {dev} is the device number for controlling chip select (see TBD)
+ * {num_bits} is the number of bits to send & receive (base 10)
+ * {dout} is a hexadecimal string of data to send
+ * The command prints out the hexadecimal string received via SPI.
+ */
+
+int do_spi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *cp = 0;
+ uchar tmp;
+ int j;
+
+ /*
+ * We use the last specified parameters, unless new ones are
+ * entered.
+ */
+ if (freq == 0)
+ freq = 1000000;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0)
+ {
+ if (argc >= 2) {
+ mode = CONFIG_DEFAULT_SPI_MODE;
+ bus = simple_strtoul(argv[1], &cp, 10);
+ if (*cp == ':') {
+ cs = simple_strtoul(cp+1, &cp, 10);
+ } else {
+ cs = bus;
+ bus = CONFIG_DEFAULT_SPI_BUS;
+ }
+ if (*cp == '.')
+ mode = simple_strtoul(cp+1, &cp, 10);
+ if (*cp == '@')
+ freq = simple_strtoul(cp+1, &cp, 10);
+ }
+ if (argc >= 3)
+ bitlen = simple_strtoul(argv[2], NULL, 10);
+ if (argc >= 4) {
+ cp = argv[3];
+ for(j = 0; *cp; j++, cp++) {
+ tmp = *cp - '0';
+ if(tmp > 9)
+ tmp -= ('A' - '0') - 10;
+ if(tmp > 15)
+ tmp -= ('a' - 'A');
+ if(tmp > 15) {
+ printf("Hex conversion error on %c\n", *cp);
+ return 1;
+ }
+ if((j % 2) == 0)
+ dout[j / 2] = (tmp << 4);
+ else
+ dout[j / 2] |= tmp;
+ }
+ }
+ }
+
+ if ((bitlen < 0) || (bitlen > (MAX_SPI_BYTES * 8))) {
+ printf("Invalid bitlen %d\n", bitlen);
+ return 1;
+ }
+
+ if (do_spi_xfer(bus, cs))
+ return 1;
+
+ return 0;
+}
+
+/***************************************************/
+
+U_BOOT_CMD(
+ sspi, 5, 1, do_spi,
+ "SPI utility command",
+ "[<bus>:]<cs>[.<mode>][@<freq>] <bit_len> <dout> - Send and receive bits\n"
+ "<bus> - Identifies the SPI bus\n"
+ "<cs> - Identifies the chip select\n"
+ "<mode> - Identifies the SPI mode to use\n"
+ "<freq> - Identifies the SPI bus frequency in Hz\n"
+ "<bit_len> - Number of bits to send (base 10)\n"
+ "<dout> - Hexadecimal string that gets sent"
+);
diff --git a/roms/u-boot/cmd/spl.c b/roms/u-boot/cmd/spl.c
new file mode 100644
index 000000000..472703f8f
--- /dev/null
+++ b/roms/u-boot/cmd/spl.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011
+ * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cmd_spl.h>
+#include <env.h>
+#include <image.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <linux/libfdt.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const char **subcmd_list[] = {
+
+ [SPL_EXPORT_FDT] = (const char * []) {
+#ifdef CONFIG_OF_LIBFDT
+ "start",
+ "loados",
+ #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
+ "ramdisk",
+ #endif
+ "fdt",
+ "cmdline",
+ "bdt",
+ "prep",
+#endif
+ NULL,
+ },
+ [SPL_EXPORT_ATAGS] = (const char * []) {
+#if defined(CONFIG_SETUP_MEMORY_TAGS) || \
+ defined(CONFIG_CMDLINE_TAG) || \
+ defined(CONFIG_INITRD_TAG) || \
+ defined(CONFIG_SERIAL_TAG) || \
+ defined(CONFIG_REVISION_TAG)
+ "start",
+ "loados",
+#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
+ "ramdisk",
+#endif
+ "cmdline",
+ "bdt",
+ "prep",
+#endif
+ NULL,
+ },
+ NULL
+};
+
+/* Calls bootm with the parameters given */
+static int call_bootm(int argc, char *const argv[], const char *subcommand[])
+{
+ char *bootm_argv[5];
+
+ int i = 0;
+ int ret = 0;
+ int j;
+
+ /* create paramter array */
+ bootm_argv[0] = "do_bootm";
+ switch (argc) {
+ case 3:
+ bootm_argv[4] = argv[2]; /* fdt addr */
+ case 2:
+ bootm_argv[3] = argv[1]; /* initrd addr */
+ case 1:
+ bootm_argv[2] = argv[0]; /* kernel addr */
+ }
+
+
+ /*
+ * - do the work -
+ * exec subcommands of do_bootm to init the images
+ * data structure
+ */
+ while (subcommand[i] != NULL) {
+ bootm_argv[1] = (char *)subcommand[i];
+ debug("args %d: %s %s ", argc, bootm_argv[0], bootm_argv[1]);
+ for (j = 0; j < argc; j++)
+ debug("%s ", bootm_argv[j + 2]);
+ debug("\n");
+
+ ret = do_bootm(find_cmd("do_bootm"), 0, argc+2,
+ bootm_argv);
+ debug("Subcommand retcode: %d\n", ret);
+ i++;
+ }
+
+ if (ret) {
+ printf("ERROR prep subcommand failed!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_spl_export_sub[] = {
+ U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)SPL_EXPORT_FDT, "", ""),
+ U_BOOT_CMD_MKENT(atags, 0, 1, (void *)SPL_EXPORT_ATAGS, "", ""),
+};
+
+static int spl_export(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const struct cmd_tbl *c;
+
+ if (argc < 2) /* no subcommand */
+ return cmd_usage(cmdtp);
+
+ c = find_cmd_tbl(argv[1], &cmd_spl_export_sub[0],
+ ARRAY_SIZE(cmd_spl_export_sub));
+ if ((c) && ((long)c->cmd <= SPL_EXPORT_LAST)) {
+ argc -= 2;
+ argv += 2;
+ if (call_bootm(argc, argv, subcmd_list[(long)c->cmd]))
+ return -1;
+ switch ((long)c->cmd) {
+#ifdef CONFIG_OF_LIBFDT
+ case SPL_EXPORT_FDT:
+ printf("Argument image is now in RAM: 0x%p\n",
+ (void *)images.ft_addr);
+ env_set_addr("fdtargsaddr", images.ft_addr);
+ env_set_hex("fdtargslen", fdt_totalsize(images.ft_addr));
+#ifdef CONFIG_CMD_SPL_WRITE_SIZE
+ if (fdt_totalsize(images.ft_addr) >
+ CONFIG_CMD_SPL_WRITE_SIZE)
+ puts("WARN: FDT size > CMD_SPL_WRITE_SIZE\n");
+#endif
+ break;
+#endif
+ case SPL_EXPORT_ATAGS:
+ printf("Argument image is now in RAM at: 0x%p\n",
+ (void *)gd->bd->bi_boot_params);
+ break;
+ }
+ } else {
+ /* Unrecognized command */
+ return cmd_usage(cmdtp);
+ }
+
+ return 0;
+}
+
+static struct cmd_tbl cmd_spl_sub[] = {
+ U_BOOT_CMD_MKENT(export, 0, 1, (void *)SPL_EXPORT, "", ""),
+};
+
+static int do_spl(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const struct cmd_tbl *c;
+ int cmd;
+
+ if (argc < 2) /* no subcommand */
+ return cmd_usage(cmdtp);
+
+ c = find_cmd_tbl(argv[1], &cmd_spl_sub[0], ARRAY_SIZE(cmd_spl_sub));
+ if (c) {
+ cmd = (long)c->cmd;
+ switch (cmd) {
+ case SPL_EXPORT:
+ argc--;
+ argv++;
+ if (spl_export(cmdtp, flag, argc, argv))
+ printf("Subcommand failed\n");
+ break;
+ default:
+ /* unrecognized command */
+ return cmd_usage(cmdtp);
+ }
+ } else {
+ /* Unrecognized command */
+ return cmd_usage(cmdtp);
+ }
+ return 0;
+}
+
+U_BOOT_CMD(
+ spl, 6 , 1, do_spl, "SPL configuration",
+ "export <img=atags|fdt> [kernel_addr] [initrd_addr] [fdt_addr]\n"
+ "\timg\t\t\"atags\" or \"fdt\"\n"
+ "\tkernel_addr\taddress where a kernel image is stored.\n"
+ "\t\t\tkernel is loaded as part of the boot process, but it is not started.\n"
+ "\tinitrd_addr\taddress of initial ramdisk\n"
+ "\t\t\tcan be set to \"-\" if fdt_addr without initrd_addr is used.\n"
+ "\tfdt_addr\tin case of fdt, the address of the device tree.\n"
+ );
diff --git a/roms/u-boot/cmd/sqfs.c b/roms/u-boot/cmd/sqfs.c
new file mode 100644
index 000000000..107038c4c
--- /dev/null
+++ b/roms/u-boot/cmd/sqfs.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Bootlin
+ *
+ * Author: Joao Marcos Costa <joaomarcos.costa@bootlin.com>
+ *
+ * squashfs.c: implements SquashFS related commands
+ */
+
+#include <command.h>
+#include <fs.h>
+#include <squashfs.h>
+
+static int do_sqfs_ls(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+ return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SQUASHFS);
+}
+
+U_BOOT_CMD(sqfsls, 4, 1, do_sqfs_ls,
+ "List files in directory. Default: root (/).",
+ "<interface> [<dev[:part]>] [directory]\n"
+ " - list files from 'dev' on 'interface' in 'directory'\n"
+);
+
+static int do_sqfs_load(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
+{
+ return do_load(cmdtp, flag, argc, argv, FS_TYPE_SQUASHFS);
+}
+
+U_BOOT_CMD(sqfsload, 7, 0, do_sqfs_load,
+ "load binary file from a SquashFS filesystem",
+ "<interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]\n"
+ " - Load binary file 'filename' from 'dev' on 'interface'\n"
+ " to address 'addr' from SquashFS filesystem.\n"
+ " 'pos' gives the file position to start loading from.\n"
+ " If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n"
+ " 'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n"
+ " the load stops on end of file.\n"
+ " If either 'pos' or 'bytes' are not aligned to\n"
+ " ARCH_DMA_MINALIGN then a misaligned buffer warning will\n"
+ " be printed and performance will suffer for the load."
+);
diff --git a/roms/u-boot/cmd/stackprot_test.c b/roms/u-boot/cmd/stackprot_test.c
new file mode 100644
index 000000000..1e26193e8
--- /dev/null
+++ b/roms/u-boot/cmd/stackprot_test.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Broadcom
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_test_stackprot_fail(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ /*
+ * In order to avoid having the compiler optimize away the stack smashing
+ * we need to do a little something here.
+ */
+ char a[128];
+
+ memset(a, 0xa5, 512);
+
+ printf("We have smashed our stack as this should not exceed 128: sizeof(a) = %ld\n", strlen(a));
+
+ return 0;
+}
+
+U_BOOT_CMD(stackprot_test, 1, 1, do_test_stackprot_fail,
+ "test stack protector fail", "");
diff --git a/roms/u-boot/cmd/strings.c b/roms/u-boot/cmd/strings.c
new file mode 100644
index 000000000..85fdc34f0
--- /dev/null
+++ b/roms/u-boot/cmd/strings.c
@@ -0,0 +1,46 @@
+/*
+ * cmd_strings.c - just like `strings` command
+ *
+ * Copyright (c) 2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+
+static char *start_addr, *last_addr;
+
+int do_strings(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc == 1)
+ return CMD_RET_USAGE;
+
+ if ((flag & CMD_FLAG_REPEAT) == 0) {
+ start_addr = (char *)simple_strtoul(argv[1], NULL, 16);
+ if (argc > 2)
+ last_addr = (char *)simple_strtoul(argv[2], NULL, 16);
+ else
+ last_addr = (char *)-1;
+ }
+
+ char *addr = start_addr;
+ do {
+ puts(addr);
+ puts("\n");
+ addr += strlen(addr) + 1;
+ } while (addr[0] && addr < last_addr);
+
+ last_addr = addr + (last_addr - start_addr);
+ start_addr = addr;
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ strings, 3, 1, do_strings,
+ "display strings",
+ "<addr> [byte count]\n"
+ " - display strings at <addr> for at least [byte count] or first double NUL"
+);
diff --git a/roms/u-boot/cmd/sysboot.c b/roms/u-boot/cmd/sysboot.c
new file mode 100644
index 000000000..af6a2f1b7
--- /dev/null
+++ b/roms/u-boot/cmd/sysboot.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <fs.h>
+#include "pxe_utils.h"
+
+static char *fs_argv[5];
+
+static int do_get_ext2(struct cmd_tbl *cmdtp, const char *file_path,
+ char *file_addr)
+{
+#ifdef CONFIG_CMD_EXT2
+ fs_argv[0] = "ext2load";
+ fs_argv[3] = file_addr;
+ fs_argv[4] = (void *)file_path;
+
+ if (!do_ext2load(cmdtp, 0, 5, fs_argv))
+ return 1;
+#endif
+ return -ENOENT;
+}
+
+static int do_get_fat(struct cmd_tbl *cmdtp, const char *file_path,
+ char *file_addr)
+{
+#ifdef CONFIG_CMD_FAT
+ fs_argv[0] = "fatload";
+ fs_argv[3] = file_addr;
+ fs_argv[4] = (void *)file_path;
+
+ if (!do_fat_fsload(cmdtp, 0, 5, fs_argv))
+ return 1;
+#endif
+ return -ENOENT;
+}
+
+static int do_get_any(struct cmd_tbl *cmdtp, const char *file_path,
+ char *file_addr)
+{
+#ifdef CONFIG_CMD_FS_GENERIC
+ fs_argv[0] = "load";
+ fs_argv[3] = file_addr;
+ fs_argv[4] = (void *)file_path;
+
+ if (!do_load(cmdtp, 0, 5, fs_argv, FS_TYPE_ANY))
+ return 1;
+#endif
+ return -ENOENT;
+}
+
+/*
+ * Boots a system using a local disk syslinux/extlinux file
+ *
+ * Returns 0 on success, 1 on error.
+ */
+static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long pxefile_addr_r;
+ struct pxe_menu *cfg;
+ char *pxefile_addr_str;
+ char *filename;
+ int prompt = 0;
+
+ is_pxe = false;
+
+ if (argc > 1 && strstr(argv[1], "-p")) {
+ prompt = 1;
+ argc--;
+ argv++;
+ }
+
+ if (argc < 4)
+ return cmd_usage(cmdtp);
+
+ if (argc < 5) {
+ pxefile_addr_str = from_env("pxefile_addr_r");
+ if (!pxefile_addr_str)
+ return 1;
+ } else {
+ pxefile_addr_str = argv[4];
+ }
+
+ if (argc < 6) {
+ filename = env_get("bootfile");
+ } else {
+ filename = argv[5];
+ env_set("bootfile", filename);
+ }
+
+ if (strstr(argv[3], "ext2")) {
+ do_getfile = do_get_ext2;
+ } else if (strstr(argv[3], "fat")) {
+ do_getfile = do_get_fat;
+ } else if (strstr(argv[3], "any")) {
+ do_getfile = do_get_any;
+ } else {
+ printf("Invalid filesystem: %s\n", argv[3]);
+ return 1;
+ }
+ fs_argv[1] = argv[1];
+ fs_argv[2] = argv[2];
+
+ if (strict_strtoul(pxefile_addr_str, 16, &pxefile_addr_r) < 0) {
+ printf("Invalid pxefile address: %s\n", pxefile_addr_str);
+ return 1;
+ }
+
+ if (get_pxe_file(cmdtp, filename, pxefile_addr_r) < 0) {
+ printf("Error reading config file\n");
+ return 1;
+ }
+
+ cfg = parse_pxefile(cmdtp, pxefile_addr_r);
+
+ if (!cfg) {
+ printf("Error parsing config file\n");
+ return 1;
+ }
+
+ if (prompt)
+ cfg->prompt = 1;
+
+ handle_pxe_menu(cmdtp, cfg);
+
+ destroy_pxe_menu(cfg);
+
+ return 0;
+}
+
+U_BOOT_CMD(sysboot, 7, 1, do_sysboot,
+ "command to get and boot from syslinux files",
+ "[-p] <interface> <dev[:part]> <ext2|fat|any> [addr] [filename]\n"
+ " - load and parse syslinux menu file 'filename' from ext2, fat\n"
+ " or any filesystem on 'dev' on 'interface' to address 'addr'"
+);
diff --git a/roms/u-boot/cmd/terminal.c b/roms/u-boot/cmd/terminal.c
new file mode 100644
index 000000000..9e32a4191
--- /dev/null
+++ b/roms/u-boot/cmd/terminal.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2007 OpenMoko, Inc.
+ * Written by Harald Welte <laforge@openmoko.org>
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <stdio_dev.h>
+#include <serial.h>
+
+int do_terminal(struct cmd_tbl *cmd, int flag, int argc, char *const argv[])
+{
+ int last_tilde = 0;
+ struct stdio_dev *dev = NULL;
+
+ if (argc < 1)
+ return -1;
+
+ /* Scan for selected output/input device */
+ dev = stdio_get_by_name(argv[1]);
+ if (!dev)
+ return -1;
+
+ if (IS_ENABLED(CONFIG_SERIAL))
+ serial_reinit_all();
+
+ printf("Entering terminal mode for port %s\n", dev->name);
+ puts("Use '~.' to leave the terminal and get back to u-boot\n");
+
+ while (1) {
+ int c;
+
+ /* read from console and display on serial port */
+ if (stdio_devices[0]->tstc(stdio_devices[0])) {
+ c = stdio_devices[0]->getc(stdio_devices[0]);
+ if (last_tilde == 1) {
+ if (c == '.') {
+ putc(c);
+ putc('\n');
+ break;
+ } else {
+ last_tilde = 0;
+ /* write the delayed tilde */
+ dev->putc(dev, '~');
+ /* fall-through to print current
+ * character */
+ }
+ }
+ if (c == '~') {
+ last_tilde = 1;
+ puts("[u-boot]");
+ putc(c);
+ }
+ dev->putc(dev, c);
+ }
+
+ /* read from serial port and display on console */
+ if (dev->tstc(dev)) {
+ c = dev->getc(dev);
+ putc(c);
+ }
+ }
+ return 0;
+}
+
+
+/***************************************************/
+
+U_BOOT_CMD(
+ terminal, 3, 1, do_terminal,
+ "start terminal emulator",
+ ""
+);
diff --git a/roms/u-boot/cmd/test.c b/roms/u-boot/cmd/test.c
new file mode 100644
index 000000000..fa7c48fb9
--- /dev/null
+++ b/roms/u-boot/cmd/test.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <log.h>
+
+#define OP_INVALID 0
+#define OP_NOT 1
+#define OP_OR 2
+#define OP_AND 3
+#define OP_STR_EMPTY 4
+#define OP_STR_NEMPTY 5
+#define OP_STR_EQ 6
+#define OP_STR_NEQ 7
+#define OP_STR_LT 8
+#define OP_STR_GT 9
+#define OP_INT_EQ 10
+#define OP_INT_NEQ 11
+#define OP_INT_LT 12
+#define OP_INT_LE 13
+#define OP_INT_GT 14
+#define OP_INT_GE 15
+#define OP_FILE_EXISTS 16
+
+const struct {
+ int arg;
+ const char *str;
+ int op;
+ int adv;
+} op_adv[] = {
+ {1, "=", OP_STR_EQ, 3},
+ {1, "!=", OP_STR_NEQ, 3},
+ {1, "<", OP_STR_LT, 3},
+ {1, ">", OP_STR_GT, 3},
+ {1, "-eq", OP_INT_EQ, 3},
+ {1, "-ne", OP_INT_NEQ, 3},
+ {1, "-lt", OP_INT_LT, 3},
+ {1, "-le", OP_INT_LE, 3},
+ {1, "-gt", OP_INT_GT, 3},
+ {1, "-ge", OP_INT_GE, 3},
+ {0, "!", OP_NOT, 1},
+ {0, "-o", OP_OR, 1},
+ {0, "-a", OP_AND, 1},
+ {0, "-z", OP_STR_EMPTY, 2},
+ {0, "-n", OP_STR_NEMPTY, 2},
+ {0, "-e", OP_FILE_EXISTS, 4},
+};
+
+static int do_test(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char * const *ap;
+ int i, op, left, adv, expr, last_expr, last_unop, last_binop;
+
+ /* args? */
+ if (argc < 3)
+ return 1;
+
+#ifdef DEBUG
+ {
+ debug("test(%d):", argc);
+ left = 1;
+ while (argv[left])
+ debug(" '%s'", argv[left++]);
+ }
+#endif
+
+ left = argc - 1;
+ ap = argv + 1;
+ expr = 0;
+ last_unop = OP_INVALID;
+ last_binop = OP_INVALID;
+ last_expr = -1;
+ while (left > 0) {
+ for (i = 0; i < ARRAY_SIZE(op_adv); i++) {
+ if (left <= op_adv[i].arg)
+ continue;
+ if (!strcmp(ap[op_adv[i].arg], op_adv[i].str)) {
+ op = op_adv[i].op;
+ adv = op_adv[i].adv;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(op_adv)) {
+ expr = 1;
+ break;
+ }
+ if (left < adv) {
+ expr = 1;
+ break;
+ }
+
+ switch (op) {
+ case OP_STR_EMPTY:
+ expr = strlen(ap[1]) == 0 ? 1 : 0;
+ break;
+ case OP_STR_NEMPTY:
+ expr = strlen(ap[1]) == 0 ? 0 : 1;
+ break;
+ case OP_STR_EQ:
+ expr = strcmp(ap[0], ap[2]) == 0;
+ break;
+ case OP_STR_NEQ:
+ expr = strcmp(ap[0], ap[2]) != 0;
+ break;
+ case OP_STR_LT:
+ expr = strcmp(ap[0], ap[2]) < 0;
+ break;
+ case OP_STR_GT:
+ expr = strcmp(ap[0], ap[2]) > 0;
+ break;
+ case OP_INT_EQ:
+ expr = simple_strtol(ap[0], NULL, 0) ==
+ simple_strtol(ap[2], NULL, 0);
+ break;
+ case OP_INT_NEQ:
+ expr = simple_strtol(ap[0], NULL, 0) !=
+ simple_strtol(ap[2], NULL, 0);
+ break;
+ case OP_INT_LT:
+ expr = simple_strtol(ap[0], NULL, 0) <
+ simple_strtol(ap[2], NULL, 0);
+ break;
+ case OP_INT_LE:
+ expr = simple_strtol(ap[0], NULL, 0) <=
+ simple_strtol(ap[2], NULL, 0);
+ break;
+ case OP_INT_GT:
+ expr = simple_strtol(ap[0], NULL, 0) >
+ simple_strtol(ap[2], NULL, 0);
+ break;
+ case OP_INT_GE:
+ expr = simple_strtol(ap[0], NULL, 0) >=
+ simple_strtol(ap[2], NULL, 0);
+ break;
+ case OP_FILE_EXISTS:
+ expr = file_exists(ap[1], ap[2], ap[3], FS_TYPE_ANY);
+ break;
+ }
+
+ switch (op) {
+ case OP_OR:
+ last_expr = expr;
+ last_binop = OP_OR;
+ break;
+ case OP_AND:
+ last_expr = expr;
+ last_binop = OP_AND;
+ break;
+ case OP_NOT:
+ if (last_unop == OP_NOT)
+ last_unop = OP_INVALID;
+ else
+ last_unop = OP_NOT;
+ break;
+ default:
+ if (last_unop == OP_NOT) {
+ expr = !expr;
+ last_unop = OP_INVALID;
+ }
+
+ if (last_binop == OP_OR)
+ expr = last_expr || expr;
+ else if (last_binop == OP_AND)
+ expr = last_expr && expr;
+ last_binop = OP_INVALID;
+
+ break;
+ }
+
+ ap += adv; left -= adv;
+ }
+
+ expr = !expr;
+
+ debug (": returns %d\n", expr);
+
+ return expr;
+}
+
+#undef true
+#undef false
+
+U_BOOT_CMD(
+ test, CONFIG_SYS_MAXARGS, 1, do_test,
+ "minimal test like /bin/sh",
+ "[args..]"
+);
+
+static int do_false(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return 1;
+}
+
+U_BOOT_CMD(
+ false, CONFIG_SYS_MAXARGS, 1, do_false,
+ "do nothing, unsuccessfully",
+ NULL
+);
+
+static int do_true(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return 0;
+}
+
+U_BOOT_CMD(
+ true, CONFIG_SYS_MAXARGS, 1, do_true,
+ "do nothing, successfully",
+ NULL
+);
diff --git a/roms/u-boot/cmd/thordown.c b/roms/u-boot/cmd/thordown.c
new file mode 100644
index 000000000..838764cce
--- /dev/null
+++ b/roms/u-boot/cmd/thordown.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * cmd_thordown.c -- USB TIZEN "THOR" Downloader gadget
+ *
+ * Copyright (C) 2013 Lukasz Majewski <l.majewski@samsung.com>
+ * All rights reserved.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <thor.h>
+#include <dfu.h>
+#include <g_dnl.h>
+#include <usb.h>
+
+int do_thor_down(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ char *usb_controller = argv[1];
+ char *interface = argv[2];
+ char *devstring = argv[3];
+
+ int ret;
+
+ puts("TIZEN \"THOR\" Downloader\n");
+
+ ret = dfu_init_env_entities(interface, devstring);
+ if (ret)
+ goto done;
+
+ int controller_index = simple_strtoul(usb_controller, NULL, 0);
+ ret = usb_gadget_initialize(controller_index);
+ if (ret) {
+ pr_err("USB init failed: %d\n", ret);
+ ret = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ ret = g_dnl_register("usb_dnl_thor");
+ if (ret) {
+ pr_err("g_dnl_register failed %d\n", ret);
+ ret = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ ret = thor_init();
+ if (ret) {
+ pr_err("THOR DOWNLOAD failed: %d\n", ret);
+ ret = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ do {
+ ret = thor_handle();
+ if (ret == THOR_DFU_REINIT_NEEDED) {
+ dfu_free_entities();
+ ret = dfu_init_env_entities(interface, devstring);
+ }
+ if (ret) {
+ pr_err("THOR failed: %d\n", ret);
+ ret = CMD_RET_FAILURE;
+ goto exit;
+ }
+ } while (ret == 0);
+exit:
+ g_dnl_unregister();
+ usb_gadget_release(controller_index);
+done:
+ dfu_free_entities();
+
+ return ret;
+}
+
+U_BOOT_CMD(thordown, CONFIG_SYS_MAXARGS, 1, do_thor_down,
+ "TIZEN \"THOR\" downloader",
+ "<USB_controller> <interface> <dev>\n"
+ " - device software upgrade via LTHOR TIZEN download\n"
+ " program via <USB_controller> on device <dev>,\n"
+ " attached to interface <interface>\n"
+);
diff --git a/roms/u-boot/cmd/ti/Kconfig b/roms/u-boot/cmd/ti/Kconfig
new file mode 100644
index 000000000..efeff0d48
--- /dev/null
+++ b/roms/u-boot/cmd/ti/Kconfig
@@ -0,0 +1,10 @@
+menu "TI specific command line interface"
+
+config CMD_DDR3
+ bool "command for verifying DDR features"
+ help
+ Support for testing ddr3 on TI platforms. This command
+ supports memory verification, memory comapre and ecc
+ verification if supported.
+
+endmenu
diff --git a/roms/u-boot/cmd/ti/Makefile b/roms/u-boot/cmd/ti/Makefile
new file mode 100644
index 000000000..16fbade9e
--- /dev/null
+++ b/roms/u-boot/cmd/ti/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+
+obj- += dummy.o
+
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_CMD_DDR3) += ddr3.o
+endif
diff --git a/roms/u-boot/cmd/ti/ddr3.c b/roms/u-boot/cmd/ti/ddr3.c
new file mode 100644
index 000000000..6b43a7386
--- /dev/null
+++ b/roms/u-boot/cmd/ti/ddr3.c
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EMIF: DDR3 test commands
+ *
+ * Copyright (C) 2012-2017 Texas Instruments Incorporated, <www.ti.com>
+ */
+
+#include <cpu_func.h>
+#include <env.h>
+#include <init.h>
+#include <log.h>
+#include <asm/arch/hardware.h>
+#include <asm/cache.h>
+#include <asm/emif.h>
+#include <common.h>
+#include <command.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_ARCH_KEYSTONE
+#include <asm/arch/ddr3.h>
+#define DDR_MIN_ADDR CONFIG_SYS_SDRAM_BASE
+#define STACKSIZE (512 << 10) /* 512 KiB */
+
+#define DDR_REMAP_ADDR 0x80000000
+#define ECC_START_ADDR1 ((DDR_MIN_ADDR - DDR_REMAP_ADDR) >> 17)
+
+#define ECC_END_ADDR1 (((gd->start_addr_sp - DDR_REMAP_ADDR - \
+ STACKSIZE) >> 17) - 2)
+#endif
+
+#define DDR_TEST_BURST_SIZE 1024
+
+static int ddr_memory_test(u32 start_address, u32 end_address, int quick)
+{
+ u32 index_start, value, index;
+
+ index_start = start_address;
+
+ while (1) {
+ /* Write a pattern */
+ for (index = index_start;
+ index < index_start + DDR_TEST_BURST_SIZE;
+ index += 4)
+ __raw_writel(index, index);
+
+ /* Read and check the pattern */
+ for (index = index_start;
+ index < index_start + DDR_TEST_BURST_SIZE;
+ index += 4) {
+ value = __raw_readl(index);
+ if (value != index) {
+ printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
+ index, value, __raw_readl(index));
+
+ return -1;
+ }
+ }
+
+ index_start += DDR_TEST_BURST_SIZE;
+ if (index_start >= end_address)
+ break;
+
+ if (quick)
+ continue;
+
+ /* Write a pattern for complementary values */
+ for (index = index_start;
+ index < index_start + DDR_TEST_BURST_SIZE;
+ index += 4)
+ __raw_writel((u32)~index, index);
+
+ /* Read and check the pattern */
+ for (index = index_start;
+ index < index_start + DDR_TEST_BURST_SIZE;
+ index += 4) {
+ value = __raw_readl(index);
+ if (value != ~index) {
+ printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
+ index, value, __raw_readl(index));
+
+ return -1;
+ }
+ }
+
+ index_start += DDR_TEST_BURST_SIZE;
+ if (index_start >= end_address)
+ break;
+
+ /* Write a pattern */
+ for (index = index_start;
+ index < index_start + DDR_TEST_BURST_SIZE;
+ index += 2)
+ __raw_writew((u16)index, index);
+
+ /* Read and check the pattern */
+ for (index = index_start;
+ index < index_start + DDR_TEST_BURST_SIZE;
+ index += 2) {
+ value = __raw_readw(index);
+ if (value != (u16)index) {
+ printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
+ index, value, __raw_readw(index));
+
+ return -1;
+ }
+ }
+
+ index_start += DDR_TEST_BURST_SIZE;
+ if (index_start >= end_address)
+ break;
+
+ /* Write a pattern */
+ for (index = index_start;
+ index < index_start + DDR_TEST_BURST_SIZE;
+ index += 1)
+ __raw_writeb((u8)index, index);
+
+ /* Read and check the pattern */
+ for (index = index_start;
+ index < index_start + DDR_TEST_BURST_SIZE;
+ index += 1) {
+ value = __raw_readb(index);
+ if (value != (u8)index) {
+ printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
+ index, value, __raw_readb(index));
+
+ return -1;
+ }
+ }
+
+ index_start += DDR_TEST_BURST_SIZE;
+ if (index_start >= end_address)
+ break;
+ }
+
+ puts("ddr memory test PASSED!\n");
+ return 0;
+}
+
+static int ddr_memory_compare(u32 address1, u32 address2, u32 size)
+{
+ u32 index, value, index2, value2;
+
+ for (index = address1, index2 = address2;
+ index < address1 + size;
+ index += 4, index2 += 4) {
+ value = __raw_readl(index);
+ value2 = __raw_readl(index2);
+
+ if (value != value2) {
+ printf("ddr_memory_test: Compare failed at address = 0x%x value = 0x%x, address2 = 0x%x value2 = 0x%x\n",
+ index, value, index2, value2);
+
+ return -1;
+ }
+ }
+
+ puts("ddr memory compare PASSED!\n");
+ return 0;
+}
+
+static void ddr_check_ecc_status(void)
+{
+ struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
+ u32 err_1b = readl(&emif->emif_1b_ecc_err_cnt);
+ u32 int_status = readl(&emif->emif_irqstatus_raw_sys);
+ int ecc_test = 0;
+ char *env;
+
+ env = env_get("ecc_test");
+ if (env)
+ ecc_test = simple_strtol(env, NULL, 0);
+
+ puts("ECC test Status:\n");
+ if (int_status & EMIF_INT_WR_ECC_ERR_SYS_MASK)
+ puts("\tECC test: DDR ECC write error interrupted\n");
+
+ if (int_status & EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK)
+ if (!ecc_test)
+ panic("\tECC test: DDR ECC 2-bit error interrupted");
+
+ if (int_status & EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK)
+ puts("\tECC test: DDR ECC 1-bit error interrupted\n");
+
+ if (err_1b)
+ printf("\tECC test: 1-bit ECC err count: 0x%x\n", err_1b);
+}
+
+static int ddr_memory_ecc_err(u32 addr, u32 ecc_err)
+{
+ struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
+ u32 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg);
+ u32 val1, val2, val3;
+
+ debug("Disabling D-Cache before ECC test\n");
+ dcache_disable();
+ invalidate_dcache_all();
+
+ puts("Testing DDR ECC:\n");
+ puts("\tECC test: Disabling DDR ECC ...\n");
+ writel(0, &emif->emif_ecc_ctrl_reg);
+
+ val1 = readl(addr);
+ val2 = val1 ^ ecc_err;
+ writel(val2, addr);
+
+ val3 = readl(addr);
+#ifdef CONFIG_ARCH_KEYSTONE
+ ecc_ctrl = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16);
+ writel(ecc_ctrl, EMIF1_BASE + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET);
+ ddr3_enable_ecc(EMIF1_BASE, 1);
+#else
+ writel(ecc_ctrl, &emif->emif_ecc_ctrl_reg);
+#endif
+
+ printf("\tECC test: addr 0x%x, read data 0x%x, written data 0x%x, err pattern: 0x%x, read after write data 0x%x\n",
+ addr, val1, val2, ecc_err, val3);
+
+ puts("\tECC test: Enabled DDR ECC ...\n");
+
+ val1 = readl(addr);
+ printf("\tECC test: addr 0x%x, read data 0x%x\n", addr, val1);
+
+ ddr_check_ecc_status();
+
+ debug("Enabling D-cache back after ECC test\n");
+ enable_caches();
+
+ return 0;
+}
+
+static int is_addr_valid(u32 addr)
+{
+ struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
+ u32 start_addr, end_addr, range, ecc_ctrl;
+
+#ifdef CONFIG_ARCH_KEYSTONE
+ ecc_ctrl = EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK;
+ range = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16);
+#else
+ ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg);
+ range = readl(&emif->emif_ecc_address_range_1);
+#endif
+
+ /* Check in ecc address range 1 */
+ if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK) {
+ start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16)
+ + CONFIG_SYS_SDRAM_BASE;
+ end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF +
+ CONFIG_SYS_SDRAM_BASE;
+ if ((addr >= start_addr) && (addr <= end_addr))
+ /* addr within ecc address range 1 */
+ return 1;
+ }
+
+ /* Check in ecc address range 2 */
+ if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK) {
+ range = readl(&emif->emif_ecc_address_range_2);
+ start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16)
+ + CONFIG_SYS_SDRAM_BASE;
+ end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF +
+ CONFIG_SYS_SDRAM_BASE;
+ if ((addr >= start_addr) && (addr <= end_addr))
+ /* addr within ecc address range 2 */
+ return 1;
+ }
+
+ return 0;
+}
+
+static int is_ecc_enabled(void)
+{
+ struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
+ u32 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg);
+
+ return (ecc_ctrl & EMIF_ECC_CTRL_REG_ECC_EN_MASK) &&
+ (ecc_ctrl & EMIF_ECC_REG_RMW_EN_MASK);
+}
+
+static int do_ddr_test(struct cmd_tbl *cmdtp,
+ int flag, int argc, char *const argv[])
+{
+ u32 start_addr, end_addr, size, ecc_err;
+
+ if ((argc == 4) && (strncmp(argv[1], "ecc_err", 8) == 0)) {
+ if (!is_ecc_enabled()) {
+ puts("ECC not enabled. Please Enable ECC any try again\n");
+ return CMD_RET_FAILURE;
+ }
+
+ start_addr = simple_strtoul(argv[2], NULL, 16);
+ ecc_err = simple_strtoul(argv[3], NULL, 16);
+
+ if (!is_addr_valid(start_addr)) {
+ puts("Invalid address. Please enter ECC supported address!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ddr_memory_ecc_err(start_addr, ecc_err);
+ return 0;
+ }
+
+ if (!(((argc == 4) && (strncmp(argv[1], "test", 5) == 0)) ||
+ ((argc == 5) && (strncmp(argv[1], "compare", 8) == 0))))
+ return cmd_usage(cmdtp);
+
+ start_addr = simple_strtoul(argv[2], NULL, 16);
+ end_addr = simple_strtoul(argv[3], NULL, 16);
+
+ if ((start_addr < CONFIG_SYS_SDRAM_BASE) ||
+ (start_addr > (CONFIG_SYS_SDRAM_BASE +
+ get_effective_memsize() - 1)) ||
+ (end_addr < CONFIG_SYS_SDRAM_BASE) ||
+ (end_addr > (CONFIG_SYS_SDRAM_BASE +
+ get_effective_memsize() - 1)) || (start_addr >= end_addr)) {
+ puts("Invalid start or end address!\n");
+ return cmd_usage(cmdtp);
+ }
+
+ puts("Please wait ...\n");
+ if (argc == 5) {
+ size = simple_strtoul(argv[4], NULL, 16);
+ ddr_memory_compare(start_addr, end_addr, size);
+ } else {
+ ddr_memory_test(start_addr, end_addr, 0);
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(ddr, 5, 1, do_ddr_test,
+ "DDR3 test",
+ "test <start_addr in hex> <end_addr in hex> - test DDR from start\n"
+ " address to end address\n"
+ "ddr compare <start_addr in hex> <end_addr in hex> <size in hex> -\n"
+ " compare DDR data of (size) bytes from start address to end\n"
+ " address\n"
+ "ddr ecc_err <addr in hex> <bit_err in hex> - generate bit errors\n"
+ " in DDR data at <addr>, the command will read a 32-bit data\n"
+ " from <addr>, and write (data ^ bit_err) back to <addr>\n"
+);
diff --git a/roms/u-boot/cmd/time.c b/roms/u-boot/cmd/time.c
new file mode 100644
index 000000000..db8c1892d
--- /dev/null
+++ b/roms/u-boot/cmd/time.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ */
+
+#include <common.h>
+#include <command.h>
+
+static void report_time(ulong cycles)
+{
+ ulong minutes, seconds, milliseconds;
+ ulong total_seconds, remainder;
+
+ total_seconds = cycles / CONFIG_SYS_HZ;
+ remainder = cycles % CONFIG_SYS_HZ;
+ minutes = total_seconds / 60;
+ seconds = total_seconds % 60;
+ /* approximate millisecond value */
+ milliseconds = (remainder * 1000 + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ;
+
+ printf("\ntime:");
+ if (minutes)
+ printf(" %lu minutes,", minutes);
+ printf(" %lu.%03lu seconds\n", seconds, milliseconds);
+}
+
+static int do_time(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ ulong cycles = 0;
+ int retval = 0;
+ int repeatable = 0;
+
+ if (argc == 1)
+ return CMD_RET_USAGE;
+
+ retval = cmd_process(0, argc - 1, argv + 1, &repeatable, &cycles);
+ report_time(cycles);
+
+ return retval;
+}
+
+U_BOOT_CMD(time, CONFIG_SYS_MAXARGS, 0, do_time,
+ "run commands and summarize execution time",
+ "command [args...]\n");
diff --git a/roms/u-boot/cmd/timer.c b/roms/u-boot/cmd/timer.c
new file mode 100644
index 000000000..551be5dd5
--- /dev/null
+++ b/roms/u-boot/cmd/timer.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_timer(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ static ulong start;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(argv[1], "start"))
+ start = get_timer(0);
+
+ if (!strcmp(argv[1], "get")) {
+ ulong msecs = get_timer(start) * 1000 / CONFIG_SYS_HZ;
+ printf("%ld.%03d\n", msecs / 1000, (int)(msecs % 1000));
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ timer, 2, 1, do_timer,
+ "access the system timer",
+ "start - Reset the timer reference.\n"
+ "timer get - Print the time since 'start'."
+);
diff --git a/roms/u-boot/cmd/tlv_eeprom.c b/roms/u-boot/cmd/tlv_eeprom.c
new file mode 100644
index 000000000..5099cbdd9
--- /dev/null
+++ b/roms/u-boot/cmd/tlv_eeprom.c
@@ -0,0 +1,1108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Copyright (C) 2013 Curt Brune <curt@cumulusnetworks.com>
+ * Copyright (C) 2014 Srideep <srideep_devireddy@dell.com>
+ * Copyright (C) 2013 Miles Tseng <miles_tseng@accton.com>
+ * Copyright (C) 2014,2016 david_yang <david_yang@accton.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <i2c.h>
+#include <i2c_eeprom.h>
+#include <env.h>
+#include <init.h>
+#include <net.h>
+#include <asm/global_data.h>
+#include <linux/ctype.h>
+#include <u-boot/crc.h>
+
+#include "tlv_eeprom.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MAX_TLV_DEVICES 2
+
+/* File scope function prototypes */
+static bool is_checksum_valid(u8 *eeprom);
+static int read_eeprom(u8 *eeprom);
+static void show_eeprom(u8 *eeprom);
+static void decode_tlv(struct tlvinfo_tlv *tlv);
+static void update_crc(u8 *eeprom);
+static int prog_eeprom(u8 *eeprom);
+static bool tlvinfo_find_tlv(u8 *eeprom, u8 tcode, int *eeprom_index);
+static bool tlvinfo_delete_tlv(u8 *eeprom, u8 code);
+static bool tlvinfo_add_tlv(u8 *eeprom, int tcode, char *strval);
+static int set_mac(char *buf, const char *string);
+static int set_date(char *buf, const char *string);
+static int set_bytes(char *buf, const char *string, int *converted_accum);
+static void show_tlv_devices(void);
+
+/* Set to 1 if we've read EEPROM into memory */
+static int has_been_read;
+/* The EERPOM contents after being read into memory */
+static u8 eeprom[TLV_INFO_MAX_LEN];
+
+static struct udevice *tlv_devices[MAX_TLV_DEVICES];
+static unsigned int current_dev;
+
+#define to_header(p) ((struct tlvinfo_header *)p)
+#define to_entry(p) ((struct tlvinfo_tlv *)p)
+
+#define HDR_SIZE sizeof(struct tlvinfo_header)
+#define ENT_SIZE sizeof(struct tlvinfo_tlv)
+
+static inline bool is_digit(char c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+/**
+ * is_valid_tlv
+ *
+ * Perform basic sanity checks on a TLV field. The TLV is pointed to
+ * by the parameter provided.
+ * 1. The type code is not reserved (0x00 or 0xFF)
+ */
+static inline bool is_valid_tlv(struct tlvinfo_tlv *tlv)
+{
+ return((tlv->type != 0x00) && (tlv->type != 0xFF));
+}
+
+/**
+ * is_hex
+ *
+ * Tests if character is an ASCII hex digit
+ */
+static inline u8 is_hex(char p)
+{
+ return (((p >= '0') && (p <= '9')) ||
+ ((p >= 'A') && (p <= 'F')) ||
+ ((p >= 'a') && (p <= 'f')));
+}
+
+/**
+ * is_checksum_valid
+ *
+ * Validate the checksum in the provided TlvInfo EEPROM data. First,
+ * verify that the TlvInfo header is valid, then make sure the last
+ * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data
+ * and compare it to the value stored in the EEPROM CRC-32 TLV.
+ */
+static bool is_checksum_valid(u8 *eeprom)
+{
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+ struct tlvinfo_tlv *eeprom_crc;
+ unsigned int calc_crc;
+ unsigned int stored_crc;
+
+ // Is the eeprom header valid?
+ if (!is_valid_tlvinfo_header(eeprom_hdr))
+ return false;
+
+ // Is the last TLV a CRC?
+ eeprom_crc = to_entry(&eeprom[HDR_SIZE +
+ be16_to_cpu(eeprom_hdr->totallen) - (ENT_SIZE + 4)]);
+ if (eeprom_crc->type != TLV_CODE_CRC_32 || eeprom_crc->length != 4)
+ return false;
+
+ // Calculate the checksum
+ calc_crc = crc32(0, (void *)eeprom,
+ HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen) - 4);
+ stored_crc = (eeprom_crc->value[0] << 24) |
+ (eeprom_crc->value[1] << 16) |
+ (eeprom_crc->value[2] << 8) |
+ eeprom_crc->value[3];
+ return calc_crc == stored_crc;
+}
+
+/**
+ * read_eeprom
+ *
+ * Read the EEPROM into memory, if it hasn't already been read.
+ */
+static int read_eeprom(u8 *eeprom)
+{
+ int ret;
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+ struct tlvinfo_tlv *eeprom_tlv = to_entry(&eeprom[HDR_SIZE]);
+
+ if (has_been_read)
+ return 0;
+
+ /* Read the header */
+ ret = read_tlv_eeprom((void *)eeprom_hdr, 0, HDR_SIZE, current_dev);
+ /* If the header was successfully read, read the TLVs */
+ if (ret == 0 && is_valid_tlvinfo_header(eeprom_hdr))
+ ret = read_tlv_eeprom((void *)eeprom_tlv, HDR_SIZE,
+ be16_to_cpu(eeprom_hdr->totallen),
+ current_dev);
+
+ // If the contents are invalid, start over with default contents
+ if (!is_valid_tlvinfo_header(eeprom_hdr) ||
+ !is_checksum_valid(eeprom)) {
+ strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING);
+ eeprom_hdr->version = TLV_INFO_VERSION;
+ eeprom_hdr->totallen = cpu_to_be16(0);
+ update_crc(eeprom);
+ }
+
+ has_been_read = 1;
+
+#ifdef DEBUG
+ show_eeprom(eeprom);
+#endif
+
+ return ret;
+}
+
+/**
+ * show_eeprom
+ *
+ * Display the contents of the EEPROM
+ */
+static void show_eeprom(u8 *eeprom)
+{
+ int tlv_end;
+ int curr_tlv;
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+ struct tlvinfo_tlv *eeprom_tlv;
+
+ if (!is_valid_tlvinfo_header(eeprom_hdr)) {
+ printf("EEPROM does not contain data in a valid TlvInfo format.\n");
+ return;
+ }
+
+ printf("TLV: %u\n", current_dev);
+ printf("TlvInfo Header:\n");
+ printf(" Id String: %s\n", eeprom_hdr->signature);
+ printf(" Version: %d\n", eeprom_hdr->version);
+ printf(" Total Length: %d\n", be16_to_cpu(eeprom_hdr->totallen));
+
+ printf("TLV Name Code Len Value\n");
+ printf("-------------------- ---- --- -----\n");
+ curr_tlv = HDR_SIZE;
+ tlv_end = HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen);
+ while (curr_tlv < tlv_end) {
+ eeprom_tlv = to_entry(&eeprom[curr_tlv]);
+ if (!is_valid_tlv(eeprom_tlv)) {
+ printf("Invalid TLV field starting at EEPROM offset %d\n",
+ curr_tlv);
+ return;
+ }
+ decode_tlv(eeprom_tlv);
+ curr_tlv += ENT_SIZE + eeprom_tlv->length;
+ }
+
+ printf("Checksum is %s.\n",
+ is_checksum_valid(eeprom) ? "valid" : "invalid");
+
+#ifdef DEBUG
+ printf("EEPROM dump: (0x%x bytes)", TLV_INFO_MAX_LEN);
+ for (i = 0; i < TLV_INFO_MAX_LEN; i++) {
+ if ((i % 16) == 0)
+ printf("\n%02X: ", i);
+ printf("%02X ", eeprom[i]);
+ }
+ printf("\n");
+#endif
+}
+
+/**
+ * Struct for displaying the TLV codes and names.
+ */
+struct tlv_code_desc {
+ u8 m_code;
+ char *m_name;
+};
+
+/**
+ * List of TLV codes and names.
+ */
+static struct tlv_code_desc tlv_code_list[] = {
+ { TLV_CODE_PRODUCT_NAME, "Product Name"},
+ { TLV_CODE_PART_NUMBER, "Part Number"},
+ { TLV_CODE_SERIAL_NUMBER, "Serial Number"},
+ { TLV_CODE_MAC_BASE, "Base MAC Address"},
+ { TLV_CODE_MANUF_DATE, "Manufacture Date"},
+ { TLV_CODE_DEVICE_VERSION, "Device Version"},
+ { TLV_CODE_LABEL_REVISION, "Label Revision"},
+ { TLV_CODE_PLATFORM_NAME, "Platform Name"},
+ { TLV_CODE_ONIE_VERSION, "ONIE Version"},
+ { TLV_CODE_MAC_SIZE, "MAC Addresses"},
+ { TLV_CODE_MANUF_NAME, "Manufacturer"},
+ { TLV_CODE_MANUF_COUNTRY, "Country Code"},
+ { TLV_CODE_VENDOR_NAME, "Vendor Name"},
+ { TLV_CODE_DIAG_VERSION, "Diag Version"},
+ { TLV_CODE_SERVICE_TAG, "Service Tag"},
+ { TLV_CODE_VENDOR_EXT, "Vendor Extension"},
+ { TLV_CODE_CRC_32, "CRC-32"},
+};
+
+/**
+ * Look up a TLV name by its type.
+ */
+static inline const char *tlv_type2name(u8 type)
+{
+ char *name = "Unknown";
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tlv_code_list); i++) {
+ if (tlv_code_list[i].m_code == type) {
+ name = tlv_code_list[i].m_name;
+ break;
+ }
+ }
+
+ return name;
+}
+
+/*
+ * decode_tlv
+ *
+ * Print a string representing the contents of the TLV field. The format of
+ * the string is:
+ * 1. The name of the field left justified in 20 characters
+ * 2. The type code in hex right justified in 5 characters
+ * 3. The length in decimal right justified in 4 characters
+ * 4. The value, left justified in however many characters it takes
+ * The validity of EEPROM contents and the TLV field have been verified
+ * prior to calling this function.
+ */
+#define DECODE_NAME_MAX 20
+
+/*
+ * The max decode value is currently for the 'raw' type or the 'vendor
+ * extension' type, both of which have the same decode format. The
+ * max decode string size is computed as follows:
+ *
+ * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1
+ *
+ */
+#define DECODE_VALUE_MAX ((5 * TLV_VALUE_MAX_LEN) + 1)
+
+static void decode_tlv(struct tlvinfo_tlv *tlv)
+{
+ char name[DECODE_NAME_MAX];
+ char value[DECODE_VALUE_MAX];
+ int i;
+
+ strncpy(name, tlv_type2name(tlv->type), DECODE_NAME_MAX);
+
+ switch (tlv->type) {
+ case TLV_CODE_PRODUCT_NAME:
+ case TLV_CODE_PART_NUMBER:
+ case TLV_CODE_SERIAL_NUMBER:
+ case TLV_CODE_MANUF_DATE:
+ case TLV_CODE_LABEL_REVISION:
+ case TLV_CODE_PLATFORM_NAME:
+ case TLV_CODE_ONIE_VERSION:
+ case TLV_CODE_MANUF_NAME:
+ case TLV_CODE_MANUF_COUNTRY:
+ case TLV_CODE_VENDOR_NAME:
+ case TLV_CODE_DIAG_VERSION:
+ case TLV_CODE_SERVICE_TAG:
+ memcpy(value, tlv->value, tlv->length);
+ value[tlv->length] = 0;
+ break;
+ case TLV_CODE_MAC_BASE:
+ sprintf(value, "%02X:%02X:%02X:%02X:%02X:%02X",
+ tlv->value[0], tlv->value[1], tlv->value[2],
+ tlv->value[3], tlv->value[4], tlv->value[5]);
+ break;
+ case TLV_CODE_DEVICE_VERSION:
+ sprintf(value, "%u", tlv->value[0]);
+ break;
+ case TLV_CODE_MAC_SIZE:
+ sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]);
+ break;
+ case TLV_CODE_VENDOR_EXT:
+ value[0] = 0;
+ for (i = 0; (i < (DECODE_VALUE_MAX / 5)) && (i < tlv->length);
+ i++) {
+ sprintf(value, "%s 0x%02X", value, tlv->value[i]);
+ }
+ break;
+ case TLV_CODE_CRC_32:
+ sprintf(value, "0x%02X%02X%02X%02X",
+ tlv->value[0], tlv->value[1],
+ tlv->value[2], tlv->value[3]);
+ break;
+ default:
+ value[0] = 0;
+ for (i = 0; (i < (DECODE_VALUE_MAX / 5)) && (i < tlv->length);
+ i++) {
+ sprintf(value, "%s 0x%02X", value, tlv->value[i]);
+ }
+ break;
+ }
+
+ name[DECODE_NAME_MAX - 1] = 0;
+ printf("%-20s 0x%02X %3d %s\n", name, tlv->type, tlv->length, value);
+}
+
+/**
+ * update_crc
+ *
+ * This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then
+ * one is added. This function should be called after each update to the
+ * EEPROM structure, to make sure the CRC is always correct.
+ */
+static void update_crc(u8 *eeprom)
+{
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+ struct tlvinfo_tlv *eeprom_crc;
+ unsigned int calc_crc;
+ int eeprom_index;
+
+ // Discover the CRC TLV
+ if (!tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) {
+ unsigned int totallen = be16_to_cpu(eeprom_hdr->totallen);
+
+ if ((totallen + ENT_SIZE + 4) > TLV_TOTAL_LEN_MAX)
+ return;
+ eeprom_index = HDR_SIZE + totallen;
+ eeprom_hdr->totallen = cpu_to_be16(totallen + ENT_SIZE + 4);
+ }
+ eeprom_crc = to_entry(&eeprom[eeprom_index]);
+ eeprom_crc->type = TLV_CODE_CRC_32;
+ eeprom_crc->length = 4;
+
+ // Calculate the checksum
+ calc_crc = crc32(0, (void *)eeprom,
+ HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen) - 4);
+ eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF;
+ eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF;
+ eeprom_crc->value[2] = (calc_crc >> 8) & 0xFF;
+ eeprom_crc->value[3] = (calc_crc >> 0) & 0xFF;
+}
+
+/**
+ * prog_eeprom
+ *
+ * Write the EEPROM data from CPU memory to the hardware.
+ */
+static int prog_eeprom(u8 *eeprom)
+{
+ int ret = 0;
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+ int eeprom_len;
+
+ update_crc(eeprom);
+
+ eeprom_len = HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen);
+ ret = write_tlv_eeprom(eeprom, eeprom_len);
+ if (ret) {
+ printf("Programming failed.\n");
+ return -1;
+ }
+
+ printf("Programming passed.\n");
+ return 0;
+}
+
+/**
+ * show_tlv_code_list - Display the list of TLV codes and names
+ */
+void show_tlv_code_list(void)
+{
+ int i;
+
+ printf("TLV Code TLV Name\n");
+ printf("======== =================\n");
+ for (i = 0; i < ARRAY_SIZE(tlv_code_list); i++) {
+ printf("0x%02X %s\n",
+ tlv_code_list[i].m_code,
+ tlv_code_list[i].m_name);
+ }
+}
+
+/**
+ * do_tlv_eeprom
+ *
+ * This function implements the tlv_eeprom command.
+ */
+int do_tlv_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char cmd;
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+
+ // If no arguments, read the EERPOM and display its contents
+ if (argc == 1) {
+ read_eeprom(eeprom);
+ show_eeprom(eeprom);
+ return 0;
+ }
+
+ // We only look at the first character to the command, so "read" and
+ // "reset" will both be treated as "read".
+ cmd = argv[1][0];
+
+ // Read the EEPROM contents
+ if (cmd == 'r') {
+ has_been_read = 0;
+ if (!read_eeprom(eeprom))
+ printf("EEPROM data loaded from device to memory.\n");
+ return 0;
+ }
+
+ // Subsequent commands require that the EEPROM has already been read.
+ if (!has_been_read) {
+ printf("Please read the EEPROM data first, using the 'tlv_eeprom read' command.\n");
+ return 0;
+ }
+
+ // Handle the commands that don't take parameters
+ if (argc == 2) {
+ switch (cmd) {
+ case 'w': /* write */
+ prog_eeprom(eeprom);
+ break;
+ case 'e': /* erase */
+ strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING);
+ eeprom_hdr->version = TLV_INFO_VERSION;
+ eeprom_hdr->totallen = cpu_to_be16(0);
+ update_crc(eeprom);
+ printf("EEPROM data in memory reset.\n");
+ break;
+ case 'l': /* list */
+ show_tlv_code_list();
+ break;
+ case 'd': /* dev */
+ show_tlv_devices();
+ break;
+ default:
+ cmd_usage(cmdtp);
+ break;
+ }
+ return 0;
+ }
+
+ // The set command takes one or two args.
+ if (argc > 4) {
+ cmd_usage(cmdtp);
+ return 0;
+ }
+
+ // Set command. If the TLV exists in the EEPROM, delete it. Then if
+ // data was supplied for this TLV add the TLV with the new contents at
+ // the end.
+ if (cmd == 's') {
+ int tcode;
+
+ tcode = simple_strtoul(argv[2], NULL, 0);
+ tlvinfo_delete_tlv(eeprom, tcode);
+ if (argc == 4)
+ tlvinfo_add_tlv(eeprom, tcode, argv[3]);
+ } else if (cmd == 'd') { /* 'dev' command */
+ unsigned int devnum;
+
+ devnum = simple_strtoul(argv[2], NULL, 0);
+ if (devnum > MAX_TLV_DEVICES || !tlv_devices[devnum]) {
+ printf("Invalid device number\n");
+ return 0;
+ }
+ current_dev = devnum;
+ has_been_read = 0;
+ } else {
+ cmd_usage(cmdtp);
+ }
+
+ return 0;
+}
+
+/**
+ * This macro defines the tlv_eeprom command line command.
+ */
+U_BOOT_CMD(tlv_eeprom, 4, 1, do_tlv_eeprom,
+ "Display and program the system EEPROM data block.",
+ "[read|write|set <type_code> <string_value>|erase|list]\n"
+ "tlv_eeprom\n"
+ " - With no arguments display the current contents.\n"
+ "tlv_eeprom dev [dev]\n"
+ " - List devices or set current EEPROM device.\n"
+ "tlv_eeprom read\n"
+ " - Load EEPROM data from device to memory.\n"
+ "tlv_eeprom write\n"
+ " - Write the EEPROM data to persistent storage.\n"
+ "tlv_eeprom set <type_code> <string_value>\n"
+ " - Set a field to a value.\n"
+ " - If no string_value, field is deleted.\n"
+ " - Use 'tlv_eeprom write' to make changes permanent.\n"
+ "tlv_eeprom erase\n"
+ " - Reset the in memory EEPROM data.\n"
+ " - Use 'tlv_eeprom read' to refresh the in memory EEPROM data.\n"
+ " - Use 'tlv_eeprom write' to make changes permanent.\n"
+ "tlv_eeprom list\n"
+ " - List the understood TLV codes and names.\n"
+ );
+
+/**
+ * tlvinfo_find_tlv
+ *
+ * This function finds the TLV with the supplied code in the EERPOM.
+ * An offset from the beginning of the EEPROM is returned in the
+ * eeprom_index parameter if the TLV is found.
+ */
+static bool tlvinfo_find_tlv(u8 *eeprom, u8 tcode, int *eeprom_index)
+{
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+ struct tlvinfo_tlv *eeprom_tlv;
+ int eeprom_end;
+
+ // Search through the TLVs, looking for the first one which matches the
+ // supplied type code.
+ *eeprom_index = HDR_SIZE;
+ eeprom_end = HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen);
+ while (*eeprom_index < eeprom_end) {
+ eeprom_tlv = to_entry(&eeprom[*eeprom_index]);
+ if (!is_valid_tlv(eeprom_tlv))
+ return false;
+ if (eeprom_tlv->type == tcode)
+ return true;
+ *eeprom_index += ENT_SIZE + eeprom_tlv->length;
+ }
+ return(false);
+}
+
+/**
+ * tlvinfo_delete_tlv
+ *
+ * This function deletes the TLV with the specified type code from the
+ * EEPROM.
+ */
+static bool tlvinfo_delete_tlv(u8 *eeprom, u8 code)
+{
+ int eeprom_index;
+ int tlength;
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+ struct tlvinfo_tlv *eeprom_tlv;
+
+ // Find the TLV and then move all following TLVs "forward"
+ if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) {
+ eeprom_tlv = to_entry(&eeprom[eeprom_index]);
+ tlength = ENT_SIZE + eeprom_tlv->length;
+ memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index + tlength],
+ HDR_SIZE +
+ be16_to_cpu(eeprom_hdr->totallen) - eeprom_index -
+ tlength);
+ eeprom_hdr->totallen =
+ cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) -
+ tlength);
+ update_crc(eeprom);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * tlvinfo_add_tlv
+ *
+ * This function adds a TLV to the EEPROM, converting the value (a string) to
+ * the format in which it will be stored in the EEPROM.
+ */
+#define MAX_TLV_VALUE_LEN 256
+static bool tlvinfo_add_tlv(u8 *eeprom, int tcode, char *strval)
+{
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+ struct tlvinfo_tlv *eeprom_tlv;
+ int new_tlv_len = 0;
+ u32 value;
+ char data[MAX_TLV_VALUE_LEN];
+ int eeprom_index;
+
+ // Encode each TLV type into the format to be stored in the EERPOM
+ switch (tcode) {
+ case TLV_CODE_PRODUCT_NAME:
+ case TLV_CODE_PART_NUMBER:
+ case TLV_CODE_SERIAL_NUMBER:
+ case TLV_CODE_LABEL_REVISION:
+ case TLV_CODE_PLATFORM_NAME:
+ case TLV_CODE_ONIE_VERSION:
+ case TLV_CODE_MANUF_NAME:
+ case TLV_CODE_MANUF_COUNTRY:
+ case TLV_CODE_VENDOR_NAME:
+ case TLV_CODE_DIAG_VERSION:
+ case TLV_CODE_SERVICE_TAG:
+ strncpy(data, strval, MAX_TLV_VALUE_LEN);
+ new_tlv_len = min_t(size_t, MAX_TLV_VALUE_LEN, strlen(strval));
+ break;
+ case TLV_CODE_DEVICE_VERSION:
+ value = simple_strtoul(strval, NULL, 0);
+ if (value >= 256) {
+ printf("ERROR: Device version must be 255 or less. Value supplied: %u",
+ value);
+ return false;
+ }
+ data[0] = value & 0xFF;
+ new_tlv_len = 1;
+ break;
+ case TLV_CODE_MAC_SIZE:
+ value = simple_strtoul(strval, NULL, 0);
+ if (value >= 65536) {
+ printf("ERROR: MAC Size must be 65535 or less. Value supplied: %u",
+ value);
+ return false;
+ }
+ data[0] = (value >> 8) & 0xFF;
+ data[1] = value & 0xFF;
+ new_tlv_len = 2;
+ break;
+ case TLV_CODE_MANUF_DATE:
+ if (set_date(data, strval) != 0)
+ return false;
+ new_tlv_len = 19;
+ break;
+ case TLV_CODE_MAC_BASE:
+ if (set_mac(data, strval) != 0)
+ return false;
+ new_tlv_len = 6;
+ break;
+ case TLV_CODE_CRC_32:
+ printf("WARNING: The CRC TLV is set automatically and cannot be set manually.\n");
+ return false;
+ case TLV_CODE_VENDOR_EXT:
+ default:
+ if (set_bytes(data, strval, &new_tlv_len) != 0)
+ return false;
+ break;
+ }
+
+ // Is there room for this TLV?
+ if ((be16_to_cpu(eeprom_hdr->totallen) + ENT_SIZE + new_tlv_len) >
+ TLV_TOTAL_LEN_MAX) {
+ printf("ERROR: There is not enough room in the EERPOM to save data.\n");
+ return false;
+ }
+
+ // Add TLV at the end, overwriting CRC TLV if it exists
+ if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index))
+ eeprom_hdr->totallen =
+ cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) -
+ ENT_SIZE - 4);
+ else
+ eeprom_index = HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen);
+ eeprom_tlv = to_entry(&eeprom[eeprom_index]);
+ eeprom_tlv->type = tcode;
+ eeprom_tlv->length = new_tlv_len;
+ memcpy(eeprom_tlv->value, data, new_tlv_len);
+
+ // Update the total length and calculate (add) a new CRC-32 TLV
+ eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) +
+ ENT_SIZE + new_tlv_len);
+ update_crc(eeprom);
+
+ return true;
+}
+
+/**
+ * set_mac
+ *
+ * Converts a string MAC address into a binary buffer.
+ *
+ * This function takes a pointer to a MAC address string
+ * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number).
+ * The string format is verified and then converted to binary and
+ * stored in a buffer.
+ */
+static int set_mac(char *buf, const char *string)
+{
+ char *p = (char *)string;
+ int i;
+ int err = 0;
+ char *end;
+
+ if (!p) {
+ printf("ERROR: NULL mac addr string passed in.\n");
+ return -1;
+ }
+
+ if (strlen(p) != 17) {
+ printf("ERROR: MAC address strlen() != 17 -- %zu\n", strlen(p));
+ printf("ERROR: Bad MAC address format: %s\n", string);
+ return -1;
+ }
+
+ for (i = 0; i < 17; i++) {
+ if ((i % 3) == 2) {
+ if (p[i] != ':') {
+ err++;
+ printf("ERROR: mac: p[%i] != :, found: `%c'\n",
+ i, p[i]);
+ break;
+ }
+ continue;
+ } else if (!is_hex(p[i])) {
+ err++;
+ printf("ERROR: mac: p[%i] != hex digit, found: `%c'\n",
+ i, p[i]);
+ break;
+ }
+ }
+
+ if (err != 0) {
+ printf("ERROR: Bad MAC address format: %s\n", string);
+ return -1;
+ }
+
+ /* Convert string to binary */
+ for (i = 0, p = (char *)string; i < 6; i++) {
+ buf[i] = p ? simple_strtoul(p, &end, 16) : 0;
+ if (p)
+ p = (*end) ? end + 1 : end;
+ }
+
+ if (!is_valid_ethaddr((u8 *)buf)) {
+ printf("ERROR: MAC address must not be 00:00:00:00:00:00, a multicast address or FF:FF:FF:FF:FF:FF.\n");
+ printf("ERROR: Bad MAC address format: %s\n", string);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * set_date
+ *
+ * Validates the format of the data string
+ *
+ * This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss)
+ * and validates that the format is correct. If so the string is copied
+ * to the supplied buffer.
+ */
+static int set_date(char *buf, const char *string)
+{
+ int i;
+
+ if (!string) {
+ printf("ERROR: NULL date string passed in.\n");
+ return -1;
+ }
+
+ if (strlen(string) != 19) {
+ printf("ERROR: Date strlen() != 19 -- %zu\n", strlen(string));
+ printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
+ string);
+ return -1;
+ }
+
+ for (i = 0; string[i] != 0; i++) {
+ switch (i) {
+ case 2:
+ case 5:
+ if (string[i] != '/') {
+ printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
+ string);
+ return -1;
+ }
+ break;
+ case 10:
+ if (string[i] != ' ') {
+ printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
+ string);
+ return -1;
+ }
+ break;
+ case 13:
+ case 16:
+ if (string[i] != ':') {
+ printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
+ string);
+ return -1;
+ }
+ break;
+ default:
+ if (!is_digit(string[i])) {
+ printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
+ string);
+ return -1;
+ }
+ break;
+ }
+ }
+
+ strcpy(buf, string);
+ return 0;
+}
+
+/**
+ * set_bytes
+ *
+ * Converts a space-separated string of decimal numbers into a
+ * buffer of bytes.
+ *
+ * This function takes a pointer to a space-separated string of decimal
+ * numbers (i.e. "128 0x55 0321") with "C" standard radix specifiers
+ * and converts them to an array of bytes.
+ */
+static int set_bytes(char *buf, const char *string, int *converted_accum)
+{
+ char *p = (char *)string;
+ int i;
+ uint byte;
+
+ if (!p) {
+ printf("ERROR: NULL string passed in.\n");
+ return -1;
+ }
+
+ /* Convert string to bytes */
+ for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0);
+ i++) {
+ while ((*p == ' ') || (*p == '\t') || (*p == ',') ||
+ (*p == ';')) {
+ p++;
+ }
+ if (*p != 0) {
+ if (!is_digit(*p)) {
+ printf("ERROR: Non-digit found in byte string: (%s)\n",
+ string);
+ return -1;
+ }
+ byte = simple_strtoul(p, &p, 0);
+ if (byte >= 256) {
+ printf("ERROR: The value specified is greater than 255: (%u) in string: %s\n",
+ byte, string);
+ return -1;
+ }
+ buf[i] = byte & 0xFF;
+ }
+ }
+
+ if (i == TLV_VALUE_MAX_LEN && (*p != 0)) {
+ printf("ERROR: Trying to assign too many bytes (max: %d) in string: %s\n",
+ TLV_VALUE_MAX_LEN, string);
+ return -1;
+ }
+
+ *converted_accum = i;
+ return 0;
+}
+
+static void show_tlv_devices(void)
+{
+ unsigned int dev;
+
+ for (dev = 0; dev < MAX_TLV_DEVICES; dev++)
+ if (tlv_devices[dev])
+ printf("TLV: %u%s\n", dev,
+ (dev == current_dev) ? " (*)" : "");
+}
+
+static int find_tlv_devices(struct udevice **tlv_devices_p)
+{
+ int ret;
+ int count_dev = 0;
+ struct udevice *dev;
+
+ for (ret = uclass_first_device_check(UCLASS_I2C_EEPROM, &dev);
+ dev;
+ ret = uclass_next_device_check(&dev)) {
+ if (ret == 0)
+ tlv_devices_p[count_dev++] = dev;
+ if (count_dev >= MAX_TLV_DEVICES)
+ break;
+ }
+
+ return (count_dev == 0) ? -ENODEV : 0;
+}
+
+static struct udevice *find_tlv_device_by_index(int dev_num)
+{
+ struct udevice *local_tlv_devices[MAX_TLV_DEVICES] = {};
+ struct udevice **tlv_devices_p;
+ int ret;
+
+ if (gd->flags & (GD_FLG_RELOC | GD_FLG_SPL_INIT)) {
+ /* Assume BSS is initialized; use static data */
+ if (tlv_devices[dev_num])
+ return tlv_devices[dev_num];
+ tlv_devices_p = tlv_devices;
+ } else {
+ tlv_devices_p = local_tlv_devices;
+ }
+
+ ret = find_tlv_devices(tlv_devices_p);
+ if (ret == 0 && tlv_devices_p[dev_num])
+ return tlv_devices_p[dev_num];
+
+ return NULL;
+}
+
+/**
+ * read_tlv_eeprom - read the hwinfo from i2c EEPROM
+ */
+int read_tlv_eeprom(void *eeprom, int offset, int len, int dev_num)
+{
+ struct udevice *dev;
+
+ if (dev_num >= MAX_TLV_DEVICES)
+ return -EINVAL;
+
+ dev = find_tlv_device_by_index(dev_num);
+ if (!dev)
+ return -ENODEV;
+
+ return i2c_eeprom_read(dev, offset, eeprom, len);
+}
+
+/**
+ * write_tlv_eeprom - write the hwinfo to i2c EEPROM
+ */
+int write_tlv_eeprom(void *eeprom, int len)
+{
+ if (!(gd->flags & GD_FLG_RELOC))
+ return -ENODEV;
+ if (!tlv_devices[current_dev])
+ return -ENODEV;
+
+ return i2c_eeprom_write(tlv_devices[current_dev], 0, eeprom, len);
+}
+
+int read_tlvinfo_tlv_eeprom(void *eeprom, struct tlvinfo_header **hdr,
+ struct tlvinfo_tlv **first_entry, int dev_num)
+{
+ int ret;
+ struct tlvinfo_header *tlv_hdr;
+ struct tlvinfo_tlv *tlv_ent;
+
+ /* Read TLV header */
+ ret = read_tlv_eeprom(eeprom, 0, HDR_SIZE, dev_num);
+ if (ret < 0)
+ return ret;
+
+ tlv_hdr = eeprom;
+ if (!is_valid_tlvinfo_header(tlv_hdr))
+ return -EINVAL;
+
+ /* Read TLV entries */
+ tlv_ent = to_entry(&tlv_hdr[1]);
+ ret = read_tlv_eeprom(tlv_ent, HDR_SIZE,
+ be16_to_cpu(tlv_hdr->totallen), dev_num);
+ if (ret < 0)
+ return ret;
+ if (!is_checksum_valid(eeprom))
+ return -EINVAL;
+
+ *hdr = tlv_hdr;
+ *first_entry = tlv_ent;
+
+ return 0;
+}
+
+/**
+ * mac_read_from_eeprom
+ *
+ * Read the MAC addresses from EEPROM
+ *
+ * This function reads the MAC addresses from EEPROM and sets the
+ * appropriate environment variables for each one read.
+ *
+ * The environment variables are only set if they haven't been set already.
+ * This ensures that any user-saved variables are never overwritten.
+ *
+ * This function must be called after relocation.
+ */
+int mac_read_from_eeprom(void)
+{
+ unsigned int i;
+ int eeprom_index;
+ struct tlvinfo_tlv *eeprom_tlv;
+ int maccount;
+ u8 macbase[6];
+ struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
+
+ puts("EEPROM: ");
+
+ if (read_eeprom(eeprom)) {
+ printf("Read failed.\n");
+ return -1;
+ }
+
+ maccount = 1;
+ if (tlvinfo_find_tlv(eeprom, TLV_CODE_MAC_SIZE, &eeprom_index)) {
+ eeprom_tlv = to_entry(&eeprom[eeprom_index]);
+ maccount = (eeprom_tlv->value[0] << 8) | eeprom_tlv->value[1];
+ }
+
+ memcpy(macbase, "\0\0\0\0\0\0", 6);
+ if (tlvinfo_find_tlv(eeprom, TLV_CODE_MAC_BASE, &eeprom_index)) {
+ eeprom_tlv = to_entry(&eeprom[eeprom_index]);
+ memcpy(macbase, eeprom_tlv->value, 6);
+ }
+
+ for (i = 0; i < maccount; i++) {
+ if (is_valid_ethaddr(macbase)) {
+ char ethaddr[18];
+ char enetvar[11];
+
+ sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
+ macbase[0], macbase[1], macbase[2],
+ macbase[3], macbase[4], macbase[5]);
+ sprintf(enetvar, i ? "eth%daddr" : "ethaddr", i);
+ /* Only initialize environment variables that are blank
+ * (i.e. have not yet been set)
+ */
+ if (!env_get(enetvar))
+ env_set(enetvar, ethaddr);
+
+ macbase[5]++;
+ if (macbase[5] == 0) {
+ macbase[4]++;
+ if (macbase[4] == 0) {
+ macbase[3]++;
+ if (macbase[3] == 0) {
+ macbase[0] = 0;
+ macbase[1] = 0;
+ macbase[2] = 0;
+ }
+ }
+ }
+ }
+ }
+
+ printf("%s v%u len=%u\n", eeprom_hdr->signature, eeprom_hdr->version,
+ be16_to_cpu(eeprom_hdr->totallen));
+
+ return 0;
+}
+
+/**
+ * populate_serial_number - read the serial number from EEPROM
+ *
+ * This function reads the serial number from the EEPROM and sets the
+ * appropriate environment variable.
+ *
+ * The environment variable is only set if it has not been set
+ * already. This ensures that any user-saved variables are never
+ * overwritten.
+ *
+ * This function must be called after relocation.
+ */
+int populate_serial_number(void)
+{
+ char serialstr[257];
+ int eeprom_index;
+ struct tlvinfo_tlv *eeprom_tlv;
+
+ if (env_get("serial#"))
+ return 0;
+
+ if (read_eeprom(eeprom)) {
+ printf("Read failed.\n");
+ return -1;
+ }
+
+ if (tlvinfo_find_tlv(eeprom, TLV_CODE_SERIAL_NUMBER, &eeprom_index)) {
+ eeprom_tlv = to_entry(&eeprom[eeprom_index]);
+ memcpy(serialstr, eeprom_tlv->value, eeprom_tlv->length);
+ serialstr[eeprom_tlv->length] = 0;
+ env_set("serial#", serialstr);
+ }
+
+ return 0;
+}
diff --git a/roms/u-boot/cmd/tpm-common.c b/roms/u-boot/cmd/tpm-common.c
new file mode 100644
index 000000000..88c9e08e3
--- /dev/null
+++ b/roms/u-boot/cmd/tpm-common.c
@@ -0,0 +1,387 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <env.h>
+#include <malloc.h>
+#include <asm/unaligned.h>
+#include <linux/string.h>
+#include <tpm-common.h>
+#include "tpm-user-utils.h"
+
+static struct udevice *tpm_dev;
+
+/**
+ * Print a byte string in hexdecimal format, 16-bytes per line.
+ *
+ * @param data byte string to be printed
+ * @param count number of bytes to be printed
+ */
+void print_byte_string(u8 *data, size_t count)
+{
+ int i, print_newline = 0;
+
+ for (i = 0; i < count; i++) {
+ printf(" %02x", data[i]);
+ print_newline = (i % 16 == 15);
+ if (print_newline)
+ putc('\n');
+ }
+ /* Avoid duplicated newline at the end */
+ if (!print_newline)
+ putc('\n');
+}
+
+/**
+ * Convert a text string of hexdecimal values into a byte string.
+ *
+ * @param bytes text string of hexdecimal values with no space
+ * between them
+ * @param data output buffer for byte string. The caller has to make
+ * sure it is large enough for storing the output. If
+ * NULL is passed, a large enough buffer will be allocated,
+ * and the caller must free it.
+ * @param count_ptr output variable for the length of byte string
+ * @return pointer to output buffer
+ */
+void *parse_byte_string(char *bytes, u8 *data, size_t *count_ptr)
+{
+ char byte[3];
+ size_t count, length;
+ int i;
+
+ if (!bytes)
+ return NULL;
+ length = strlen(bytes);
+ count = length / 2;
+
+ if (!data)
+ data = malloc(count);
+ if (!data)
+ return NULL;
+
+ byte[2] = '\0';
+ for (i = 0; i < length; i += 2) {
+ byte[0] = bytes[i];
+ byte[1] = bytes[i + 1];
+ data[i / 2] = (u8)simple_strtoul(byte, NULL, 16);
+ }
+
+ if (count_ptr)
+ *count_ptr = count;
+
+ return data;
+}
+
+/**
+ * report_return_code() - Report any error and return failure or success
+ *
+ * @param return_code TPM command return code
+ * @return value of enum command_ret_t
+ */
+int report_return_code(int return_code)
+{
+ if (return_code) {
+ printf("Error: %d\n", return_code);
+ return CMD_RET_FAILURE;
+ } else {
+ return CMD_RET_SUCCESS;
+ }
+}
+
+/**
+ * Return number of values defined by a type string.
+ *
+ * @param type_str type string
+ * @return number of values of type string
+ */
+int type_string_get_num_values(const char *type_str)
+{
+ return strlen(type_str);
+}
+
+/**
+ * Return total size of values defined by a type string.
+ *
+ * @param type_str type string
+ * @return total size of values of type string, or 0 if type string
+ * contains illegal type character.
+ */
+size_t type_string_get_space_size(const char *type_str)
+{
+ size_t size;
+
+ for (size = 0; *type_str; type_str++) {
+ switch (*type_str) {
+ case 'b':
+ size += 1;
+ break;
+ case 'w':
+ size += 2;
+ break;
+ case 'd':
+ size += 4;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ return size;
+}
+
+/**
+ * Allocate a buffer large enough to hold values defined by a type
+ * string. The caller has to free the buffer.
+ *
+ * @param type_str type string
+ * @param count pointer for storing size of buffer
+ * @return pointer to buffer or NULL on error
+ */
+void *type_string_alloc(const char *type_str, u32 *count)
+{
+ void *data;
+ size_t size;
+
+ size = type_string_get_space_size(type_str);
+ if (!size)
+ return NULL;
+ data = malloc(size);
+ if (data)
+ *count = size;
+
+ return data;
+}
+
+/**
+ * Pack values defined by a type string into a buffer. The buffer must have
+ * large enough space.
+ *
+ * @param type_str type string
+ * @param values text strings of values to be packed
+ * @param data output buffer of values
+ * @return 0 on success, non-0 on error
+ */
+int type_string_pack(const char *type_str, char * const values[],
+ u8 *data)
+{
+ size_t offset;
+ u32 value;
+
+ for (offset = 0; *type_str; type_str++, values++) {
+ value = simple_strtoul(values[0], NULL, 0);
+ switch (*type_str) {
+ case 'b':
+ data[offset] = value;
+ offset += 1;
+ break;
+ case 'w':
+ put_unaligned_be16(value, data + offset);
+ offset += 2;
+ break;
+ case 'd':
+ put_unaligned_be32(value, data + offset);
+ offset += 4;
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Read values defined by a type string from a buffer, and write these values
+ * to environment variables.
+ *
+ * @param type_str type string
+ * @param data input buffer of values
+ * @param vars names of environment variables
+ * @return 0 on success, non-0 on error
+ */
+int type_string_write_vars(const char *type_str, u8 *data,
+ char * const vars[])
+{
+ size_t offset;
+ u32 value;
+
+ for (offset = 0; *type_str; type_str++, vars++) {
+ switch (*type_str) {
+ case 'b':
+ value = data[offset];
+ offset += 1;
+ break;
+ case 'w':
+ value = get_unaligned_be16(data + offset);
+ offset += 2;
+ break;
+ case 'd':
+ value = get_unaligned_be32(data + offset);
+ offset += 4;
+ break;
+ default:
+ return -1;
+ }
+ if (env_set_ulong(*vars, value))
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tpm_show_device(void)
+{
+ struct udevice *dev;
+ char buf[80];
+ int n = 0, rc;
+
+ for_each_tpm_device(dev) {
+ rc = tpm_get_desc(dev, buf, sizeof(buf));
+ if (rc < 0)
+ printf("device %d: can't get info\n", n);
+ else
+ printf("device %d: %s\n", n, buf);
+
+ n++;
+ };
+
+ return 0;
+}
+
+static int tpm_set_device(unsigned long num)
+{
+ struct udevice *dev;
+ unsigned long n = 0;
+ int rc = CMD_RET_FAILURE;
+
+ for_each_tpm_device(dev) {
+ if (n == num) {
+ rc = 0;
+ break;
+ }
+
+ n++;
+ }
+
+ if (!rc)
+ tpm_dev = dev;
+
+ return rc;
+}
+
+int get_tpm(struct udevice **devp)
+{
+ int rc;
+
+ /*
+ * To keep a backward compatibility with previous code,
+ * if a tpm device is not explicitly set, we set the first one.
+ */
+ if (!tpm_dev) {
+ rc = tpm_set_device(0);
+ if (rc) {
+ printf("Couldn't set TPM 0 (rc = %d)\n", rc);
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ if (devp)
+ *devp = tpm_dev;
+
+ return 0;
+}
+
+int do_tpm_device(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned long num;
+ int rc;
+
+ if (argc == 2) {
+ num = simple_strtoul(argv[1], NULL, 10);
+
+ rc = tpm_set_device(num);
+ if (rc)
+ printf("Couldn't set TPM %lu (rc = %d)\n", num, rc);
+ } else {
+ rc = tpm_show_device();
+ }
+
+ return rc;
+}
+
+int do_tpm_info(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct udevice *dev;
+ char buf[80];
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+ rc = tpm_get_desc(dev, buf, sizeof(buf));
+ if (rc < 0) {
+ printf("Couldn't get TPM info (%d)\n", rc);
+ return CMD_RET_FAILURE;
+ }
+ printf("%s\n", buf);
+
+ return 0;
+}
+
+int do_tpm_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct udevice *dev;
+ int rc;
+
+ if (argc != 1)
+ return CMD_RET_USAGE;
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ return report_return_code(tpm_init(dev));
+}
+
+int do_tpm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *tpm_commands, *cmd;
+ struct tpm_chip_priv *priv;
+ struct udevice *dev;
+ unsigned int size;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ priv = dev_get_uclass_priv(dev);
+
+ /* Below getters return NULL if the desired stack is not built */
+ switch (priv->version) {
+ case TPM_V1:
+ tpm_commands = get_tpm1_commands(&size);
+ break;
+ case TPM_V2:
+ tpm_commands = get_tpm2_commands(&size);
+ break;
+ default:
+ tpm_commands = NULL;
+ }
+
+ if (!tpm_commands)
+ return CMD_RET_USAGE;
+
+ cmd = find_cmd_tbl(argv[1], tpm_commands, size);
+ if (!cmd)
+ return CMD_RET_USAGE;
+
+ return cmd->cmd(cmdtp, flag, argc - 1, argv + 1);
+}
diff --git a/roms/u-boot/cmd/tpm-user-utils.h b/roms/u-boot/cmd/tpm-user-utils.h
new file mode 100644
index 000000000..358ddff57
--- /dev/null
+++ b/roms/u-boot/cmd/tpm-user-utils.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#ifndef __TPM_USER_UTILS_H
+#define __TPM_USER_UTILS_H
+
+void print_byte_string(u8 *data, size_t count);
+void *parse_byte_string(char *bytes, u8 *data, size_t *count_ptr);
+int report_return_code(int return_code);
+int type_string_get_num_values(const char *type_str);
+size_t type_string_get_space_size(const char *type_str);
+void *type_string_alloc(const char *type_str, u32 *count);
+int type_string_pack(const char *type_str, char * const values[], u8 *data);
+int type_string_write_vars(const char *type_str, u8 *data, char * const vars[]);
+int get_tpm(struct udevice **devp);
+
+int do_tpm_device(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_tpm_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_tpm_info(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_tpm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+
+#endif /* __TPM_USER_UTILS_H */
diff --git a/roms/u-boot/cmd/tpm-v1.c b/roms/u-boot/cmd/tpm-v1.c
new file mode 100644
index 000000000..3a7e35d52
--- /dev/null
+++ b/roms/u-boot/cmd/tpm-v1.c
@@ -0,0 +1,829 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <malloc.h>
+#include <asm/unaligned.h>
+#include <tpm-common.h>
+#include <tpm-v1.h>
+#include "tpm-user-utils.h"
+#include <tpm_api.h>
+
+static int do_tpm_startup(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum tpm_startup_type mode;
+ struct udevice *dev;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ if (!strcasecmp("TPM_ST_CLEAR", argv[1])) {
+ mode = TPM_ST_CLEAR;
+ } else if (!strcasecmp("TPM_ST_STATE", argv[1])) {
+ mode = TPM_ST_STATE;
+ } else if (!strcasecmp("TPM_ST_DEACTIVATED", argv[1])) {
+ mode = TPM_ST_DEACTIVATED;
+ } else {
+ printf("Couldn't recognize mode string: %s\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ return report_return_code(tpm_startup(dev, mode));
+}
+
+static int do_tpm_nv_define_space(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 index, perm, size;
+ struct udevice *dev;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+ index = simple_strtoul(argv[1], NULL, 0);
+ perm = simple_strtoul(argv[2], NULL, 0);
+ size = simple_strtoul(argv[3], NULL, 0);
+
+ return report_return_code(tpm1_nv_define_space(dev, index, perm, size));
+}
+
+static int do_tpm_nv_read_value(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 index, count, rc;
+ struct udevice *dev;
+ void *data;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+ index = simple_strtoul(argv[1], NULL, 0);
+ data = (void *)simple_strtoul(argv[2], NULL, 0);
+ count = simple_strtoul(argv[3], NULL, 0);
+
+ rc = tpm_nv_read_value(dev, index, data, count);
+ if (!rc) {
+ puts("area content:\n");
+ print_byte_string(data, count);
+ }
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_nv_write_value(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ u32 index, rc;
+ size_t count;
+ void *data;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+ index = simple_strtoul(argv[1], NULL, 0);
+ data = parse_byte_string(argv[2], NULL, &count);
+ if (!data) {
+ printf("Couldn't parse byte string %s\n", argv[2]);
+ return CMD_RET_FAILURE;
+ }
+
+ rc = tpm_nv_write_value(dev, index, data, count);
+ free(data);
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_extend(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u8 in_digest[20], out_digest[20];
+ struct udevice *dev;
+ u32 index, rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+ index = simple_strtoul(argv[1], NULL, 0);
+ if (!parse_byte_string(argv[2], in_digest, NULL)) {
+ printf("Couldn't parse byte string %s\n", argv[2]);
+ return CMD_RET_FAILURE;
+ }
+
+ rc = tpm_pcr_extend(dev, index, in_digest, out_digest);
+ if (!rc) {
+ puts("PCR value after execution of the command:\n");
+ print_byte_string(out_digest, sizeof(out_digest));
+ }
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 index, count, rc;
+ struct udevice *dev;
+ void *data;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+ index = simple_strtoul(argv[1], NULL, 0);
+ data = (void *)simple_strtoul(argv[2], NULL, 0);
+ count = simple_strtoul(argv[3], NULL, 0);
+
+ rc = tpm_pcr_read(dev, index, data, count);
+ if (!rc) {
+ puts("Named PCR content:\n");
+ print_byte_string(data, count);
+ }
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_tsc_physical_presence(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct udevice *dev;
+ u16 presence;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ presence = (u16)simple_strtoul(argv[1], NULL, 0);
+
+ return report_return_code(tpm_tsc_physical_presence(dev, presence));
+}
+
+static int do_tpm_read_pubek(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ u32 count, rc;
+ void *data;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+ data = (void *)simple_strtoul(argv[1], NULL, 0);
+ count = simple_strtoul(argv[2], NULL, 0);
+
+ rc = tpm_read_pubek(dev, data, count);
+ if (!rc) {
+ puts("pubek value:\n");
+ print_byte_string(data, count);
+ }
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_physical_set_deactivated(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct udevice *dev;
+ u8 state;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ state = (u8)simple_strtoul(argv[1], NULL, 0);
+
+ return report_return_code(tpm_physical_set_deactivated(dev, state));
+}
+
+static int do_tpm_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 cap_area, sub_cap, rc;
+ void *cap;
+ size_t count;
+ struct udevice *dev;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+ cap_area = simple_strtoul(argv[1], NULL, 0);
+ sub_cap = simple_strtoul(argv[2], NULL, 0);
+ cap = (void *)simple_strtoul(argv[3], NULL, 0);
+ count = simple_strtoul(argv[4], NULL, 0);
+
+ rc = tpm_get_capability(dev, cap_area, sub_cap, cap, count);
+ if (!rc) {
+ puts("capability information:\n");
+ print_byte_string(cap, count);
+ }
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_raw_transfer(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ void *command;
+ u8 response[1024];
+ size_t count, response_length = sizeof(response);
+ u32 rc;
+
+ command = parse_byte_string(argv[1], NULL, &count);
+ if (!command) {
+ printf("Couldn't parse byte string %s\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ rc = tpm_xfer(dev, command, count, response, &response_length);
+ free(command);
+ if (!rc) {
+ puts("tpm response:\n");
+ print_byte_string(response, response_length);
+ }
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_nv_define(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 index, perm, size;
+ struct udevice *dev;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+ size = type_string_get_space_size(argv[1]);
+ if (!size) {
+ printf("Couldn't parse arguments\n");
+ return CMD_RET_USAGE;
+ }
+ index = simple_strtoul(argv[2], NULL, 0);
+ perm = simple_strtoul(argv[3], NULL, 0);
+
+ return report_return_code(tpm1_nv_define_space(dev, index, perm, size));
+}
+
+static int do_tpm_nv_read(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 index, count, err;
+ struct udevice *dev;
+ void *data;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+ if (argc != 3 + type_string_get_num_values(argv[1]))
+ return CMD_RET_USAGE;
+ index = simple_strtoul(argv[2], NULL, 0);
+ data = type_string_alloc(argv[1], &count);
+ if (!data) {
+ printf("Couldn't parse arguments\n");
+ return CMD_RET_USAGE;
+ }
+
+ err = tpm_nv_read_value(dev, index, data, count);
+ if (!err) {
+ if (type_string_write_vars(argv[1], data, argv + 3)) {
+ printf("Couldn't write to variables\n");
+ err = ~0;
+ }
+ }
+ free(data);
+
+ return report_return_code(err);
+}
+
+static int do_tpm_nv_write(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 index, count, err;
+ struct udevice *dev;
+ void *data;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+ if (argc != 3 + type_string_get_num_values(argv[1]))
+ return CMD_RET_USAGE;
+ index = simple_strtoul(argv[2], NULL, 0);
+ data = type_string_alloc(argv[1], &count);
+ if (!data) {
+ printf("Couldn't parse arguments\n");
+ return CMD_RET_USAGE;
+ }
+ if (type_string_pack(argv[1], argv + 3, data)) {
+ printf("Couldn't parse arguments\n");
+ free(data);
+ return CMD_RET_USAGE;
+ }
+
+ err = tpm_nv_write_value(dev, index, data, count);
+ free(data);
+
+ return report_return_code(err);
+}
+
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+
+static int do_tpm_oiap(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 auth_handle, err;
+ struct udevice *dev;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ err = tpm1_oiap(dev, &auth_handle);
+
+ return report_return_code(err);
+}
+
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+static int do_tpm_load_key_by_sha1(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 parent_handle = 0;
+ u32 key_len, key_handle, err;
+ u8 usage_auth[DIGEST_LENGTH];
+ u8 parent_hash[DIGEST_LENGTH];
+ void *key;
+ struct udevice *dev;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ parse_byte_string(argv[1], parent_hash, NULL);
+ key = (void *)simple_strtoul(argv[2], NULL, 0);
+ key_len = simple_strtoul(argv[3], NULL, 0);
+ if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
+ return CMD_RET_FAILURE;
+ parse_byte_string(argv[4], usage_auth, NULL);
+
+ err = tpm_find_key_sha1(usage_auth, parent_hash, &parent_handle);
+ if (err) {
+ printf("Could not find matching parent key (err = %d)\n", err);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Found parent key %08x\n", parent_handle);
+
+ err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
+ &key_handle);
+ if (!err) {
+ printf("Key handle is 0x%x\n", key_handle);
+ env_set_hex("key_handle", key_handle);
+ }
+
+ return report_return_code(err);
+}
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
+static int do_tpm_load_key2_oiap(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 parent_handle, key_len, key_handle, err;
+ u8 usage_auth[DIGEST_LENGTH];
+ void *key;
+ struct udevice *dev;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ parent_handle = simple_strtoul(argv[1], NULL, 0);
+ key = (void *)simple_strtoul(argv[2], NULL, 0);
+ key_len = simple_strtoul(argv[3], NULL, 0);
+ if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
+ return CMD_RET_FAILURE;
+ parse_byte_string(argv[4], usage_auth, NULL);
+
+ err = tpm1_load_key2_oiap(dev, parent_handle, key, key_len, usage_auth,
+ &key_handle);
+ if (!err)
+ printf("Key handle is 0x%x\n", key_handle);
+
+ return report_return_code(err);
+}
+
+static int do_tpm_get_pub_key_oiap(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 key_handle, err;
+ u8 usage_auth[DIGEST_LENGTH];
+ u8 pub_key_buffer[TPM_PUBKEY_MAX_LENGTH];
+ size_t pub_key_len = sizeof(pub_key_buffer);
+ struct udevice *dev;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ key_handle = simple_strtoul(argv[1], NULL, 0);
+ if (strlen(argv[2]) != 2 * DIGEST_LENGTH)
+ return CMD_RET_FAILURE;
+ parse_byte_string(argv[2], usage_auth, NULL);
+
+ err = tpm1_get_pub_key_oiap(dev, key_handle, usage_auth, pub_key_buffer,
+ &pub_key_len);
+ if (!err) {
+ printf("dump of received pub key structure:\n");
+ print_byte_string(pub_key_buffer, pub_key_len);
+ }
+ return report_return_code(err);
+}
+
+TPM_COMMAND_NO_ARG(tpm1_end_oiap)
+
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+static int do_tpm_flush(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ int type = 0;
+ int rc;
+
+ rc = get_tpm(&dev);
+ if (rc)
+ return rc;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp(argv[1], "key"))
+ type = TPM_RT_KEY;
+ else if (!strcasecmp(argv[1], "auth"))
+ type = TPM_RT_AUTH;
+ else if (!strcasecmp(argv[1], "hash"))
+ type = TPM_RT_HASH;
+ else if (!strcasecmp(argv[1], "trans"))
+ type = TPM_RT_TRANS;
+ else if (!strcasecmp(argv[1], "context"))
+ type = TPM_RT_CONTEXT;
+ else if (!strcasecmp(argv[1], "counter"))
+ type = TPM_RT_COUNTER;
+ else if (!strcasecmp(argv[1], "delegate"))
+ type = TPM_RT_DELEGATE;
+ else if (!strcasecmp(argv[1], "daa_tpm"))
+ type = TPM_RT_DAA_TPM;
+ else if (!strcasecmp(argv[1], "daa_v0"))
+ type = TPM_RT_DAA_V0;
+ else if (!strcasecmp(argv[1], "daa_v1"))
+ type = TPM_RT_DAA_V1;
+
+ if (!type) {
+ printf("Resource type %s unknown.\n", argv[1]);
+ return -1;
+ }
+
+ if (!strcasecmp(argv[2], "all")) {
+ u16 res_count;
+ u8 buf[288];
+ u8 *ptr;
+ int err;
+ uint i;
+
+ /* fetch list of already loaded resources in the TPM */
+ err = tpm_get_capability(dev, TPM_CAP_HANDLE, type, buf,
+ sizeof(buf));
+ if (err) {
+ printf("tpm_get_capability returned error %d.\n", err);
+ return -1;
+ }
+ res_count = get_unaligned_be16(buf);
+ ptr = buf + 2;
+ for (i = 0; i < res_count; ++i, ptr += 4)
+ tpm1_flush_specific(dev, get_unaligned_be32(ptr), type);
+ } else {
+ u32 handle = simple_strtoul(argv[2], NULL, 0);
+
+ if (!handle) {
+ printf("Illegal resource handle %s\n", argv[2]);
+ return -1;
+ }
+ tpm1_flush_specific(dev, cpu_to_be32(handle), type);
+ }
+
+ return 0;
+}
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+
+#ifdef CONFIG_TPM_LIST_RESOURCES
+static int do_tpm_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int type = 0;
+ u16 res_count;
+ u8 buf[288];
+ u8 *ptr;
+ int err;
+ uint i;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp(argv[1], "key"))
+ type = TPM_RT_KEY;
+ else if (!strcasecmp(argv[1], "auth"))
+ type = TPM_RT_AUTH;
+ else if (!strcasecmp(argv[1], "hash"))
+ type = TPM_RT_HASH;
+ else if (!strcasecmp(argv[1], "trans"))
+ type = TPM_RT_TRANS;
+ else if (!strcasecmp(argv[1], "context"))
+ type = TPM_RT_CONTEXT;
+ else if (!strcasecmp(argv[1], "counter"))
+ type = TPM_RT_COUNTER;
+ else if (!strcasecmp(argv[1], "delegate"))
+ type = TPM_RT_DELEGATE;
+ else if (!strcasecmp(argv[1], "daa_tpm"))
+ type = TPM_RT_DAA_TPM;
+ else if (!strcasecmp(argv[1], "daa_v0"))
+ type = TPM_RT_DAA_V0;
+ else if (!strcasecmp(argv[1], "daa_v1"))
+ type = TPM_RT_DAA_V1;
+
+ if (!type) {
+ printf("Resource type %s unknown.\n", argv[1]);
+ return -1;
+ }
+
+ /* fetch list of already loaded resources in the TPM */
+ err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
+ sizeof(buf));
+ if (err) {
+ printf("tpm_get_capability returned error %d.\n", err);
+ return -1;
+ }
+ res_count = get_unaligned_be16(buf);
+ ptr = buf + 2;
+
+ printf("Resources of type %s (%02x):\n", argv[1], type);
+ if (!res_count) {
+ puts("None\n");
+ } else {
+ for (i = 0; i < res_count; ++i, ptr += 4)
+ printf("Index %d: %08x\n", i, get_unaligned_be32(ptr));
+ }
+
+ return 0;
+}
+#endif /* CONFIG_TPM_LIST_RESOURCES */
+
+TPM_COMMAND_NO_ARG(tpm_self_test_full)
+TPM_COMMAND_NO_ARG(tpm_continue_self_test)
+TPM_COMMAND_NO_ARG(tpm_force_clear)
+TPM_COMMAND_NO_ARG(tpm_physical_enable)
+TPM_COMMAND_NO_ARG(tpm_physical_disable)
+
+static struct cmd_tbl tpm1_commands[] = {
+ U_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, "", ""),
+ U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
+ U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""),
+ U_BOOT_CMD_MKENT(startup, 0, 1,
+ do_tpm_startup, "", ""),
+ U_BOOT_CMD_MKENT(self_test_full, 0, 1,
+ do_tpm_self_test_full, "", ""),
+ U_BOOT_CMD_MKENT(continue_self_test, 0, 1,
+ do_tpm_continue_self_test, "", ""),
+ U_BOOT_CMD_MKENT(force_clear, 0, 1,
+ do_tpm_force_clear, "", ""),
+ U_BOOT_CMD_MKENT(physical_enable, 0, 1,
+ do_tpm_physical_enable, "", ""),
+ U_BOOT_CMD_MKENT(physical_disable, 0, 1,
+ do_tpm_physical_disable, "", ""),
+ U_BOOT_CMD_MKENT(nv_define_space, 0, 1,
+ do_tpm_nv_define_space, "", ""),
+ U_BOOT_CMD_MKENT(nv_read_value, 0, 1,
+ do_tpm_nv_read_value, "", ""),
+ U_BOOT_CMD_MKENT(nv_write_value, 0, 1,
+ do_tpm_nv_write_value, "", ""),
+ U_BOOT_CMD_MKENT(extend, 0, 1,
+ do_tpm_extend, "", ""),
+ U_BOOT_CMD_MKENT(pcr_read, 0, 1,
+ do_tpm_pcr_read, "", ""),
+ U_BOOT_CMD_MKENT(tsc_physical_presence, 0, 1,
+ do_tpm_tsc_physical_presence, "", ""),
+ U_BOOT_CMD_MKENT(read_pubek, 0, 1,
+ do_tpm_read_pubek, "", ""),
+ U_BOOT_CMD_MKENT(physical_set_deactivated, 0, 1,
+ do_tpm_physical_set_deactivated, "", ""),
+ U_BOOT_CMD_MKENT(get_capability, 0, 1,
+ do_tpm_get_capability, "", ""),
+ U_BOOT_CMD_MKENT(raw_transfer, 0, 1,
+ do_tpm_raw_transfer, "", ""),
+ U_BOOT_CMD_MKENT(nv_define, 0, 1,
+ do_tpm_nv_define, "", ""),
+ U_BOOT_CMD_MKENT(nv_read, 0, 1,
+ do_tpm_nv_read, "", ""),
+ U_BOOT_CMD_MKENT(nv_write, 0, 1,
+ do_tpm_nv_write, "", ""),
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+ U_BOOT_CMD_MKENT(oiap, 0, 1,
+ do_tpm_oiap, "", ""),
+ U_BOOT_CMD_MKENT(end_oiap, 0, 1,
+ do_tpm1_end_oiap, "", ""),
+ U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
+ do_tpm_load_key2_oiap, "", ""),
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+ U_BOOT_CMD_MKENT(load_key_by_sha1, 0, 1,
+ do_tpm_load_key_by_sha1, "", ""),
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+ U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
+ do_tpm_get_pub_key_oiap, "", ""),
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+ U_BOOT_CMD_MKENT(flush, 0, 1,
+ do_tpm_flush, "", ""),
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+#ifdef CONFIG_TPM_LIST_RESOURCES
+ U_BOOT_CMD_MKENT(list, 0, 1,
+ do_tpm_list, "", ""),
+#endif /* CONFIG_TPM_LIST_RESOURCES */
+};
+
+struct cmd_tbl *get_tpm1_commands(unsigned int *size)
+{
+ *size = ARRAY_SIZE(tpm1_commands);
+
+ return tpm1_commands;
+}
+
+U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
+"Issue a TPMv1.x command",
+"cmd args...\n"
+" - Issue TPM command <cmd> with arguments <args...>.\n"
+"Admin Startup and State Commands:\n"
+" device [num device]\n"
+" - Show all devices or set the specified device\n"
+" info - Show information about the TPM\n"
+" init\n"
+" - Put TPM into a state where it waits for 'startup' command.\n"
+" startup mode\n"
+" - Issue TPM_Starup command. <mode> is one of TPM_ST_CLEAR,\n"
+" TPM_ST_STATE, and TPM_ST_DEACTIVATED.\n"
+"Admin Testing Commands:\n"
+" self_test_full\n"
+" - Test all of the TPM capabilities.\n"
+" continue_self_test\n"
+" - Inform TPM that it should complete the self-test.\n"
+"Admin Opt-in Commands:\n"
+" physical_enable\n"
+" - Set the PERMANENT disable flag to FALSE using physical presence as\n"
+" authorization.\n"
+" physical_disable\n"
+" - Set the PERMANENT disable flag to TRUE using physical presence as\n"
+" authorization.\n"
+" physical_set_deactivated 0|1\n"
+" - Set deactivated flag.\n"
+"Admin Ownership Commands:\n"
+" force_clear\n"
+" - Issue TPM_ForceClear command.\n"
+" tsc_physical_presence flags\n"
+" - Set TPM device's Physical Presence flags to <flags>.\n"
+"The Capability Commands:\n"
+" get_capability cap_area sub_cap addr count\n"
+" - Read <count> bytes of TPM capability indexed by <cap_area> and\n"
+" <sub_cap> to memory address <addr>.\n"
+#if defined(CONFIG_TPM_FLUSH_RESOURCES) || defined(CONFIG_TPM_LIST_RESOURCES)
+"Resource management functions\n"
+#endif
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+" flush resource_type id\n"
+" - flushes a resource of type <resource_type> (may be one of key, auth,\n"
+" hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
+" and id <id> from the TPM. Use an <id> of \"all\" to flush all\n"
+" resources of that type.\n"
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+#ifdef CONFIG_TPM_LIST_RESOURCES
+" list resource_type\n"
+" - lists resources of type <resource_type> (may be one of key, auth,\n"
+" hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
+" contained in the TPM.\n"
+#endif /* CONFIG_TPM_LIST_RESOURCES */
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+"Storage functions\n"
+" loadkey2_oiap parent_handle key_addr key_len usage_auth\n"
+" - loads a key data from memory address <key_addr>, <key_len> bytes\n"
+" into TPM using the parent key <parent_handle> with authorization\n"
+" <usage_auth> (20 bytes hex string).\n"
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+" load_key_by_sha1 parent_hash key_addr key_len usage_auth\n"
+" - loads a key data from memory address <key_addr>, <key_len> bytes\n"
+" into TPM using the parent hash <parent_hash> (20 bytes hex string)\n"
+" with authorization <usage_auth> (20 bytes hex string).\n"
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+" get_pub_key_oiap key_handle usage_auth\n"
+" - get the public key portion of a loaded key <key_handle> using\n"
+" authorization <usage auth> (20 bytes hex string)\n"
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+"Endorsement Key Handling Commands:\n"
+" read_pubek addr count\n"
+" - Read <count> bytes of the public endorsement key to memory\n"
+" address <addr>\n"
+"Integrity Collection and Reporting Commands:\n"
+" extend index digest_hex_string\n"
+" - Add a new measurement to a PCR. Update PCR <index> with the 20-bytes\n"
+" <digest_hex_string>\n"
+" pcr_read index addr count\n"
+" - Read <count> bytes from PCR <index> to memory address <addr>.\n"
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+"Authorization Sessions\n"
+" oiap\n"
+" - setup an OIAP session\n"
+" end_oiap\n"
+" - terminates an active OIAP session\n"
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+"Non-volatile Storage Commands:\n"
+" nv_define_space index permission size\n"
+" - Establish a space at index <index> with <permission> of <size> bytes.\n"
+" nv_read_value index addr count\n"
+" - Read <count> bytes from space <index> to memory address <addr>.\n"
+" nv_write_value index addr count\n"
+" - Write <count> bytes from memory address <addr> to space <index>.\n"
+"Miscellaneous helper functions:\n"
+" raw_transfer byte_string\n"
+" - Send a byte string <byte_string> to TPM and print the response.\n"
+" Non-volatile storage helper functions:\n"
+" These helper functions treat a non-volatile space as a non-padded\n"
+" sequence of integer values. These integer values are defined by a type\n"
+" string, which is a text string of 'bwd' characters: 'b' means a 8-bit\n"
+" value, 'w' 16-bit value, 'd' 32-bit value. All helper functions take\n"
+" a type string as their first argument.\n"
+" nv_define type_string index perm\n"
+" - Define a space <index> with permission <perm>.\n"
+" nv_read types_string index vars...\n"
+" - Read from space <index> to environment variables <vars...>.\n"
+" nv_write types_string index values...\n"
+" - Write to space <index> from values <values...>.\n"
+);
diff --git a/roms/u-boot/cmd/tpm-v2.c b/roms/u-boot/cmd/tpm-v2.c
new file mode 100644
index 000000000..daae91100
--- /dev/null
+++ b/roms/u-boot/cmd/tpm-v2.c
@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Bootlin
+ * Author: Miquel Raynal <miquel.raynal@bootlin.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <log.h>
+#include <mapmem.h>
+#include <tpm-common.h>
+#include <tpm-v2.h>
+#include "tpm-user-utils.h"
+
+static int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum tpm2_startup_types mode;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp("TPM2_SU_CLEAR", argv[1])) {
+ mode = TPM2_SU_CLEAR;
+ } else if (!strcasecmp("TPM2_SU_STATE", argv[1])) {
+ mode = TPM2_SU_STATE;
+ } else {
+ printf("Couldn't recognize mode string: %s\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ return report_return_code(tpm2_startup(dev, mode));
+}
+
+static int do_tpm2_self_test(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ enum tpm2_yes_no full_test;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ if (!strcasecmp("full", argv[1])) {
+ full_test = TPMI_YES;
+ } else if (!strcasecmp("continue", argv[1])) {
+ full_test = TPMI_NO;
+ } else {
+ printf("Couldn't recognize test mode: %s\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ return report_return_code(tpm2_self_test(dev, full_test));
+}
+
+static int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 handle = 0;
+ const char *pw = (argc < 3) ? NULL : argv[2];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc < 2 || argc > 3)
+ return CMD_RET_USAGE;
+
+ if (pw_sz > TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
+ handle = TPM2_RH_LOCKOUT;
+ else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
+ handle = TPM2_RH_PLATFORM;
+ else
+ return CMD_RET_USAGE;
+
+ return report_return_code(tpm2_clear(dev, handle, pw, pw_sz));
+}
+
+static int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct tpm_chip_priv *priv;
+ u32 index = simple_strtoul(argv[1], NULL, 0);
+ void *digest = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
+ int ret;
+ u32 rc;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ priv = dev_get_uclass_priv(dev);
+ if (!priv)
+ return -EINVAL;
+
+ if (index >= priv->pcr_count)
+ return -EINVAL;
+
+ rc = tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, digest,
+ TPM2_DIGEST_LEN);
+
+ unmap_sysmem(digest);
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct tpm_chip_priv *priv;
+ u32 index, rc;
+ unsigned int updates;
+ void *data;
+ int ret;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ priv = dev_get_uclass_priv(dev);
+ if (!priv)
+ return -EINVAL;
+
+ index = simple_strtoul(argv[1], NULL, 0);
+ if (index >= priv->pcr_count)
+ return -EINVAL;
+
+ data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
+
+ rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, data, &updates);
+ if (!rc) {
+ printf("PCR #%u content (%u known updates):\n", index, updates);
+ print_byte_string(data, TPM2_DIGEST_LEN);
+ }
+
+ unmap_sysmem(data);
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 capability, property, rc;
+ u8 *data;
+ size_t count;
+ int i, j;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc != 5)
+ return CMD_RET_USAGE;
+
+ capability = simple_strtoul(argv[1], NULL, 0);
+ property = simple_strtoul(argv[2], NULL, 0);
+ data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
+ count = simple_strtoul(argv[4], NULL, 0);
+
+ rc = tpm2_get_capability(dev, capability, property, data, count);
+ if (rc)
+ goto unmap_data;
+
+ printf("Capabilities read from TPM:\n");
+ for (i = 0; i < count; i++) {
+ printf("Property 0x");
+ for (j = 0; j < 4; j++)
+ printf("%02x", data[(i * 8) + j + sizeof(u32)]);
+ printf(": 0x");
+ for (j = 4; j < 8; j++)
+ printf("%02x", data[(i * 8) + j + sizeof(u32)]);
+ printf("\n");
+ }
+
+unmap_data:
+ unmap_sysmem(data);
+
+ return report_return_code(rc);
+}
+
+static int do_tpm_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *pw = (argc < 2) ? NULL : argv[1];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc > 2)
+ return CMD_RET_USAGE;
+
+ if (pw_sz > TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ return report_return_code(tpm2_dam_reset(dev, pw, pw_sz));
+}
+
+static int do_tpm_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *pw = (argc < 5) ? NULL : argv[4];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ /*
+ * No Dictionary Attack Mitigation (DAM) means:
+ * maxtries = 0xFFFFFFFF, recovery_time = 1, lockout_recovery = 0
+ */
+ unsigned long int max_tries;
+ unsigned long int recovery_time;
+ unsigned long int lockout_recovery;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc < 4 || argc > 5)
+ return CMD_RET_USAGE;
+
+ if (pw_sz > TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (strict_strtoul(argv[1], 0, &max_tries))
+ return CMD_RET_USAGE;
+
+ if (strict_strtoul(argv[2], 0, &recovery_time))
+ return CMD_RET_USAGE;
+
+ if (strict_strtoul(argv[3], 0, &lockout_recovery))
+ return CMD_RET_USAGE;
+
+ log(LOGC_NONE, LOGL_INFO, "Changing dictionary attack parameters:\n");
+ log(LOGC_NONE, LOGL_INFO, "- maxTries: %lu", max_tries);
+ log(LOGC_NONE, LOGL_INFO, "- recoveryTime: %lu\n", recovery_time);
+ log(LOGC_NONE, LOGL_INFO, "- lockoutRecovery: %lu\n", lockout_recovery);
+
+ return report_return_code(tpm2_dam_parameters(dev, pw, pw_sz, max_tries,
+ recovery_time,
+ lockout_recovery));
+}
+
+static int do_tpm_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 handle;
+ const char *newpw = argv[2];
+ const char *oldpw = (argc == 3) ? NULL : argv[3];
+ const ssize_t newpw_sz = strlen(newpw);
+ const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ if (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
+ handle = TPM2_RH_LOCKOUT;
+ else if (!strcasecmp("TPM2_RH_ENDORSEMENT", argv[1]))
+ handle = TPM2_RH_ENDORSEMENT;
+ else if (!strcasecmp("TPM2_RH_OWNER", argv[1]))
+ handle = TPM2_RH_OWNER;
+ else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
+ handle = TPM2_RH_PLATFORM;
+ else
+ return CMD_RET_USAGE;
+
+ return report_return_code(tpm2_change_auth(dev, handle, newpw, newpw_sz,
+ oldpw, oldpw_sz));
+}
+
+static int do_tpm_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ u32 index = simple_strtoul(argv[1], NULL, 0);
+ char *key = argv[2];
+ const char *pw = (argc < 4) ? NULL : argv[3];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (strlen(key) != TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ return report_return_code(tpm2_pcr_setauthpolicy(dev, pw, pw_sz, index,
+ key));
+}
+
+static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ u32 index = simple_strtoul(argv[1], NULL, 0);
+ char *key = argv[2];
+ const ssize_t key_sz = strlen(key);
+ const char *pw = (argc < 4) ? NULL : argv[3];
+ const ssize_t pw_sz = pw ? strlen(pw) : 0;
+ struct udevice *dev;
+ int ret;
+
+ ret = get_tpm(&dev);
+ if (ret)
+ return ret;
+
+ if (strlen(key) != TPM2_DIGEST_LEN)
+ return -EINVAL;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ return report_return_code(tpm2_pcr_setauthvalue(dev, pw, pw_sz, index,
+ key, key_sz));
+}
+
+static struct cmd_tbl tpm2_commands[] = {
+ U_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, "", ""),
+ U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
+ U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""),
+ U_BOOT_CMD_MKENT(startup, 0, 1, do_tpm2_startup, "", ""),
+ U_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_self_test, "", ""),
+ U_BOOT_CMD_MKENT(clear, 0, 1, do_tpm2_clear, "", ""),
+ U_BOOT_CMD_MKENT(pcr_extend, 0, 1, do_tpm2_pcr_extend, "", ""),
+ U_BOOT_CMD_MKENT(pcr_read, 0, 1, do_tpm_pcr_read, "", ""),
+ U_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm_get_capability, "", ""),
+ U_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm_dam_reset, "", ""),
+ U_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm_dam_parameters, "", ""),
+ U_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm_change_auth, "", ""),
+ U_BOOT_CMD_MKENT(pcr_setauthpolicy, 0, 1,
+ do_tpm_pcr_setauthpolicy, "", ""),
+ U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1,
+ do_tpm_pcr_setauthvalue, "", ""),
+};
+
+struct cmd_tbl *get_tpm2_commands(unsigned int *size)
+{
+ *size = ARRAY_SIZE(tpm2_commands);
+
+ return tpm2_commands;
+}
+
+U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
+"<command> [<arguments>]\n"
+"\n"
+"device [num device]\n"
+" Show all devices or set the specified device\n"
+"info\n"
+" Show information about the TPM.\n"
+"init\n"
+" Initialize the software stack. Always the first command to issue.\n"
+"startup <mode>\n"
+" Issue a TPM2_Startup command.\n"
+" <mode> is one of:\n"
+" * TPM2_SU_CLEAR (reset state)\n"
+" * TPM2_SU_STATE (preserved state)\n"
+"self_test <type>\n"
+" Test the TPM capabilities.\n"
+" <type> is one of:\n"
+" * full (perform all tests)\n"
+" * continue (only check untested tests)\n"
+"clear <hierarchy>\n"
+" Issue a TPM2_Clear command.\n"
+" <hierarchy> is one of:\n"
+" * TPM2_RH_LOCKOUT\n"
+" * TPM2_RH_PLATFORM\n"
+"pcr_extend <pcr> <digest_addr>\n"
+" Extend PCR #<pcr> with digest at <digest_addr>.\n"
+" <pcr>: index of the PCR\n"
+" <digest_addr>: address of a 32-byte SHA256 digest\n"
+"pcr_read <pcr> <digest_addr>\n"
+" Read PCR #<pcr> to memory address <digest_addr>.\n"
+" <pcr>: index of the PCR\n"
+" <digest_addr>: address to store the a 32-byte SHA256 digest\n"
+"get_capability <capability> <property> <addr> <count>\n"
+" Read and display <count> entries indexed by <capability>/<property>.\n"
+" Values are 4 bytes long and are written at <addr>.\n"
+" <capability>: capability\n"
+" <property>: property\n"
+" <addr>: address to store <count> entries of 4 bytes\n"
+" <count>: number of entries to retrieve\n"
+"dam_reset [<password>]\n"
+" If the TPM is not in a LOCKOUT state, reset the internal error counter.\n"
+" <password>: optional password\n"
+"dam_parameters <max_tries> <recovery_time> <lockout_recovery> [<password>]\n"
+" If the TPM is not in a LOCKOUT state, set the DAM parameters\n"
+" <maxTries>: maximum number of failures before lockout,\n"
+" 0 means always locking\n"
+" <recoveryTime>: time before decrement of the error counter,\n"
+" 0 means no lockout\n"
+" <lockoutRecovery>: time of a lockout (before the next try),\n"
+" 0 means a reboot is needed\n"
+" <password>: optional password of the LOCKOUT hierarchy\n"
+"change_auth <hierarchy> <new_pw> [<old_pw>]\n"
+" <hierarchy>: the hierarchy\n"
+" <new_pw>: new password for <hierarchy>\n"
+" <old_pw>: optional previous password of <hierarchy>\n"
+"pcr_setauthpolicy|pcr_setauthvalue <pcr> <key> [<password>]\n"
+" Change the <key> to access PCR #<pcr>.\n"
+" hierarchy and may be empty.\n"
+" /!\\WARNING: untested function, use at your own risks !\n"
+" <pcr>: index of the PCR\n"
+" <key>: secret to protect the access of PCR #<pcr>\n"
+" <password>: optional password of the PLATFORM hierarchy\n"
+);
diff --git a/roms/u-boot/cmd/tpm_test.c b/roms/u-boot/cmd/tpm_test.c
new file mode 100644
index 000000000..a3ccb12f5
--- /dev/null
+++ b/roms/u-boot/cmd/tpm_test.c
@@ -0,0 +1,571 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <log.h>
+#include <tpm-v1.h>
+#include "tpm-user-utils.h"
+#include <tpm_api.h>
+
+/* Prints error and returns on failure */
+#define TPM_CHECK(tpm_command) do { \
+ uint32_t result; \
+ \
+ result = (tpm_command); \
+ if (result != TPM_SUCCESS) { \
+ printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \
+ __LINE__, result); \
+ return result; \
+ } \
+} while (0)
+
+#define INDEX0 0xda70
+#define INDEX1 0xda71
+#define INDEX2 0xda72
+#define INDEX3 0xda73
+#define INDEX_INITIALISED 0xda80
+#define PHYS_PRESENCE 4
+#define PRESENCE 8
+
+static uint32_t TlclStartupIfNeeded(struct udevice *dev)
+{
+ uint32_t result = tpm_startup(dev, TPM_ST_CLEAR);
+
+ return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
+}
+
+static int test_timer(struct udevice *dev)
+{
+ printf("get_timer(0) = %lu\n", get_timer(0));
+ return 0;
+}
+
+static uint32_t tpm_get_flags(struct udevice *dev, uint8_t *disable,
+ uint8_t *deactivated, uint8_t *nvlocked)
+{
+ struct tpm_permanent_flags pflags;
+ uint32_t result;
+
+ result = tpm1_get_permanent_flags(dev, &pflags);
+ if (result)
+ return result;
+ if (disable)
+ *disable = pflags.disable;
+ if (deactivated)
+ *deactivated = pflags.deactivated;
+ if (nvlocked)
+ *nvlocked = pflags.nv_locked;
+ debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n",
+ pflags.disable, pflags.deactivated, pflags.nv_locked);
+
+ return 0;
+}
+
+static uint32_t tpm_nv_write_value_lock(struct udevice *dev, uint32_t index)
+{
+ debug("TPM: Write lock 0x%x\n", index);
+
+ return tpm_nv_write_value(dev, index, NULL, 0);
+}
+
+static int tpm_is_owned(struct udevice *dev)
+{
+ uint8_t response[TPM_PUBEK_SIZE];
+ uint32_t result;
+
+ result = tpm_read_pubek(dev, response, sizeof(response));
+
+ return result != TPM_SUCCESS;
+}
+
+static int test_early_extend(struct udevice *dev)
+{
+ uint8_t value_in[20];
+ uint8_t value_out[20];
+
+ printf("Testing earlyextend ...");
+ tpm_init(dev);
+ TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
+ TPM_CHECK(tpm_continue_self_test(dev));
+ TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, value_out));
+ printf("done\n");
+ return 0;
+}
+
+static int test_early_nvram(struct udevice *dev)
+{
+ uint32_t x;
+
+ printf("Testing earlynvram ...");
+ tpm_init(dev);
+ TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
+ TPM_CHECK(tpm_continue_self_test(dev));
+ TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+ TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
+ printf("done\n");
+ return 0;
+}
+
+static int test_early_nvram2(struct udevice *dev)
+{
+ uint32_t x;
+
+ printf("Testing earlynvram2 ...");
+ tpm_init(dev);
+ TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR));
+ TPM_CHECK(tpm_continue_self_test(dev));
+ TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+ TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
+ printf("done\n");
+ return 0;
+}
+
+static int test_enable(struct udevice *dev)
+{
+ uint8_t disable = 0, deactivated = 0;
+
+ printf("Testing enable ...\n");
+ tpm_init(dev);
+ TPM_CHECK(TlclStartupIfNeeded(dev));
+ TPM_CHECK(tpm_self_test_full(dev));
+ TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+ TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
+ printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
+ TPM_CHECK(tpm_physical_enable(dev));
+ TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
+ TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
+ printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
+ if (disable == 1 || deactivated == 1)
+ printf("\tfailed to enable or activate\n");
+ printf("\tdone\n");
+ return 0;
+}
+
+#define reboot() do { \
+ printf("\trebooting...\n"); \
+ reset_cpu(); \
+} while (0)
+
+static int test_fast_enable(struct udevice *dev)
+{
+ uint8_t disable = 0, deactivated = 0;
+ int i;
+
+ printf("Testing fastenable ...\n");
+ tpm_init(dev);
+ TPM_CHECK(TlclStartupIfNeeded(dev));
+ TPM_CHECK(tpm_self_test_full(dev));
+ TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+ TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
+ printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
+ for (i = 0; i < 2; i++) {
+ TPM_CHECK(tpm_force_clear(dev));
+ TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
+ printf("\tdisable is %d, deactivated is %d\n", disable,
+ deactivated);
+ assert(disable == 1 && deactivated == 1);
+ TPM_CHECK(tpm_physical_enable(dev));
+ TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
+ TPM_CHECK(tpm_get_flags(dev, &disable, &deactivated, NULL));
+ printf("\tdisable is %d, deactivated is %d\n", disable,
+ deactivated);
+ assert(disable == 0 && deactivated == 0);
+ }
+ printf("\tdone\n");
+ return 0;
+}
+
+static int test_global_lock(struct udevice *dev)
+{
+ uint32_t zero = 0;
+ uint32_t result;
+ uint32_t x;
+
+ printf("Testing globallock ...\n");
+ tpm_init(dev);
+ TPM_CHECK(TlclStartupIfNeeded(dev));
+ TPM_CHECK(tpm_self_test_full(dev));
+ TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+ TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
+ TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero,
+ sizeof(uint32_t)));
+ TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
+ TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero,
+ sizeof(uint32_t)));
+ TPM_CHECK(tpm_set_global_lock(dev));
+ /* Verifies that write to index0 fails */
+ x = 1;
+ result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x));
+ assert(result == TPM_AREA_LOCKED);
+ TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
+ assert(x == 0);
+ /* Verifies that write to index1 is still possible */
+ x = 2;
+ TPM_CHECK(tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
+ TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
+ assert(x == 2);
+ /* Turns off PP */
+ tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
+ /* Verifies that write to index1 fails */
+ x = 3;
+ result = tpm_nv_write_value(dev, INDEX1, (uint8_t *)&x, sizeof(x));
+ assert(result == TPM_BAD_PRESENCE);
+ TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
+ assert(x == 2);
+ printf("\tdone\n");
+ return 0;
+}
+
+static int test_lock(struct udevice *dev)
+{
+ printf("Testing lock ...\n");
+ tpm_init(dev);
+ tpm_startup(dev, TPM_ST_CLEAR);
+ tpm_self_test_full(dev);
+ tpm_tsc_physical_presence(dev, PRESENCE);
+ tpm_nv_write_value_lock(dev, INDEX0);
+ printf("\tLocked 0x%x\n", INDEX0);
+ printf("\tdone\n");
+ return 0;
+}
+
+static void initialise_spaces(struct udevice *dev)
+{
+ uint32_t zero = 0;
+ uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
+
+ printf("\tInitialising spaces\n");
+ tpm1_nv_set_locked(dev); /* useful only the first time */
+ tpm1_nv_define_space(dev, INDEX0, perm, 4);
+ tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero, 4);
+ tpm1_nv_define_space(dev, INDEX1, perm, 4);
+ tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero, 4);
+ tpm1_nv_define_space(dev, INDEX2, perm, 4);
+ tpm_nv_write_value(dev, INDEX2, (uint8_t *)&zero, 4);
+ tpm1_nv_define_space(dev, INDEX3, perm, 4);
+ tpm_nv_write_value(dev, INDEX3, (uint8_t *)&zero, 4);
+ perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
+ TPM_NV_PER_PPWRITE;
+ tpm1_nv_define_space(dev, INDEX_INITIALISED, perm, 1);
+}
+
+static int test_readonly(struct udevice *dev)
+{
+ uint8_t c;
+ uint32_t index_0, index_1, index_2, index_3;
+ int read0, read1, read2, read3;
+
+ printf("Testing readonly ...\n");
+ tpm_init(dev);
+ tpm_startup(dev, TPM_ST_CLEAR);
+ tpm_self_test_full(dev);
+ tpm_tsc_physical_presence(dev, PRESENCE);
+ /*
+ * Checks if initialisation has completed by trying to read-lock a
+ * space that's created at the end of initialisation
+ */
+ if (tpm_nv_read_value(dev, INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
+ /* The initialisation did not complete */
+ initialise_spaces(dev);
+ }
+
+ /* Checks if spaces are OK or messed up */
+ read0 = tpm_nv_read_value(dev, INDEX0, (uint8_t *)&index_0,
+ sizeof(index_0));
+ read1 = tpm_nv_read_value(dev, INDEX1, (uint8_t *)&index_1,
+ sizeof(index_1));
+ read2 = tpm_nv_read_value(dev, INDEX2, (uint8_t *)&index_2,
+ sizeof(index_2));
+ read3 = tpm_nv_read_value(dev, INDEX3, (uint8_t *)&index_3,
+ sizeof(index_3));
+ if (read0 || read1 || read2 || read3) {
+ printf("Invalid contents\n");
+ return 0;
+ }
+
+ /*
+ * Writes space, and locks it. Then attempts to write again.
+ * I really wish I could use the imperative.
+ */
+ index_0 += 1;
+ if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
+ sizeof(index_0) !=
+ TPM_SUCCESS)) {
+ pr_err("\tcould not write index 0\n");
+ }
+ tpm_nv_write_value_lock(dev, INDEX0);
+ if (tpm_nv_write_value(dev, INDEX0, (uint8_t *)&index_0,
+ sizeof(index_0)) ==
+ TPM_SUCCESS)
+ pr_err("\tindex 0 is not locked\n");
+
+ printf("\tdone\n");
+ return 0;
+}
+
+static int test_redefine_unowned(struct udevice *dev)
+{
+ uint32_t perm;
+ uint32_t result;
+ uint32_t x;
+
+ printf("Testing redefine_unowned ...");
+ tpm_init(dev);
+ TPM_CHECK(TlclStartupIfNeeded(dev));
+ TPM_CHECK(tpm_self_test_full(dev));
+ TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+ assert(!tpm_is_owned(dev));
+
+ /* Ensures spaces exist. */
+ TPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)));
+ TPM_CHECK(tpm_nv_read_value(dev, INDEX1, (uint8_t *)&x, sizeof(x)));
+
+ /* Redefines spaces a couple of times. */
+ perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
+ TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm,
+ 2 * sizeof(uint32_t)));
+ TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)));
+ perm = TPM_NV_PER_PPWRITE;
+ TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
+ 2 * sizeof(uint32_t)));
+ TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
+
+ /* Sets the global lock */
+ tpm_set_global_lock(dev);
+
+ /* Verifies that index0 cannot be redefined */
+ result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
+ assert(result == TPM_AREA_LOCKED);
+
+ /* Checks that index1 can */
+ TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm,
+ 2 * sizeof(uint32_t)));
+ TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)));
+
+ /* Turns off PP */
+ tpm_tsc_physical_presence(dev, PHYS_PRESENCE);
+
+ /* Verifies that neither index0 nor index1 can be redefined */
+ result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t));
+ assert(result == TPM_BAD_PRESENCE);
+ result = tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t));
+ assert(result == TPM_BAD_PRESENCE);
+
+ printf("done\n");
+ return 0;
+}
+
+#define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK)
+#define PERMPP TPM_NV_PER_PPWRITE
+
+static int test_space_perm(struct udevice *dev)
+{
+ uint32_t perm;
+
+ printf("Testing spaceperm ...");
+ tpm_init(dev);
+ TPM_CHECK(TlclStartupIfNeeded(dev));
+ TPM_CHECK(tpm_continue_self_test(dev));
+ TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+ TPM_CHECK(tpm_get_permissions(dev, INDEX0, &perm));
+ assert((perm & PERMPPGL) == PERMPPGL);
+ TPM_CHECK(tpm_get_permissions(dev, INDEX1, &perm));
+ assert((perm & PERMPP) == PERMPP);
+ printf("done\n");
+ return 0;
+}
+
+static int test_startup(struct udevice *dev)
+{
+ uint32_t result;
+
+ printf("Testing startup ...\n");
+
+ tpm_init(dev);
+ result = tpm_startup(dev, TPM_ST_CLEAR);
+ if (result != 0 && result != TPM_INVALID_POSTINIT)
+ printf("\ttpm startup failed with 0x%x\n", result);
+ result = tpm_get_flags(dev, NULL, NULL, NULL);
+ if (result != 0)
+ printf("\ttpm getflags failed with 0x%x\n", result);
+ printf("\texecuting SelfTestFull\n");
+ tpm_self_test_full(dev);
+ result = tpm_get_flags(dev, NULL, NULL, NULL);
+ if (result != 0)
+ printf("\ttpm getflags failed with 0x%x\n", result);
+ printf("\tdone\n");
+ return 0;
+}
+
+/*
+ * Runs [op] and ensures it returns success and doesn't run longer than
+ * [time_limit] in milliseconds.
+ */
+#define TTPM_CHECK(op, time_limit) do { \
+ ulong start, time; \
+ uint32_t __result; \
+ \
+ start = get_timer(0); \
+ __result = op; \
+ if (__result != TPM_SUCCESS) { \
+ printf("\t" #op ": error 0x%x\n", __result); \
+ return -1; \
+ } \
+ time = get_timer(start); \
+ printf("\t" #op ": %lu ms\n", time); \
+ if (time > (ulong)time_limit) { \
+ printf("\t" #op " exceeded " #time_limit " ms\n"); \
+ } \
+} while (0)
+
+
+static int test_timing(struct udevice *dev)
+{
+ uint8_t in[20], out[20];
+ uint32_t x;
+
+ printf("Testing timing ...");
+ tpm_init(dev);
+ TTPM_CHECK(TlclStartupIfNeeded(dev), 50);
+ TTPM_CHECK(tpm_continue_self_test(dev), 100);
+ TTPM_CHECK(tpm_self_test_full(dev), 1000);
+ TTPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE), 100);
+ TTPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
+ 100);
+ TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)),
+ 100);
+ TTPM_CHECK(tpm_pcr_extend(dev, 0, in, out), 200);
+ TTPM_CHECK(tpm_set_global_lock(dev), 50);
+ TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100);
+ printf("done\n");
+ return 0;
+}
+
+#define TPM_MAX_NV_WRITES_NOOWNER 64
+
+static int test_write_limit(struct udevice *dev)
+{
+ uint32_t result;
+ int i;
+
+ printf("Testing writelimit ...\n");
+ tpm_init(dev);
+ TPM_CHECK(TlclStartupIfNeeded(dev));
+ TPM_CHECK(tpm_self_test_full(dev));
+ TPM_CHECK(tpm_tsc_physical_presence(dev, PRESENCE));
+ TPM_CHECK(tpm_force_clear(dev));
+ TPM_CHECK(tpm_physical_enable(dev));
+ TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
+
+ for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
+ printf("\twriting %d\n", i);
+ result = tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i,
+ sizeof(i));
+ switch (result) {
+ case TPM_SUCCESS:
+ break;
+ case TPM_MAXNVWRITES:
+ assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
+ default:
+ pr_err("\tunexpected error code %d (0x%x)\n",
+ result, result);
+ }
+ }
+
+ /* Reset write count */
+ TPM_CHECK(tpm_force_clear(dev));
+ TPM_CHECK(tpm_physical_enable(dev));
+ TPM_CHECK(tpm_physical_set_deactivated(dev, 0));
+
+ /* Try writing again. */
+ TPM_CHECK(tpm_nv_write_value(dev, INDEX0, (uint8_t *)&i, sizeof(i)));
+ printf("\tdone\n");
+ return 0;
+}
+
+#define VOIDTEST(XFUNC) \
+ int do_test_##XFUNC(struct cmd_tbl *cmd_tbl, int flag, int argc, \
+ char *const argv[]) \
+ { \
+ struct udevice *dev; \
+ int ret; \
+\
+ ret = get_tpm(&dev); \
+ if (ret) \
+ return ret; \
+ return test_##XFUNC(dev); \
+ }
+
+#define VOIDENT(XNAME) \
+ U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
+
+VOIDTEST(early_extend)
+VOIDTEST(early_nvram)
+VOIDTEST(early_nvram2)
+VOIDTEST(enable)
+VOIDTEST(fast_enable)
+VOIDTEST(global_lock)
+VOIDTEST(lock)
+VOIDTEST(readonly)
+VOIDTEST(redefine_unowned)
+VOIDTEST(space_perm)
+VOIDTEST(startup)
+VOIDTEST(timing)
+VOIDTEST(write_limit)
+VOIDTEST(timer)
+
+static struct cmd_tbl cmd_cros_tpm_sub[] = {
+ VOIDENT(early_extend)
+ VOIDENT(early_nvram)
+ VOIDENT(early_nvram2)
+ VOIDENT(enable)
+ VOIDENT(fast_enable)
+ VOIDENT(global_lock)
+ VOIDENT(lock)
+ VOIDENT(readonly)
+ VOIDENT(redefine_unowned)
+ VOIDENT(space_perm)
+ VOIDENT(startup)
+ VOIDENT(timing)
+ VOIDENT(write_limit)
+ VOIDENT(timer)
+};
+
+static int do_tpmtest(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c;
+ int i;
+
+ printf("argc = %d, argv = ", argc);
+
+ for (i = 0; i < argc; i++)
+ printf(" %s", argv[i]);
+
+ printf("\n------\n");
+
+ argc--;
+ argv++;
+ c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
+ ARRAY_SIZE(cmd_cros_tpm_sub));
+ return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
+}
+
+U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
+ "\n\tearly_extend\n"
+ "\tearly_nvram\n"
+ "\tearly_nvram2\n"
+ "\tenable\n"
+ "\tfast_enable\n"
+ "\tglobal_lock\n"
+ "\tlock\n"
+ "\treadonly\n"
+ "\tredefine_unowned\n"
+ "\tspace_perm\n"
+ "\tstartup\n"
+ "\ttiming\n"
+ "\twrite_limit\n");
diff --git a/roms/u-boot/cmd/trace.c b/roms/u-boot/cmd/trace.c
new file mode 100644
index 000000000..4ce47c762
--- /dev/null
+++ b/roms/u-boot/cmd/trace.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <mapmem.h>
+#include <trace.h>
+#include <asm/io.h>
+
+static int get_args(int argc, char *const argv[], char **buff,
+ size_t *buff_ptr, size_t *buff_size)
+{
+ if (argc < 2)
+ return -1;
+ if (argc < 4) {
+ *buff_size = env_get_ulong("profsize", 16, 0);
+ *buff = map_sysmem(env_get_ulong("profbase", 16, 0),
+ *buff_size);
+ *buff_ptr = env_get_ulong("profoffset", 16, 0);
+ } else {
+ *buff_size = simple_strtoul(argv[3], NULL, 16);
+ *buff = map_sysmem(simple_strtoul(argv[2], NULL, 16),
+ *buff_size);
+ *buff_ptr = 0;
+ };
+ return 0;
+}
+
+static int create_func_list(int argc, char *const argv[])
+{
+ size_t buff_size, avail, buff_ptr, needed, used;
+ char *buff;
+ int err;
+
+ if (get_args(argc, argv, &buff, &buff_ptr, &buff_size))
+ return -1;
+
+ avail = buff_size - buff_ptr;
+ err = trace_list_functions(buff + buff_ptr, avail, &needed);
+ if (err)
+ printf("Error: truncated (%#zx bytes needed)\n", needed);
+ used = min(avail, (size_t)needed);
+ printf("Function trace dumped to %08lx, size %#zx\n",
+ (ulong)map_to_sysmem(buff + buff_ptr), used);
+ env_set_hex("profbase", map_to_sysmem(buff));
+ env_set_hex("profsize", buff_size);
+ env_set_hex("profoffset", buff_ptr + used);
+
+ return 0;
+}
+
+static int create_call_list(int argc, char *const argv[])
+{
+ size_t buff_size, avail, buff_ptr, needed, used;
+ char *buff;
+ int err;
+
+ if (get_args(argc, argv, &buff, &buff_ptr, &buff_size))
+ return -1;
+
+ avail = buff_size - buff_ptr;
+ err = trace_list_calls(buff + buff_ptr, avail, &needed);
+ if (err)
+ printf("Error: truncated (%#zx bytes needed)\n", needed);
+ used = min(avail, (size_t)needed);
+ printf("Call list dumped to %08lx, size %#zx\n",
+ (ulong)map_to_sysmem(buff + buff_ptr), used);
+
+ env_set_hex("profbase", map_to_sysmem(buff));
+ env_set_hex("profsize", buff_size);
+ env_set_hex("profoffset", buff_ptr + used);
+
+ return 0;
+}
+
+int do_trace(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const char *cmd = argc < 2 ? NULL : argv[1];
+
+ if (!cmd)
+ return cmd_usage(cmdtp);
+ switch (*cmd) {
+ case 'p':
+ trace_set_enabled(0);
+ break;
+ case 'c':
+ if (create_call_list(argc, argv))
+ return cmd_usage(cmdtp);
+ break;
+ case 'r':
+ trace_set_enabled(1);
+ break;
+ case 'f':
+ if (create_func_list(argc, argv))
+ return cmd_usage(cmdtp);
+ break;
+ case 's':
+ trace_print_stats();
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ trace, 4, 1, do_trace,
+ "trace utility commands",
+ "stats - display tracing statistics\n"
+ "trace pause - pause tracing\n"
+ "trace resume - resume tracing\n"
+ "trace funclist [<addr> <size>] - dump function list into buffer\n"
+ "trace calls [<addr> <size>] "
+ "- dump function call trace into buffer"
+);
diff --git a/roms/u-boot/cmd/tsi148.c b/roms/u-boot/cmd/tsi148.c
new file mode 100644
index 000000000..2eae14f87
--- /dev/null
+++ b/roms/u-boot/cmd/tsi148.c
@@ -0,0 +1,472 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009 Reinhard Arlt, reinhard.arlt@esd-electronics.com
+ *
+ * base on universe.h by
+ *
+ * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com
+ */
+
+#include <common.h>
+#include <command.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#include <tsi148.h>
+
+#define LPCI_VENDOR PCI_VENDOR_ID_TUNDRA
+#define LPCI_DEVICE PCI_DEVICE_ID_TUNDRA_TSI148
+
+typedef struct _TSI148_DEV TSI148_DEV;
+
+struct _TSI148_DEV {
+ int bus;
+ pci_dev_t busdevfn;
+ TSI148 *uregs;
+ unsigned int pci_bs;
+};
+
+static TSI148_DEV *dev;
+
+/*
+ * Most of the TSI148 register are BIGENDIAN
+ * This is the reason for the __raw_writel(htonl(x), x) usage!
+ */
+
+int tsi148_init(void)
+{
+ int j, result;
+ pci_dev_t busdevfn;
+ unsigned int val;
+
+ busdevfn = pci_find_device(LPCI_VENDOR, LPCI_DEVICE, 0);
+ if (busdevfn == -1) {
+ puts("Tsi148: No Tundra Tsi148 found!\n");
+ return -1;
+ }
+
+ /* Lets turn Latency off */
+ pci_write_config_dword(busdevfn, 0x0c, 0);
+
+ dev = malloc(sizeof(*dev));
+ if (NULL == dev) {
+ puts("Tsi148: No memory!\n");
+ return -1;
+ }
+
+ memset(dev, 0, sizeof(*dev));
+ dev->busdevfn = busdevfn;
+
+ pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val);
+ val &= ~0xf;
+ dev->uregs = (TSI148 *)val;
+
+ debug("Tsi148: Base : %p\n", dev->uregs);
+
+ /* check mapping */
+ debug("Tsi148: Read via mapping, PCI_ID = %08X\n",
+ readl(&dev->uregs->pci_id));
+ if (((LPCI_DEVICE << 16) | LPCI_VENDOR) != readl(&dev->uregs->pci_id)) {
+ printf("Tsi148: Cannot read PCI-ID via Mapping: %08x\n",
+ readl(&dev->uregs->pci_id));
+ result = -1;
+ goto break_30;
+ }
+
+ debug("Tsi148: PCI_BS = %08X\n", readl(&dev->uregs->pci_mbarl));
+
+ dev->pci_bs = readl(&dev->uregs->pci_mbarl);
+
+ /* turn off windows */
+ for (j = 0; j < 8; j++) {
+ __raw_writel(htonl(0x00000000), &dev->uregs->outbound[j].otat);
+ __raw_writel(htonl(0x00000000), &dev->uregs->inbound[j].itat);
+ }
+
+ /* Tsi148 VME timeout etc */
+ __raw_writel(htonl(0x00000084), &dev->uregs->vctrl);
+
+#ifdef DEBUG
+ if ((__raw_readl(&dev->uregs->vstat) & 0x00000100) != 0)
+ printf("Tsi148: System Controller!\n");
+ else
+ printf("Tsi148: Not System Controller!\n");
+#endif
+
+ /*
+ * Lets turn off interrupts
+ */
+ /* Disable interrupts in Tsi148 first */
+ __raw_writel(htonl(0x00000000), &dev->uregs->inten);
+ /* Disable interrupt out */
+ __raw_writel(htonl(0x00000000), &dev->uregs->inteo);
+ eieio();
+ /* Reset all IRQ's */
+ __raw_writel(htonl(0x03ff3f00), &dev->uregs->intc);
+ /* Map all ints to 0 */
+ __raw_writel(htonl(0x00000000), &dev->uregs->intm1);
+ __raw_writel(htonl(0x00000000), &dev->uregs->intm2);
+ eieio();
+
+ val = __raw_readl(&dev->uregs->vstat);
+ val &= ~(0x00004000);
+ __raw_writel(val, &dev->uregs->vstat);
+ eieio();
+
+ debug("Tsi148: register struct size %08x\n", sizeof(TSI148));
+
+ return 0;
+
+ break_30:
+ free(dev);
+ dev = NULL;
+
+ return result;
+}
+
+/*
+ * Create pci slave window (access: pci -> vme)
+ */
+int tsi148_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr,
+ int size, int vam, int vdw)
+{
+ int result, i;
+ unsigned int ctl = 0;
+
+ if (NULL == dev) {
+ result = -1;
+ goto exit_10;
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (0x00000000 == readl(&dev->uregs->outbound[i].otat))
+ break;
+ }
+
+ if (i > 7) {
+ printf("Tsi148: No Image available\n");
+ result = -1;
+ goto exit_10;
+ }
+
+ debug("Tsi148: Using image %d\n", i);
+
+ printf("Tsi148: Pci addr %08x\n", pciAddr);
+
+ __raw_writel(htonl(pciAddr), &dev->uregs->outbound[i].otsal);
+ __raw_writel(0x00000000, &dev->uregs->outbound[i].otsau);
+ __raw_writel(htonl(pciAddr + size), &dev->uregs->outbound[i].oteal);
+ __raw_writel(0x00000000, &dev->uregs->outbound[i].oteau);
+ __raw_writel(htonl(vmeAddr - pciAddr), &dev->uregs->outbound[i].otofl);
+ __raw_writel(0x00000000, &dev->uregs->outbound[i].otofu);
+
+ switch (vam & VME_AM_Axx) {
+ case VME_AM_A16:
+ ctl = 0x00000000;
+ break;
+ case VME_AM_A24:
+ ctl = 0x00000001;
+ break;
+ case VME_AM_A32:
+ ctl = 0x00000002;
+ break;
+ }
+
+ switch (vam & VME_AM_Mxx) {
+ case VME_AM_DATA:
+ ctl |= 0x00000000;
+ break;
+ case VME_AM_PROG:
+ ctl |= 0x00000010;
+ break;
+ }
+
+ if (vam & VME_AM_SUP)
+ ctl |= 0x00000020;
+
+ switch (vdw & VME_FLAG_Dxx) {
+ case VME_FLAG_D16:
+ ctl |= 0x00000000;
+ break;
+ case VME_FLAG_D32:
+ ctl |= 0x00000040;
+ break;
+ }
+
+ ctl |= 0x80040000; /* enable, no prefetch */
+
+ __raw_writel(htonl(ctl), &dev->uregs->outbound[i].otat);
+
+ debug("Tsi148: window-addr =%p\n",
+ &dev->uregs->outbound[i].otsau);
+ debug("Tsi148: pci slave window[%d] attr =%08x\n",
+ i, ntohl(__raw_readl(&dev->uregs->outbound[i].otat)));
+ debug("Tsi148: pci slave window[%d] start =%08x\n",
+ i, ntohl(__raw_readl(&dev->uregs->outbound[i].otsal)));
+ debug("Tsi148: pci slave window[%d] end =%08x\n",
+ i, ntohl(__raw_readl(&dev->uregs->outbound[i].oteal)));
+ debug("Tsi148: pci slave window[%d] offset=%08x\n",
+ i, ntohl(__raw_readl(&dev->uregs->outbound[i].otofl)));
+
+ return 0;
+
+ exit_10:
+ return -result;
+}
+
+unsigned int tsi148_eval_vam(int vam)
+{
+ unsigned int ctl = 0;
+
+ switch (vam & VME_AM_Axx) {
+ case VME_AM_A16:
+ ctl = 0x00000000;
+ break;
+ case VME_AM_A24:
+ ctl = 0x00000010;
+ break;
+ case VME_AM_A32:
+ ctl = 0x00000020;
+ break;
+ }
+ switch (vam & VME_AM_Mxx) {
+ case VME_AM_DATA:
+ ctl |= 0x00000001;
+ break;
+ case VME_AM_PROG:
+ ctl |= 0x00000002;
+ break;
+ case (VME_AM_PROG | VME_AM_DATA):
+ ctl |= 0x00000003;
+ break;
+ }
+
+ if (vam & VME_AM_SUP)
+ ctl |= 0x00000008;
+ if (vam & VME_AM_USR)
+ ctl |= 0x00000004;
+
+ return ctl;
+}
+
+/*
+ * Create vme slave window (access: vme -> pci)
+ */
+int tsi148_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr,
+ int size, int vam)
+{
+ int result, i;
+ unsigned int ctl = 0;
+
+ if (NULL == dev) {
+ result = -1;
+ goto exit_10;
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (0x00000000 == readl(&dev->uregs->inbound[i].itat))
+ break;
+ }
+
+ if (i > 7) {
+ printf("Tsi148: No Image available\n");
+ result = -1;
+ goto exit_10;
+ }
+
+ debug("Tsi148: Using image %d\n", i);
+
+ __raw_writel(htonl(vmeAddr), &dev->uregs->inbound[i].itsal);
+ __raw_writel(0x00000000, &dev->uregs->inbound[i].itsau);
+ __raw_writel(htonl(vmeAddr + size), &dev->uregs->inbound[i].iteal);
+ __raw_writel(0x00000000, &dev->uregs->inbound[i].iteau);
+ __raw_writel(htonl(pciAddr - vmeAddr), &dev->uregs->inbound[i].itofl);
+ if (vmeAddr > pciAddr)
+ __raw_writel(0xffffffff, &dev->uregs->inbound[i].itofu);
+ else
+ __raw_writel(0x00000000, &dev->uregs->inbound[i].itofu);
+
+ ctl = tsi148_eval_vam(vam);
+ ctl |= 0x80000000; /* enable */
+ __raw_writel(htonl(ctl), &dev->uregs->inbound[i].itat);
+
+ debug("Tsi148: window-addr =%p\n",
+ &dev->uregs->inbound[i].itsau);
+ debug("Tsi148: vme slave window[%d] attr =%08x\n",
+ i, ntohl(__raw_readl(&dev->uregs->inbound[i].itat)));
+ debug("Tsi148: vme slave window[%d] start =%08x\n",
+ i, ntohl(__raw_readl(&dev->uregs->inbound[i].itsal)));
+ debug("Tsi148: vme slave window[%d] end =%08x\n",
+ i, ntohl(__raw_readl(&dev->uregs->inbound[i].iteal)));
+ debug("Tsi148: vme slave window[%d] offset=%08x\n",
+ i, ntohl(__raw_readl(&dev->uregs->inbound[i].itofl)));
+
+ return 0;
+
+ exit_10:
+ return -result;
+}
+
+/*
+ * Create vme slave window (access: vme -> gcsr)
+ */
+int tsi148_vme_gcsr_window(unsigned int vmeAddr, int vam)
+{
+ int result;
+ unsigned int ctl;
+
+ result = 0;
+
+ if (NULL == dev) {
+ result = 1;
+ } else {
+ __raw_writel(htonl(vmeAddr), &dev->uregs->gbal);
+ __raw_writel(0x00000000, &dev->uregs->gbau);
+
+ ctl = tsi148_eval_vam(vam);
+ ctl |= 0x00000080; /* enable */
+ __raw_writel(htonl(ctl), &dev->uregs->gcsrat);
+ }
+
+ return result;
+}
+
+/*
+ * Create vme slave window (access: vme -> crcsr)
+ */
+int tsi148_vme_crcsr_window(unsigned int vmeAddr)
+{
+ int result;
+ unsigned int ctl;
+
+ result = 0;
+
+ if (NULL == dev) {
+ result = 1;
+ } else {
+ __raw_writel(htonl(vmeAddr), &dev->uregs->crol);
+ __raw_writel(0x00000000, &dev->uregs->crou);
+
+ ctl = 0x00000080; /* enable */
+ __raw_writel(htonl(ctl), &dev->uregs->crat);
+ }
+
+ return result;
+}
+
+/*
+ * Create vme slave window (access: vme -> crg)
+ */
+int tsi148_vme_crg_window(unsigned int vmeAddr, int vam)
+{
+ int result;
+ unsigned int ctl;
+
+ result = 0;
+
+ if (NULL == dev) {
+ result = 1;
+ } else {
+ __raw_writel(htonl(vmeAddr), &dev->uregs->cbal);
+ __raw_writel(0x00000000, &dev->uregs->cbau);
+
+ ctl = tsi148_eval_vam(vam);
+ ctl |= 0x00000080; /* enable */
+ __raw_writel(htonl(ctl), &dev->uregs->crgat);
+ }
+
+ return result;
+}
+
+/*
+ * Tundra Tsi148 configuration
+ */
+int do_tsi148(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, vdw = 0;
+ char cmd = 'x';
+
+ /* get parameter */
+ if (argc > 1)
+ cmd = argv[1][0];
+ if (argc > 2)
+ addr1 = simple_strtoul(argv[2], NULL, 16);
+ if (argc > 3)
+ addr2 = simple_strtoul(argv[3], NULL, 16);
+ if (argc > 4)
+ size = simple_strtoul(argv[4], NULL, 16);
+ if (argc > 5)
+ vam = simple_strtoul(argv[5], NULL, 16);
+ if (argc > 6)
+ vdw = simple_strtoul(argv[6], NULL, 16);
+
+ switch (cmd) {
+ case 'c':
+ if (strcmp(argv[1], "crg") == 0) {
+ vam = addr2;
+ printf("Tsi148: Configuring VME CRG Window "
+ "(VME->CRG):\n");
+ printf(" vme=%08lx vam=%02lx\n", addr1, vam);
+ tsi148_vme_crg_window(addr1, vam);
+ } else {
+ printf("Tsi148: Configuring VME CR/CSR Window "
+ "(VME->CR/CSR):\n");
+ printf(" pci=%08lx\n", addr1);
+ tsi148_vme_crcsr_window(addr1);
+ }
+ break;
+ case 'i': /* init */
+ tsi148_init();
+ break;
+ case 'g':
+ vam = addr2;
+ printf("Tsi148: Configuring VME GCSR Window (VME->GCSR):\n");
+ printf(" vme=%08lx vam=%02lx\n", addr1, vam);
+ tsi148_vme_gcsr_window(addr1, vam);
+ break;
+ case 'v': /* vme */
+ printf("Tsi148: Configuring VME Slave Window (VME->PCI):\n");
+ printf(" vme=%08lx pci=%08lx size=%08lx vam=%02lx\n",
+ addr1, addr2, size, vam);
+ tsi148_vme_slave_window(addr1, addr2, size, vam);
+ break;
+ case 'p': /* pci */
+ printf("Tsi148: Configuring PCI Slave Window (PCI->VME):\n");
+ printf(" pci=%08lx vme=%08lx size=%08lx vam=%02lx vdw=%02lx\n",
+ addr1, addr2, size, vam, vdw);
+ tsi148_pci_slave_window(addr1, addr2, size, vam, vdw);
+ break;
+ default:
+ printf("Tsi148: Command %s not supported!\n", argv[1]);
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ tsi148, 7, 1, do_tsi148,
+ "initialize and configure Turndra Tsi148\n",
+ "init\n"
+ " - initialize tsi148\n"
+ "tsi148 vme [vme_addr] [pci_addr] [size] [vam]\n"
+ " - create vme slave window (access: vme->pci)\n"
+ "tsi148 pci [pci_addr] [vme_addr] [size] [vam] [vdw]\n"
+ " - create pci slave window (access: pci->vme)\n"
+ "tsi148 crg [vme_addr] [vam]\n"
+ " - create vme slave window: (access vme->CRG\n"
+ "tsi148 crcsr [pci_addr]\n"
+ " - create vme slave window: (access vme->CR/CSR\n"
+ "tsi148 gcsr [vme_addr] [vam]\n"
+ " - create vme slave window: (access vme->GCSR\n"
+ " [vam] = VMEbus Address-Modifier: 01 -> A16 Address Space\n"
+ " 02 -> A24 Address Space\n"
+ " 03 -> A32 Address Space\n"
+ " 04 -> Usr AM Code\n"
+ " 08 -> Supervisor AM Code\n"
+ " 10 -> Data AM Code\n"
+ " 20 -> Program AM Code\n"
+ " [vdw] = VMEbus Maximum Datawidth: 02 -> D16 Data Width\n"
+ " 03 -> D32 Data Width\n"
+);
diff --git a/roms/u-boot/cmd/ubi.c b/roms/u-boot/cmd/ubi.c
new file mode 100644
index 000000000..cb14e3e1e
--- /dev/null
+++ b/roms/u-boot/cmd/ubi.c
@@ -0,0 +1,744 @@
+/*
+ * Unsorted Block Image commands
+ *
+ * Copyright (C) 2008 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * Copyright 2008-2009 Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <exports.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <mtd.h>
+#include <nand.h>
+#include <onenand_uboot.h>
+#include <dm/devres.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/err.h>
+#include <ubi_uboot.h>
+#include <linux/errno.h>
+#include <jffs2/load_kernel.h>
+
+#undef ubi_msg
+#define ubi_msg(fmt, ...) printf("UBI: " fmt "\n", ##__VA_ARGS__)
+
+/* Private own data */
+static struct ubi_device *ubi;
+
+#ifdef CONFIG_CMD_UBIFS
+#include <ubifs_uboot.h>
+#endif
+
+static void display_volume_info(struct ubi_device *ubi)
+{
+ int i;
+
+ for (i = 0; i < (ubi->vtbl_slots + 1); i++) {
+ if (!ubi->volumes[i])
+ continue; /* Empty record */
+ ubi_dump_vol_info(ubi->volumes[i]);
+ }
+}
+
+static void display_ubi_info(struct ubi_device *ubi)
+{
+ ubi_msg("MTD device name: \"%s\"", ubi->mtd->name);
+ ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
+ ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
+ ubi->peb_size, ubi->peb_size >> 10);
+ ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size);
+ ubi_msg("number of good PEBs: %d", ubi->good_peb_count);
+ ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count);
+ ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size);
+ ubi_msg("VID header offset: %d (aligned %d)",
+ ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
+ ubi_msg("data offset: %d", ubi->leb_start);
+ ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots);
+ ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD);
+ ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
+ ubi_msg("number of user volumes: %d",
+ ubi->vol_count - UBI_INT_VOL_COUNT);
+ ubi_msg("available PEBs: %d", ubi->avail_pebs);
+ ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs);
+ ubi_msg("number of PEBs reserved for bad PEB handling: %d",
+ ubi->beb_rsvd_pebs);
+ ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
+}
+
+static int ubi_info(int layout)
+{
+ if (layout)
+ display_volume_info(ubi);
+ else
+ display_ubi_info(ubi);
+
+ return 0;
+}
+
+static int ubi_check_volumename(const struct ubi_volume *vol, char *name)
+{
+ return strcmp(vol->name, name);
+}
+
+static int ubi_check(char *name)
+{
+ int i;
+
+ for (i = 0; i < (ubi->vtbl_slots + 1); i++) {
+ if (!ubi->volumes[i])
+ continue; /* Empty record */
+
+ if (!ubi_check_volumename(ubi->volumes[i], name))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int verify_mkvol_req(const struct ubi_device *ubi,
+ const struct ubi_mkvol_req *req)
+{
+ int n, err = EINVAL;
+
+ if (req->bytes < 0 || req->alignment < 0 || req->vol_type < 0 ||
+ req->name_len < 0)
+ goto bad;
+
+ if ((req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots) &&
+ req->vol_id != UBI_VOL_NUM_AUTO)
+ goto bad;
+
+ if (req->alignment == 0)
+ goto bad;
+
+ if (req->bytes == 0) {
+ printf("No space left in UBI device!\n");
+ err = ENOMEM;
+ goto bad;
+ }
+
+ if (req->vol_type != UBI_DYNAMIC_VOLUME &&
+ req->vol_type != UBI_STATIC_VOLUME)
+ goto bad;
+
+ if (req->alignment > ubi->leb_size)
+ goto bad;
+
+ n = req->alignment % ubi->min_io_size;
+ if (req->alignment != 1 && n)
+ goto bad;
+
+ if (req->name_len > UBI_VOL_NAME_MAX) {
+ printf("Name too long!\n");
+ err = ENAMETOOLONG;
+ goto bad;
+ }
+
+ return 0;
+bad:
+ return err;
+}
+
+static int ubi_create_vol(char *volume, int64_t size, int dynamic, int vol_id,
+ bool skipcheck)
+{
+ struct ubi_mkvol_req req;
+ int err;
+
+ if (dynamic)
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ else
+ req.vol_type = UBI_STATIC_VOLUME;
+
+ req.vol_id = vol_id;
+ req.alignment = 1;
+ req.bytes = size;
+
+ strcpy(req.name, volume);
+ req.name_len = strlen(volume);
+ req.name[req.name_len] = '\0';
+ req.flags = 0;
+ if (skipcheck)
+ req.flags |= UBI_VOL_SKIP_CRC_CHECK_FLG;
+
+ /* It's duplicated at drivers/mtd/ubi/cdev.c */
+ err = verify_mkvol_req(ubi, &req);
+ if (err) {
+ printf("verify_mkvol_req failed %d\n", err);
+ return err;
+ }
+ printf("Creating %s volume %s of size %lld\n",
+ dynamic ? "dynamic" : "static", volume, size);
+ /* Call real ubi create volume */
+ return ubi_create_volume(ubi, &req);
+}
+
+static struct ubi_volume *ubi_find_volume(char *volume)
+{
+ struct ubi_volume *vol = NULL;
+ int i;
+
+ for (i = 0; i < ubi->vtbl_slots; i++) {
+ vol = ubi->volumes[i];
+ if (vol && !strcmp(vol->name, volume))
+ return vol;
+ }
+
+ printf("Volume %s not found!\n", volume);
+ return NULL;
+}
+
+static int ubi_remove_vol(char *volume)
+{
+ int err, reserved_pebs, i;
+ struct ubi_volume *vol;
+
+ vol = ubi_find_volume(volume);
+ if (vol == NULL)
+ return ENODEV;
+
+ printf("Remove UBI volume %s (id %d)\n", vol->name, vol->vol_id);
+
+ if (ubi->ro_mode) {
+ printf("It's read-only mode\n");
+ err = EROFS;
+ goto out_err;
+ }
+
+ err = ubi_change_vtbl_record(ubi, vol->vol_id, NULL);
+ if (err) {
+ printf("Error changing Vol tabel record err=%x\n", err);
+ goto out_err;
+ }
+ reserved_pebs = vol->reserved_pebs;
+ for (i = 0; i < vol->reserved_pebs; i++) {
+ err = ubi_eba_unmap_leb(ubi, vol, i);
+ if (err)
+ goto out_err;
+ }
+
+ kfree(vol->eba_tbl);
+ ubi->volumes[vol->vol_id]->eba_tbl = NULL;
+ ubi->volumes[vol->vol_id] = NULL;
+
+ ubi->rsvd_pebs -= reserved_pebs;
+ ubi->avail_pebs += reserved_pebs;
+ i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
+ if (i > 0) {
+ i = ubi->avail_pebs >= i ? i : ubi->avail_pebs;
+ ubi->avail_pebs -= i;
+ ubi->rsvd_pebs += i;
+ ubi->beb_rsvd_pebs += i;
+ if (i > 0)
+ ubi_msg("reserve more %d PEBs", i);
+ }
+ ubi->vol_count -= 1;
+
+ return 0;
+out_err:
+ ubi_err(ubi, "cannot remove volume %s, error %d", volume, err);
+ if (err < 0)
+ err = -err;
+ return err;
+}
+
+static int ubi_rename_vol(char *oldname, char *newname)
+{
+ struct ubi_volume *vol;
+ struct ubi_rename_entry rename;
+ struct ubi_volume_desc desc;
+ struct list_head list;
+
+ vol = ubi_find_volume(oldname);
+ if (!vol) {
+ printf("%s: volume %s doesn't exist\n", __func__, oldname);
+ return ENODEV;
+ }
+
+ if (!ubi_check(newname)) {
+ printf("%s: volume %s already exist\n", __func__, newname);
+ return EINVAL;
+ }
+
+ printf("Rename UBI volume %s to %s\n", oldname, newname);
+
+ if (ubi->ro_mode) {
+ printf("%s: ubi device is in read-only mode\n", __func__);
+ return EROFS;
+ }
+
+ rename.new_name_len = strlen(newname);
+ strcpy(rename.new_name, newname);
+ rename.remove = 0;
+ desc.vol = vol;
+ desc.mode = 0;
+ rename.desc = &desc;
+ INIT_LIST_HEAD(&rename.list);
+ INIT_LIST_HEAD(&list);
+ list_add(&rename.list, &list);
+
+ return ubi_rename_volumes(ubi, &list);
+}
+
+static int ubi_volume_continue_write(char *volume, void *buf, size_t size)
+{
+ int err = 1;
+ struct ubi_volume *vol;
+
+ vol = ubi_find_volume(volume);
+ if (vol == NULL)
+ return ENODEV;
+
+ err = ubi_more_update_data(ubi, vol, buf, size);
+ if (err < 0) {
+ printf("Couldnt or partially wrote data\n");
+ return -err;
+ }
+
+ if (err) {
+ size = err;
+
+ err = ubi_check_volume(ubi, vol->vol_id);
+ if (err < 0)
+ return -err;
+
+ if (err) {
+ ubi_warn(ubi, "volume %d on UBI device %d is corrupt",
+ vol->vol_id, ubi->ubi_num);
+ vol->corrupted = 1;
+ }
+
+ vol->checked = 1;
+ ubi_gluebi_updated(vol);
+ }
+
+ return 0;
+}
+
+int ubi_volume_begin_write(char *volume, void *buf, size_t size,
+ size_t full_size)
+{
+ int err = 1;
+ int rsvd_bytes = 0;
+ struct ubi_volume *vol;
+
+ vol = ubi_find_volume(volume);
+ if (vol == NULL)
+ return ENODEV;
+
+ rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad);
+ if (size > rsvd_bytes) {
+ printf("size > volume size! Aborting!\n");
+ return EINVAL;
+ }
+
+ err = ubi_start_update(ubi, vol, full_size);
+ if (err < 0) {
+ printf("Cannot start volume update\n");
+ return -err;
+ }
+
+ return ubi_volume_continue_write(volume, buf, size);
+}
+
+int ubi_volume_write(char *volume, void *buf, size_t size)
+{
+ return ubi_volume_begin_write(volume, buf, size, size);
+}
+
+int ubi_volume_read(char *volume, char *buf, size_t size)
+{
+ int err, lnum, off, len, tbuf_size;
+ void *tbuf;
+ unsigned long long tmp;
+ struct ubi_volume *vol;
+ loff_t offp = 0;
+ size_t len_read;
+
+ vol = ubi_find_volume(volume);
+ if (vol == NULL)
+ return ENODEV;
+
+ if (vol->updating) {
+ printf("updating");
+ return EBUSY;
+ }
+ if (vol->upd_marker) {
+ printf("damaged volume, update marker is set");
+ return EBADF;
+ }
+ if (offp == vol->used_bytes)
+ return 0;
+
+ if (size == 0) {
+ printf("No size specified -> Using max size (%lld)\n", vol->used_bytes);
+ size = vol->used_bytes;
+ }
+
+ printf("Read %zu bytes from volume %s to %p\n", size, volume, buf);
+
+ if (vol->corrupted)
+ printf("read from corrupted volume %d", vol->vol_id);
+ if (offp + size > vol->used_bytes)
+ size = vol->used_bytes - offp;
+
+ tbuf_size = vol->usable_leb_size;
+ if (size < tbuf_size)
+ tbuf_size = ALIGN(size, ubi->min_io_size);
+ tbuf = malloc_cache_aligned(tbuf_size);
+ if (!tbuf) {
+ printf("NO MEM\n");
+ return ENOMEM;
+ }
+ len = size > tbuf_size ? tbuf_size : size;
+
+ tmp = offp;
+ off = do_div(tmp, vol->usable_leb_size);
+ lnum = tmp;
+ len_read = size;
+ do {
+ if (off + len >= vol->usable_leb_size)
+ len = vol->usable_leb_size - off;
+
+ err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0);
+ if (err) {
+ printf("read err %x\n", err);
+ err = -err;
+ break;
+ }
+ off += len;
+ if (off == vol->usable_leb_size) {
+ lnum += 1;
+ off -= vol->usable_leb_size;
+ }
+
+ size -= len;
+ offp += len;
+
+ memcpy(buf, tbuf, len);
+
+ buf += len;
+ len = size > tbuf_size ? tbuf_size : size;
+ } while (size);
+
+ if (!size)
+ env_set_hex("filesize", len_read);
+
+ free(tbuf);
+ return err;
+}
+
+static int ubi_dev_scan(struct mtd_info *info, const char *vid_header_offset)
+{
+ char ubi_mtd_param_buffer[80];
+ int err;
+
+ if (!vid_header_offset)
+ sprintf(ubi_mtd_param_buffer, "%s", info->name);
+ else
+ sprintf(ubi_mtd_param_buffer, "%s,%s", info->name,
+ vid_header_offset);
+
+ err = ubi_mtd_param_parse(ubi_mtd_param_buffer, NULL);
+ if (err)
+ return -err;
+
+ err = ubi_init();
+ if (err)
+ return -err;
+
+ return 0;
+}
+
+static int ubi_set_skip_check(char *volume, bool skip_check)
+{
+ struct ubi_vtbl_record vtbl_rec;
+ struct ubi_volume *vol;
+
+ vol = ubi_find_volume(volume);
+ if (!vol)
+ return ENODEV;
+
+ printf("%sing skip_check on volume %s\n",
+ skip_check ? "Sett" : "Clear", volume);
+
+ vtbl_rec = ubi->vtbl[vol->vol_id];
+ if (skip_check) {
+ vtbl_rec.flags |= UBI_VTBL_SKIP_CRC_CHECK_FLG;
+ vol->skip_check = 1;
+ } else {
+ vtbl_rec.flags &= ~UBI_VTBL_SKIP_CRC_CHECK_FLG;
+ vol->skip_check = 0;
+ }
+
+ return ubi_change_vtbl_record(ubi, vol->vol_id, &vtbl_rec);
+}
+
+static int ubi_detach(void)
+{
+#ifdef CONFIG_CMD_UBIFS
+ /*
+ * Automatically unmount UBIFS partition when user
+ * changes the UBI device. Otherwise the following
+ * UBIFS commands will crash.
+ */
+ if (ubifs_is_mounted())
+ cmd_ubifs_umount();
+#endif
+
+ /*
+ * Call ubi_exit() before re-initializing the UBI subsystem
+ */
+ if (ubi)
+ ubi_exit();
+
+ ubi = NULL;
+
+ return 0;
+}
+
+int ubi_part(char *part_name, const char *vid_header_offset)
+{
+ struct mtd_info *mtd;
+ int err = 0;
+
+ ubi_detach();
+
+ mtd_probe_devices();
+ mtd = get_mtd_device_nm(part_name);
+ if (IS_ERR(mtd)) {
+ printf("Partition %s not found!\n", part_name);
+ return 1;
+ }
+ put_mtd_device(mtd);
+
+ err = ubi_dev_scan(mtd, vid_header_offset);
+ if (err) {
+ printf("UBI init error %d\n", err);
+ printf("Please check, if the correct MTD partition is used (size big enough?)\n");
+ return err;
+ }
+
+ ubi = ubi_devices[0];
+
+ return 0;
+}
+
+static int do_ubi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int64_t size = 0;
+ ulong addr = 0;
+ bool skipcheck = false;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "detach") == 0)
+ return ubi_detach();
+
+ if (strcmp(argv[1], "part") == 0) {
+ const char *vid_header_offset = NULL;
+
+ /* Print current partition */
+ if (argc == 2) {
+ if (!ubi) {
+ printf("Error, no UBI device selected!\n");
+ return 1;
+ }
+
+ printf("Device %d: %s, MTD partition %s\n",
+ ubi->ubi_num, ubi->ubi_name, ubi->mtd->name);
+ return 0;
+ }
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if (argc > 3)
+ vid_header_offset = argv[3];
+
+ return ubi_part(argv[2], vid_header_offset);
+ }
+
+ if ((strcmp(argv[1], "part") != 0) && !ubi) {
+ printf("Error, no UBI device selected!\n");
+ return 1;
+ }
+
+ if (strcmp(argv[1], "info") == 0) {
+ int layout = 0;
+ if (argc > 2 && !strncmp(argv[2], "l", 1))
+ layout = 1;
+ return ubi_info(layout);
+ }
+
+ if (strcmp(argv[1], "check") == 0) {
+ if (argc > 2)
+ return ubi_check(argv[2]);
+
+ printf("Error, no volume name passed\n");
+ return 1;
+ }
+
+ if (strncmp(argv[1], "create", 6) == 0) {
+ int dynamic = 1; /* default: dynamic volume */
+ int id = UBI_VOL_NUM_AUTO;
+
+ /* Use maximum available size */
+ size = 0;
+
+ /* E.g., create volume with "skipcheck" bit set */
+ if (argc == 7) {
+ skipcheck = strncmp(argv[6], "--skipcheck", 11) == 0;
+ argc--;
+ }
+
+ /* E.g., create volume size type vol_id */
+ if (argc == 6) {
+ id = simple_strtoull(argv[5], NULL, 16);
+ argc--;
+ }
+
+ /* E.g., create volume size type */
+ if (argc == 5) {
+ if (strncmp(argv[4], "s", 1) == 0)
+ dynamic = 0;
+ else if (strncmp(argv[4], "d", 1) != 0) {
+ printf("Incorrect type\n");
+ return 1;
+ }
+ argc--;
+ }
+ /* E.g., create volume size */
+ if (argc == 4) {
+ if (argv[3][0] != '-')
+ size = simple_strtoull(argv[3], NULL, 16);
+ argc--;
+ }
+ /* Use maximum available size */
+ if (!size) {
+ size = (int64_t)ubi->avail_pebs * ubi->leb_size;
+ printf("No size specified -> Using max size (%lld)\n", size);
+ }
+ /* E.g., create volume */
+ if (argc == 3) {
+ return ubi_create_vol(argv[2], size, dynamic, id,
+ skipcheck);
+ }
+ }
+
+ if (strncmp(argv[1], "remove", 6) == 0) {
+ /* E.g., remove volume */
+ if (argc == 3)
+ return ubi_remove_vol(argv[2]);
+ }
+
+ if (IS_ENABLED(CONFIG_CMD_UBI_RENAME) && !strncmp(argv[1], "rename", 6))
+ return ubi_rename_vol(argv[2], argv[3]);
+
+ if (strncmp(argv[1], "skipcheck", 9) == 0) {
+ /* E.g., change skip_check flag */
+ if (argc == 4) {
+ skipcheck = strncmp(argv[3], "on", 2) == 0;
+ return ubi_set_skip_check(argv[2], skipcheck);
+ }
+ }
+
+ if (strncmp(argv[1], "write", 5) == 0) {
+ int ret;
+
+ if (argc < 5) {
+ printf("Please see usage\n");
+ return 1;
+ }
+
+ addr = simple_strtoul(argv[2], NULL, 16);
+ size = simple_strtoul(argv[4], NULL, 16);
+
+ if (strlen(argv[1]) == 10 &&
+ strncmp(argv[1] + 5, ".part", 5) == 0) {
+ if (argc < 6) {
+ ret = ubi_volume_continue_write(argv[3],
+ (void *)addr, size);
+ } else {
+ size_t full_size;
+ full_size = simple_strtoul(argv[5], NULL, 16);
+ ret = ubi_volume_begin_write(argv[3],
+ (void *)addr, size, full_size);
+ }
+ } else {
+ ret = ubi_volume_write(argv[3], (void *)addr, size);
+ }
+ if (!ret) {
+ printf("%lld bytes written to volume %s\n", size,
+ argv[3]);
+ }
+
+ return ret;
+ }
+
+ if (strncmp(argv[1], "read", 4) == 0) {
+ size = 0;
+
+ /* E.g., read volume size */
+ if (argc == 5) {
+ size = simple_strtoul(argv[4], NULL, 16);
+ argc--;
+ }
+
+ /* E.g., read volume */
+ if (argc == 4) {
+ addr = simple_strtoul(argv[2], NULL, 16);
+ argc--;
+ }
+
+ if (argc == 3) {
+ return ubi_volume_read(argv[3], (char *)addr, size);
+ }
+ }
+
+ printf("Please see usage\n");
+ return 1;
+}
+
+U_BOOT_CMD(
+ ubi, 7, 1, do_ubi,
+ "ubi commands",
+ "detach"
+ " - detach ubi from a mtd partition\n"
+ "ubi part [part] [offset]\n"
+ " - Show or set current partition (with optional VID"
+ " header offset)\n"
+ "ubi info [l[ayout]]"
+ " - Display volume and ubi layout information\n"
+ "ubi check volumename"
+ " - check if volumename exists\n"
+ "ubi create[vol] volume [size] [type] [id] [--skipcheck]\n"
+ " - create volume name with size ('-' for maximum"
+ " available size)\n"
+ "ubi write[vol] address volume size"
+ " - Write volume from address with size\n"
+ "ubi write.part address volume size [fullsize]\n"
+ " - Write part of a volume from address\n"
+ "ubi read[vol] address volume [size]"
+ " - Read volume to address with size\n"
+ "ubi remove[vol] volume"
+ " - Remove volume\n"
+#if IS_ENABLED(CONFIG_CMD_UBI_RENAME)
+ "ubi rename oldname newname\n"
+#endif
+ "ubi skipcheck volume on/off - Set or clear skip_check flag in volume header\n"
+ "[Legends]\n"
+ " volume: character name\n"
+ " size: specified in bytes\n"
+ " type: s[tatic] or d[ynamic] (default=dynamic)"
+);
diff --git a/roms/u-boot/cmd/ubifs.c b/roms/u-boot/cmd/ubifs.c
new file mode 100644
index 000000000..a26b653d6
--- /dev/null
+++ b/roms/u-boot/cmd/ubifs.c
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ */
+
+
+/*
+ * UBIFS command support
+ */
+
+#undef DEBUG
+
+#include <common.h>
+#include <config.h>
+#include <command.h>
+#include <log.h>
+#include <ubifs_uboot.h>
+
+static int ubifs_initialized;
+static int ubifs_mounted;
+
+int cmd_ubifs_mount(char *vol_name)
+{
+ int ret;
+
+ debug("Using volume %s\n", vol_name);
+
+ if (ubifs_initialized == 0) {
+ ubifs_init();
+ ubifs_initialized = 1;
+ }
+
+ ret = uboot_ubifs_mount(vol_name);
+ if (ret)
+ return -1;
+
+ ubifs_mounted = 1;
+
+ return ret;
+}
+
+static int do_ubifs_mount(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *vol_name;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ vol_name = argv[1];
+
+ return cmd_ubifs_mount(vol_name);
+}
+
+int ubifs_is_mounted(void)
+{
+ return ubifs_mounted;
+}
+
+int cmd_ubifs_umount(void)
+{
+ if (ubifs_initialized == 0) {
+ printf("No UBIFS volume mounted!\n");
+ return -1;
+ }
+
+ uboot_ubifs_umount();
+ ubifs_mounted = 0;
+ ubifs_initialized = 0;
+
+ return 0;
+}
+
+static int do_ubifs_umount(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ return cmd_ubifs_umount();
+}
+
+static int do_ubifs_ls(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *filename = "/";
+ int ret;
+
+ if (!ubifs_mounted) {
+ printf("UBIFS not mounted, use ubifsmount to mount volume first!\n");
+ return -1;
+ }
+
+ if (argc == 2)
+ filename = argv[1];
+ debug("Using filename %s\n", filename);
+
+ ret = ubifs_ls(filename);
+ if (ret) {
+ printf("** File not found %s **\n", filename);
+ ret = CMD_RET_FAILURE;
+ }
+
+ return ret;
+}
+
+static int do_ubifs_load(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *filename;
+ char *endp;
+ int ret;
+ u32 addr;
+ u32 size = 0;
+
+ if (!ubifs_mounted) {
+ printf("UBIFS not mounted, use ubifs mount to mount volume first!\n");
+ return -1;
+ }
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[1], &endp, 16);
+ if (endp == argv[1])
+ return CMD_RET_USAGE;
+
+ filename = argv[2];
+
+ if (argc == 4) {
+ size = simple_strtoul(argv[3], &endp, 16);
+ if (endp == argv[3])
+ return CMD_RET_USAGE;
+ }
+ debug("Loading file '%s' to address 0x%08x (size %d)\n", filename, addr, size);
+
+ ret = ubifs_load(filename, addr, size);
+ if (ret) {
+ printf("** File not found %s **\n", filename);
+ ret = CMD_RET_FAILURE;
+ }
+
+ return ret;
+}
+
+U_BOOT_CMD(
+ ubifsmount, 2, 0, do_ubifs_mount,
+ "mount UBIFS volume",
+ "<volume-name>\n"
+ " - mount 'volume-name' volume"
+);
+
+U_BOOT_CMD(
+ ubifsumount, 1, 0, do_ubifs_umount,
+ "unmount UBIFS volume",
+ " - unmount current volume"
+);
+
+U_BOOT_CMD(
+ ubifsls, 2, 0, do_ubifs_ls,
+ "list files in a directory",
+ "[directory]\n"
+ " - list files in a 'directory' (default '/')"
+);
+
+U_BOOT_CMD(
+ ubifsload, 4, 0, do_ubifs_load,
+ "load file from an UBIFS filesystem",
+ "<addr> <filename> [bytes]\n"
+ " - load file 'filename' to address 'addr'"
+);
diff --git a/roms/u-boot/cmd/ufs.c b/roms/u-boot/cmd/ufs.c
new file mode 100644
index 000000000..858cd49b5
--- /dev/null
+++ b/roms/u-boot/cmd/ufs.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/**
+ * ufs.c - UFS specific U-boot commands
+ *
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
+ *
+ */
+#include <common.h>
+#include <command.h>
+#include <ufs.h>
+
+static int do_ufs(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int dev, ret;
+
+ if (argc >= 2) {
+ if (!strcmp(argv[1], "init")) {
+ if (argc == 3) {
+ dev = simple_strtoul(argv[2], NULL, 10);
+ ret = ufs_probe_dev(dev);
+ if (ret)
+ return CMD_RET_FAILURE;
+ } else {
+ ufs_probe();
+ }
+
+ return CMD_RET_SUCCESS;
+ }
+ }
+
+ return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(ufs, 3, 1, do_ufs,
+ "UFS sub system",
+ "init [dev] - init UFS subsystem\n"
+);
diff --git a/roms/u-boot/cmd/universe.c b/roms/u-boot/cmd/universe.c
new file mode 100644
index 000000000..5ff47dde4
--- /dev/null
+++ b/roms/u-boot/cmd/universe.c
@@ -0,0 +1,367 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#include <universe.h>
+
+#define PCI_VENDOR PCI_VENDOR_ID_TUNDRA
+#define PCI_DEVICE PCI_DEVICE_ID_TUNDRA_CA91C042
+
+
+typedef struct _UNI_DEV UNI_DEV;
+
+struct _UNI_DEV {
+ int bus;
+ pci_dev_t busdevfn;
+ UNIVERSE *uregs;
+ unsigned int pci_bs;
+};
+
+static UNI_DEV *dev;
+
+
+int universe_init(void)
+{
+ int j, result;
+ pci_dev_t busdevfn;
+ unsigned int val;
+
+ busdevfn = pci_find_device(PCI_VENDOR, PCI_DEVICE, 0);
+ if (busdevfn == -1) {
+ puts("No Tundra Universe found!\n");
+ return -1;
+ }
+
+ /* Lets turn Latency off */
+ pci_write_config_dword(busdevfn, 0x0c, 0);
+
+ dev = malloc(sizeof(*dev));
+ if (NULL == dev) {
+ puts("UNIVERSE: No memory!\n");
+ result = -1;
+ goto break_20;
+ }
+
+ memset(dev, 0, sizeof(*dev));
+ dev->busdevfn = busdevfn;
+
+ pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_1, &val);
+ if (val & 1) {
+ pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val);
+ }
+ val &= ~0xf;
+ dev->uregs = (UNIVERSE *)val;
+
+ debug ("UNIVERSE-Base : %p\n", dev->uregs);
+
+ /* check mapping */
+ debug (" Read via mapping, PCI_ID = %08X\n", readl(&dev->uregs->pci_id));
+ if (((PCI_DEVICE <<16) | PCI_VENDOR) != readl(&dev->uregs->pci_id)) {
+ printf ("UNIVERSE: Cannot read PCI-ID via Mapping: %08x\n",
+ readl(&dev->uregs->pci_id));
+ result = -1;
+ goto break_30;
+ }
+
+ debug ("PCI_BS = %08X\n", readl(&dev->uregs->pci_bs));
+
+ dev->pci_bs = readl(&dev->uregs->pci_bs);
+
+ /* turn off windows */
+ for (j=0; j <4; j ++) {
+ writel(0x00800000, &dev->uregs->lsi[j].ctl);
+ writel(0x00800000, &dev->uregs->vsi[j].ctl);
+ }
+
+ /*
+ * Write to Misc Register
+ * Set VME Bus Time-out
+ * Arbitration Mode
+ * DTACK Enable
+ */
+ writel(0x15040000 | (readl(&dev->uregs->misc_ctl) & 0x00020000), &dev->uregs->misc_ctl);
+
+ if (readl(&dev->uregs->misc_ctl) & 0x00020000) {
+ debug ("System Controller!\n"); /* test-only */
+ } else {
+ debug ("Not System Controller!\n"); /* test-only */
+ }
+
+ /*
+ * Lets turn off interrupts
+ */
+ writel(0x00000000,&dev->uregs->lint_en); /* Disable interrupts in the Universe first */
+ writel(0x0000FFFF,&dev->uregs->lint_stat); /* Clear Any Pending Interrupts */
+ eieio();
+ writel(0x0000, &dev->uregs->lint_map0); /* Map all ints to 0 */
+ writel(0x0000, &dev->uregs->lint_map1); /* Map all ints to 0 */
+ eieio();
+
+ return 0;
+
+ break_30:
+ free(dev);
+ break_20:
+ return result;
+}
+
+
+/*
+ * Create pci slave window (access: pci -> vme)
+ */
+int universe_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr, int size, int vam, int pms, int vdw)
+{
+ int result, i;
+ unsigned int ctl = 0;
+
+ if (NULL == dev) {
+ result = -1;
+ goto exit_10;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (0x00800000 == readl(&dev->uregs->lsi[i].ctl))
+ break;
+ }
+
+ if (i == 4) {
+ printf ("universe: No Image available\n");
+ result = -1;
+ goto exit_10;
+ }
+
+ debug ("universe: Using image %d\n", i);
+
+ writel(pciAddr , &dev->uregs->lsi[i].bs);
+ writel((pciAddr + size), &dev->uregs->lsi[i].bd);
+ writel((vmeAddr - pciAddr), &dev->uregs->lsi[i].to);
+
+ switch (vam & VME_AM_Axx) {
+ case VME_AM_A16:
+ ctl = 0x00000000;
+ break;
+ case VME_AM_A24:
+ ctl = 0x00010000;
+ break;
+ case VME_AM_A32:
+ ctl = 0x00020000;
+ break;
+ }
+
+ switch (vam & VME_AM_Mxx) {
+ case VME_AM_DATA:
+ ctl |= 0x00000000;
+ break;
+ case VME_AM_PROG:
+ ctl |= 0x00008000;
+ break;
+ }
+
+ if (vam & VME_AM_SUP) {
+ ctl |= 0x00001000;
+
+ }
+
+ switch (vdw & VME_FLAG_Dxx) {
+ case VME_FLAG_D8:
+ ctl |= 0x00000000;
+ break;
+ case VME_FLAG_D16:
+ ctl |= 0x00400000;
+ break;
+ case VME_FLAG_D32:
+ ctl |= 0x00800000;
+ break;
+ }
+
+ switch (pms & PCI_MS_Mxx) {
+ case PCI_MS_MEM:
+ ctl |= 0x00000000;
+ break;
+ case PCI_MS_IO:
+ ctl |= 0x00000001;
+ break;
+ case PCI_MS_CONFIG:
+ ctl |= 0x00000002;
+ break;
+ }
+
+ ctl |= 0x80000000; /* enable */
+
+ writel(ctl, &dev->uregs->lsi[i].ctl);
+
+ debug ("universe: window-addr=%p\n", &dev->uregs->lsi[i].ctl);
+ debug ("universe: pci slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->lsi[i].ctl));
+ debug ("universe: pci slave window[%d] bs=%08x\n", i, readl(&dev->uregs->lsi[i].bs));
+ debug ("universe: pci slave window[%d] bd=%08x\n", i, readl(&dev->uregs->lsi[i].bd));
+ debug ("universe: pci slave window[%d] to=%08x\n", i, readl(&dev->uregs->lsi[i].to));
+
+ return 0;
+
+ exit_10:
+ return -result;
+}
+
+
+/*
+ * Create vme slave window (access: vme -> pci)
+ */
+int universe_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr, int size, int vam, int pms)
+{
+ int result, i;
+ unsigned int ctl = 0;
+
+ if (NULL == dev) {
+ result = -1;
+ goto exit_10;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (0x00800000 == readl(&dev->uregs->vsi[i].ctl))
+ break;
+ }
+
+ if (i == 4) {
+ printf ("universe: No Image available\n");
+ result = -1;
+ goto exit_10;
+ }
+
+ debug ("universe: Using image %d\n", i);
+
+ writel(vmeAddr , &dev->uregs->vsi[i].bs);
+ writel((vmeAddr + size), &dev->uregs->vsi[i].bd);
+ writel((pciAddr - vmeAddr), &dev->uregs->vsi[i].to);
+
+ switch (vam & VME_AM_Axx) {
+ case VME_AM_A16:
+ ctl = 0x00000000;
+ break;
+ case VME_AM_A24:
+ ctl = 0x00010000;
+ break;
+ case VME_AM_A32:
+ ctl = 0x00020000;
+ break;
+ }
+
+ switch (vam & VME_AM_Mxx) {
+ case VME_AM_DATA:
+ ctl |= 0x00000000;
+ break;
+ case VME_AM_PROG:
+ ctl |= 0x00800000;
+ break;
+ }
+
+ if (vam & VME_AM_SUP) {
+ ctl |= 0x00100000;
+
+ }
+
+ switch (pms & PCI_MS_Mxx) {
+ case PCI_MS_MEM:
+ ctl |= 0x00000000;
+ break;
+ case PCI_MS_IO:
+ ctl |= 0x00000001;
+ break;
+ case PCI_MS_CONFIG:
+ ctl |= 0x00000002;
+ break;
+ }
+
+ ctl |= 0x80f00000; /* enable */
+
+ writel(ctl, &dev->uregs->vsi[i].ctl);
+
+ debug ("universe: window-addr=%p\n", &dev->uregs->vsi[i].ctl);
+ debug ("universe: vme slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->vsi[i].ctl));
+ debug ("universe: vme slave window[%d] bs=%08x\n", i, readl(&dev->uregs->vsi[i].bs));
+ debug ("universe: vme slave window[%d] bd=%08x\n", i, readl(&dev->uregs->vsi[i].bd));
+ debug ("universe: vme slave window[%d] to=%08x\n", i, readl(&dev->uregs->vsi[i].to));
+
+ return 0;
+
+ exit_10:
+ return -result;
+}
+
+
+/*
+ * Tundra Universe configuration
+ */
+int do_universe(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, pms = 0, vdw = 0;
+ char cmd = 'x';
+
+ /* get parameter */
+ if (argc > 1)
+ cmd = argv[1][0];
+ if (argc > 2)
+ addr1 = simple_strtoul(argv[2], NULL, 16);
+ if (argc > 3)
+ addr2 = simple_strtoul(argv[3], NULL, 16);
+ if (argc > 4)
+ size = simple_strtoul(argv[4], NULL, 16);
+ if (argc > 5)
+ vam = simple_strtoul(argv[5], NULL, 16);
+ if (argc > 6)
+ pms = simple_strtoul(argv[6], NULL, 16);
+ if (argc > 7)
+ vdw = simple_strtoul(argv[7], NULL, 16);
+
+ switch (cmd) {
+ case 'i': /* init */
+ universe_init();
+ break;
+ case 'v': /* vme */
+ printf("Configuring Universe VME Slave Window (VME->PCI):\n");
+ printf(" vme=%08lx pci=%08lx size=%08lx vam=%02lx pms=%02lx\n",
+ addr1, addr2, size, vam, pms);
+ universe_vme_slave_window(addr1, addr2, size, vam, pms);
+ break;
+ case 'p': /* pci */
+ printf("Configuring Universe PCI Slave Window (PCI->VME):\n");
+ printf(" pci=%08lx vme=%08lx size=%08lx vam=%02lx pms=%02lx vdw=%02lx\n",
+ addr1, addr2, size, vam, pms, vdw);
+ universe_pci_slave_window(addr1, addr2, size, vam, pms, vdw);
+ break;
+ default:
+ printf("Universe command %s not supported!\n", argv[1]);
+ }
+
+ return 0;
+}
+
+
+U_BOOT_CMD(
+ universe, 8, 1, do_universe,
+ "initialize and configure Turndra Universe",
+ "init\n"
+ " - initialize universe\n"
+ "universe vme [vme_addr] [pci_addr] [size] [vam] [pms]\n"
+ " - create vme slave window (access: vme->pci)\n"
+ "universe pci [pci_addr] [vme_addr] [size] [vam] [pms] [vdw]\n"
+ " - create pci slave window (access: pci->vme)\n"
+ " [vam] = VMEbus Address-Modifier: 01 -> A16 Address Space\n"
+ " 02 -> A24 Address Space\n"
+ " 03 -> A32 Address Space\n"
+ " 04 -> Supervisor AM Code\n"
+ " 10 -> Data AM Code\n"
+ " 20 -> Program AM Code\n"
+ " [pms] = PCI Memory Space: 01 -> Memory Space\n"
+ " 02 -> I/O Space\n"
+ " 03 -> Configuration Space\n"
+ " [vdw] = VMEbus Maximum Datawidth: 01 -> D8 Data Width\n"
+ " 02 -> D16 Data Width\n"
+ " 03 -> D32 Data Width"
+);
diff --git a/roms/u-boot/cmd/unlz4.c b/roms/u-boot/cmd/unlz4.c
new file mode 100644
index 000000000..4ae7f34d3
--- /dev/null
+++ b/roms/u-boot/cmd/unlz4.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020
+ * FUJITSU COMPUTERTECHNOLOGIES LIMITED. All rights reserved.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <lz4.h>
+
+static int do_unlz4(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long src, dst;
+ size_t src_len = ~0UL, dst_len = ~0UL;
+ int ret;
+
+ switch (argc) {
+ case 4:
+ src = simple_strtoul(argv[1], NULL, 16);
+ dst = simple_strtoul(argv[2], NULL, 16);
+ dst_len = simple_strtoul(argv[3], NULL, 16);
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ ret = ulz4fn((void *)src, src_len, (void *)dst, &dst_len);
+ if (ret) {
+ printf("Uncompressed err :%d\n", ret);
+ return 1;
+ }
+
+ printf("Uncompressed size: %zd = 0x%zX\n", dst_len, dst_len);
+ env_set_hex("filesize", dst_len);
+
+ return 0;
+}
+
+U_BOOT_CMD(unlz4, 4, 1, do_unlz4,
+ "lz4 uncompress a memory region",
+ "srcaddr dstaddr dstsize\n"
+ "NOTE: Specify the destination size that is sufficiently larger\n"
+ " than the source size.\n"
+);
diff --git a/roms/u-boot/cmd/unzip.c b/roms/u-boot/cmd/unzip.c
new file mode 100644
index 000000000..9b28328a1
--- /dev/null
+++ b/roms/u-boot/cmd/unzip.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <gzip.h>
+#include <part.h>
+
+static int do_unzip(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long src, dst;
+ unsigned long src_len = ~0UL, dst_len = ~0UL;
+
+ switch (argc) {
+ case 4:
+ dst_len = simple_strtoul(argv[3], NULL, 16);
+ /* fall through */
+ case 3:
+ src = simple_strtoul(argv[1], NULL, 16);
+ dst = simple_strtoul(argv[2], NULL, 16);
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+
+ if (gunzip((void *) dst, dst_len, (void *) src, &src_len) != 0)
+ return 1;
+
+ printf("Uncompressed size: %lu = 0x%lX\n", src_len, src_len);
+ env_set_hex("filesize", src_len);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ unzip, 4, 1, do_unzip,
+ "unzip a memory region",
+ "srcaddr dstaddr [dstsize]"
+);
+
+static int do_gzwrite(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct blk_desc *bdev;
+ int ret;
+ unsigned char *addr;
+ unsigned long length;
+ unsigned long writebuf = 1<<20;
+ u64 startoffs = 0;
+ u64 szexpected = 0;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+ ret = blk_get_device_by_str(argv[1], argv[2], &bdev);
+ if (ret < 0)
+ return CMD_RET_FAILURE;
+
+ addr = (unsigned char *)simple_strtoul(argv[3], NULL, 16);
+ length = simple_strtoul(argv[4], NULL, 16);
+
+ if (5 < argc) {
+ writebuf = simple_strtoul(argv[5], NULL, 16);
+ if (6 < argc) {
+ startoffs = simple_strtoull(argv[6], NULL, 16);
+ if (7 < argc)
+ szexpected = simple_strtoull(argv[7],
+ NULL, 16);
+ }
+ }
+
+ ret = gzwrite(addr, length, bdev, writebuf, startoffs, szexpected);
+
+ return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ gzwrite, 8, 0, do_gzwrite,
+ "unzip and write memory to block device",
+ "<interface> <dev> <addr> length [wbuf=1M [offs=0 [outsize=0]]]\n"
+ "\twbuf is the size in bytes (hex) of write buffer\n"
+ "\t\tand should be padded to erase size for SSDs\n"
+ "\toffs is the output start offset in bytes (hex)\n"
+ "\toutsize is the size of the expected output (hex bytes)\n"
+ "\t\tand is required for files with uncompressed lengths\n"
+ "\t\t4 GiB or larger\n"
+);
diff --git a/roms/u-boot/cmd/usb.c b/roms/u-boot/cmd/usb.c
new file mode 100644
index 000000000..b9ec29a84
--- /dev/null
+++ b/roms/u-boot/cmd/usb.c
@@ -0,0 +1,758 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * Adapted for U-Boot driver model
+ * (C) Copyright 2015 Google, Inc
+ *
+ * Most of this source has been derived from the Linux USB
+ * project.
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <bootstage.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <memalign.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include <part.h>
+#include <usb.h>
+
+#ifdef CONFIG_USB_STORAGE
+static int usb_stor_curr_dev = -1; /* current device */
+#endif
+#if defined(CONFIG_USB_HOST_ETHER) && !defined(CONFIG_DM_ETH)
+static int __maybe_unused usb_ether_curr_dev = -1; /* current ethernet device */
+#endif
+
+/* some display routines (info command) */
+static char *usb_get_class_desc(unsigned char dclass)
+{
+ switch (dclass) {
+ case USB_CLASS_PER_INTERFACE:
+ return "See Interface";
+ case USB_CLASS_AUDIO:
+ return "Audio";
+ case USB_CLASS_COMM:
+ return "Communication";
+ case USB_CLASS_HID:
+ return "Human Interface";
+ case USB_CLASS_PRINTER:
+ return "Printer";
+ case USB_CLASS_MASS_STORAGE:
+ return "Mass Storage";
+ case USB_CLASS_HUB:
+ return "Hub";
+ case USB_CLASS_DATA:
+ return "CDC Data";
+ case USB_CLASS_VENDOR_SPEC:
+ return "Vendor specific";
+ default:
+ return "";
+ }
+}
+
+static void usb_display_class_sub(unsigned char dclass, unsigned char subclass,
+ unsigned char proto)
+{
+ switch (dclass) {
+ case USB_CLASS_PER_INTERFACE:
+ printf("See Interface");
+ break;
+ case USB_CLASS_HID:
+ printf("Human Interface, Subclass: ");
+ switch (subclass) {
+ case USB_SUB_HID_NONE:
+ printf("None");
+ break;
+ case USB_SUB_HID_BOOT:
+ printf("Boot ");
+ switch (proto) {
+ case USB_PROT_HID_NONE:
+ printf("None");
+ break;
+ case USB_PROT_HID_KEYBOARD:
+ printf("Keyboard");
+ break;
+ case USB_PROT_HID_MOUSE:
+ printf("Mouse");
+ break;
+ default:
+ printf("reserved");
+ break;
+ }
+ break;
+ default:
+ printf("reserved");
+ break;
+ }
+ break;
+ case USB_CLASS_MASS_STORAGE:
+ printf("Mass Storage, ");
+ switch (subclass) {
+ case US_SC_RBC:
+ printf("RBC ");
+ break;
+ case US_SC_8020:
+ printf("SFF-8020i (ATAPI)");
+ break;
+ case US_SC_QIC:
+ printf("QIC-157 (Tape)");
+ break;
+ case US_SC_UFI:
+ printf("UFI");
+ break;
+ case US_SC_8070:
+ printf("SFF-8070");
+ break;
+ case US_SC_SCSI:
+ printf("Transp. SCSI");
+ break;
+ default:
+ printf("reserved");
+ break;
+ }
+ printf(", ");
+ switch (proto) {
+ case US_PR_CB:
+ printf("Command/Bulk");
+ break;
+ case US_PR_CBI:
+ printf("Command/Bulk/Int");
+ break;
+ case US_PR_BULK:
+ printf("Bulk only");
+ break;
+ default:
+ printf("reserved");
+ break;
+ }
+ break;
+ default:
+ printf("%s", usb_get_class_desc(dclass));
+ break;
+ }
+}
+
+static void usb_display_string(struct usb_device *dev, int index)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256);
+
+ if (index != 0) {
+ if (usb_string(dev, index, &buffer[0], 256) > 0)
+ printf("String: \"%s\"", buffer);
+ }
+}
+
+static void usb_display_desc(struct usb_device *dev)
+{
+ uint packet_size = dev->descriptor.bMaxPacketSize0;
+
+ if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) {
+ printf("%d: %s, USB Revision %x.%x\n", dev->devnum,
+ usb_get_class_desc(dev->config.if_desc[0].desc.bInterfaceClass),
+ (dev->descriptor.bcdUSB>>8) & 0xff,
+ dev->descriptor.bcdUSB & 0xff);
+
+ if (strlen(dev->mf) || strlen(dev->prod) ||
+ strlen(dev->serial))
+ printf(" - %s %s %s\n", dev->mf, dev->prod,
+ dev->serial);
+ if (dev->descriptor.bDeviceClass) {
+ printf(" - Class: ");
+ usb_display_class_sub(dev->descriptor.bDeviceClass,
+ dev->descriptor.bDeviceSubClass,
+ dev->descriptor.bDeviceProtocol);
+ printf("\n");
+ } else {
+ printf(" - Class: (from Interface) %s\n",
+ usb_get_class_desc(
+ dev->config.if_desc[0].desc.bInterfaceClass));
+ }
+ if (dev->descriptor.bcdUSB >= cpu_to_le16(0x0300))
+ packet_size = 1 << packet_size;
+ printf(" - PacketSize: %d Configurations: %d\n",
+ packet_size, dev->descriptor.bNumConfigurations);
+ printf(" - Vendor: 0x%04x Product 0x%04x Version %d.%d\n",
+ dev->descriptor.idVendor, dev->descriptor.idProduct,
+ (dev->descriptor.bcdDevice>>8) & 0xff,
+ dev->descriptor.bcdDevice & 0xff);
+ }
+
+}
+
+static void usb_display_conf_desc(struct usb_config_descriptor *config,
+ struct usb_device *dev)
+{
+ printf(" Configuration: %d\n", config->bConfigurationValue);
+ printf(" - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces,
+ (config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ",
+ (config->bmAttributes & 0x20) ? "Remote Wakeup " : "",
+ config->bMaxPower*2);
+ if (config->iConfiguration) {
+ printf(" - ");
+ usb_display_string(dev, config->iConfiguration);
+ printf("\n");
+ }
+}
+
+static void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,
+ struct usb_device *dev)
+{
+ printf(" Interface: %d\n", ifdesc->bInterfaceNumber);
+ printf(" - Alternate Setting %d, Endpoints: %d\n",
+ ifdesc->bAlternateSetting, ifdesc->bNumEndpoints);
+ printf(" - Class ");
+ usb_display_class_sub(ifdesc->bInterfaceClass,
+ ifdesc->bInterfaceSubClass, ifdesc->bInterfaceProtocol);
+ printf("\n");
+ if (ifdesc->iInterface) {
+ printf(" - ");
+ usb_display_string(dev, ifdesc->iInterface);
+ printf("\n");
+ }
+}
+
+static void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
+{
+ printf(" - Endpoint %d %s ", epdesc->bEndpointAddress & 0xf,
+ (epdesc->bEndpointAddress & 0x80) ? "In" : "Out");
+ switch ((epdesc->bmAttributes & 0x03)) {
+ case 0:
+ printf("Control");
+ break;
+ case 1:
+ printf("Isochronous");
+ break;
+ case 2:
+ printf("Bulk");
+ break;
+ case 3:
+ printf("Interrupt");
+ break;
+ }
+ printf(" MaxPacket %d", get_unaligned(&epdesc->wMaxPacketSize));
+ if ((epdesc->bmAttributes & 0x03) == 0x3)
+ printf(" Interval %dms", epdesc->bInterval);
+ printf("\n");
+}
+
+/* main routine to diasplay the configs, interfaces and endpoints */
+static void usb_display_config(struct usb_device *dev)
+{
+ struct usb_config *config;
+ struct usb_interface *ifdesc;
+ struct usb_endpoint_descriptor *epdesc;
+ int i, ii;
+
+ config = &dev->config;
+ usb_display_conf_desc(&config->desc, dev);
+ for (i = 0; i < config->no_of_if; i++) {
+ ifdesc = &config->if_desc[i];
+ usb_display_if_desc(&ifdesc->desc, dev);
+ for (ii = 0; ii < ifdesc->no_of_ep; ii++) {
+ epdesc = &ifdesc->ep_desc[ii];
+ usb_display_ep_desc(epdesc);
+ }
+ }
+ printf("\n");
+}
+
+/*
+ * With driver model this isn't right since we can have multiple controllers
+ * and the device numbering starts at 1 on each bus.
+ * TODO(sjg@chromium.org): Add a way to specify the controller/bus.
+ */
+static struct usb_device *usb_find_device(int devnum)
+{
+#ifdef CONFIG_DM_USB
+ struct usb_device *udev;
+ struct udevice *hub;
+ struct uclass *uc;
+ int ret;
+
+ /* Device addresses start at 1 */
+ devnum++;
+ ret = uclass_get(UCLASS_USB_HUB, &uc);
+ if (ret)
+ return NULL;
+
+ uclass_foreach_dev(hub, uc) {
+ struct udevice *dev;
+
+ if (!device_active(hub))
+ continue;
+ udev = dev_get_parent_priv(hub);
+ if (udev->devnum == devnum)
+ return udev;
+
+ for (device_find_first_child(hub, &dev);
+ dev;
+ device_find_next_child(&dev)) {
+ if (!device_active(hub))
+ continue;
+
+ udev = dev_get_parent_priv(dev);
+ if (udev->devnum == devnum)
+ return udev;
+ }
+ }
+#else
+ struct usb_device *udev;
+ int d;
+
+ for (d = 0; d < USB_MAX_DEVICE; d++) {
+ udev = usb_get_dev_index(d);
+ if (udev == NULL)
+ return NULL;
+ if (udev->devnum == devnum)
+ return udev;
+ }
+#endif
+
+ return NULL;
+}
+
+static inline const char *portspeed(int speed)
+{
+ switch (speed) {
+ case USB_SPEED_SUPER:
+ return "5 Gb/s";
+ case USB_SPEED_HIGH:
+ return "480 Mb/s";
+ case USB_SPEED_LOW:
+ return "1.5 Mb/s";
+ default:
+ return "12 Mb/s";
+ }
+}
+
+/* shows the device tree recursively */
+static void usb_show_tree_graph(struct usb_device *dev, char *pre)
+{
+ int index;
+ int has_child, last_child;
+
+ index = strlen(pre);
+ printf(" %s", pre);
+#ifdef CONFIG_DM_USB
+ has_child = device_has_active_children(dev->dev);
+ if (device_get_uclass_id(dev->dev) == UCLASS_MASS_STORAGE) {
+ struct udevice *child;
+
+ for (device_find_first_child(dev->dev, &child);
+ child;
+ device_find_next_child(&child)) {
+ if (device_get_uclass_id(child) == UCLASS_BLK)
+ has_child = 0;
+ }
+ }
+#else
+ /* check if the device has connected children */
+ int i;
+
+ has_child = 0;
+ for (i = 0; i < dev->maxchild; i++) {
+ if (dev->children[i] != NULL)
+ has_child = 1;
+ }
+#endif
+ /* check if we are the last one */
+#ifdef CONFIG_DM_USB
+ /* Not the root of the usb tree? */
+ if (device_get_uclass_id(dev->dev->parent) != UCLASS_USB) {
+ last_child = device_is_last_sibling(dev->dev);
+#else
+ if (dev->parent != NULL) { /* not root? */
+ last_child = 1;
+ for (i = 0; i < dev->parent->maxchild; i++) {
+ /* search for children */
+ if (dev->parent->children[i] == dev) {
+ /* found our pointer, see if we have a
+ * little sister
+ */
+ while (i++ < dev->parent->maxchild) {
+ if (dev->parent->children[i] != NULL) {
+ /* found a sister */
+ last_child = 0;
+ break;
+ } /* if */
+ } /* while */
+ } /* device found */
+ } /* for all children of the parent */
+#endif
+ printf("\b+-");
+ /* correct last child */
+ if (last_child && index)
+ pre[index-1] = ' ';
+ } /* if not root hub */
+ else
+ printf(" ");
+ printf("%d ", dev->devnum);
+ pre[index++] = ' ';
+ pre[index++] = has_child ? '|' : ' ';
+ pre[index] = 0;
+ printf(" %s (%s, %dmA)\n", usb_get_class_desc(
+ dev->config.if_desc[0].desc.bInterfaceClass),
+ portspeed(dev->speed),
+ dev->config.desc.bMaxPower * 2);
+ if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
+ printf(" %s %s %s %s\n", pre, dev->mf, dev->prod, dev->serial);
+ printf(" %s\n", pre);
+#ifdef CONFIG_DM_USB
+ struct udevice *child;
+
+ for (device_find_first_child(dev->dev, &child);
+ child;
+ device_find_next_child(&child)) {
+ struct usb_device *udev;
+
+ if (!device_active(child))
+ continue;
+
+ udev = dev_get_parent_priv(child);
+
+ /*
+ * Ignore emulators and block child devices, we only want
+ * real devices
+ */
+ if ((device_get_uclass_id(child) != UCLASS_USB_EMUL) &&
+ (device_get_uclass_id(child) != UCLASS_BLK)) {
+ usb_show_tree_graph(udev, pre);
+ pre[index] = 0;
+ }
+ }
+#else
+ if (dev->maxchild > 0) {
+ for (i = 0; i < dev->maxchild; i++) {
+ if (dev->children[i] != NULL) {
+ usb_show_tree_graph(dev->children[i], pre);
+ pre[index] = 0;
+ }
+ }
+ }
+#endif
+}
+
+/* main routine for the tree command */
+static void usb_show_subtree(struct usb_device *dev)
+{
+ char preamble[32];
+
+ memset(preamble, '\0', sizeof(preamble));
+ usb_show_tree_graph(dev, &preamble[0]);
+}
+
+#ifdef CONFIG_DM_USB
+typedef void (*usb_dev_func_t)(struct usb_device *udev);
+
+static void usb_for_each_root_dev(usb_dev_func_t func)
+{
+ struct udevice *bus;
+
+ for (uclass_find_first_device(UCLASS_USB, &bus);
+ bus;
+ uclass_find_next_device(&bus)) {
+ struct usb_device *udev;
+ struct udevice *dev;
+
+ if (!device_active(bus))
+ continue;
+
+ device_find_first_child(bus, &dev);
+ if (dev && device_active(dev)) {
+ udev = dev_get_parent_priv(dev);
+ func(udev);
+ }
+ }
+}
+#endif
+
+void usb_show_tree(void)
+{
+#ifdef CONFIG_DM_USB
+ usb_for_each_root_dev(usb_show_subtree);
+#else
+ struct usb_device *udev;
+ int i;
+
+ for (i = 0; i < USB_MAX_DEVICE; i++) {
+ udev = usb_get_dev_index(i);
+ if (udev == NULL)
+ break;
+ if (udev->parent == NULL)
+ usb_show_subtree(udev);
+ }
+#endif
+}
+
+static int usb_test(struct usb_device *dev, int port, char* arg)
+{
+ int mode;
+
+ if (port > dev->maxchild) {
+ printf("Device is no hub or does not have %d ports.\n", port);
+ return 1;
+ }
+
+ switch (arg[0]) {
+ case 'J':
+ case 'j':
+ printf("Setting Test_J mode");
+ mode = USB_TEST_MODE_J;
+ break;
+ case 'K':
+ case 'k':
+ printf("Setting Test_K mode");
+ mode = USB_TEST_MODE_K;
+ break;
+ case 'S':
+ case 's':
+ printf("Setting Test_SE0_NAK mode");
+ mode = USB_TEST_MODE_SE0_NAK;
+ break;
+ case 'P':
+ case 'p':
+ printf("Setting Test_Packet mode");
+ mode = USB_TEST_MODE_PACKET;
+ break;
+ case 'F':
+ case 'f':
+ printf("Setting Test_Force_Enable mode");
+ mode = USB_TEST_MODE_FORCE_ENABLE;
+ break;
+ default:
+ printf("Unrecognized test mode: %s\nAvailable modes: "
+ "J, K, S[E0_NAK], P[acket], F[orce_Enable]\n", arg);
+ return 1;
+ }
+
+ if (port)
+ printf(" on downstream facing port %d...\n", port);
+ else
+ printf(" on upstream facing port...\n");
+
+ if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_FEATURE,
+ port ? USB_RT_PORT : USB_RECIP_DEVICE,
+ port ? USB_PORT_FEAT_TEST : USB_FEAT_TEST,
+ (mode << 8) | port,
+ NULL, 0, USB_CNTL_TIMEOUT) == -1) {
+ printf("Error during SET_FEATURE.\n");
+ return 1;
+ } else {
+ printf("Test mode successfully set. Use 'usb start' "
+ "to return to normal operation.\n");
+ return 0;
+ }
+}
+
+
+/******************************************************************************
+ * usb boot command intepreter. Derived from diskboot
+ */
+#ifdef CONFIG_USB_STORAGE
+static int do_usbboot(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ return common_diskboot(cmdtp, "usb", argc, argv);
+}
+#endif /* CONFIG_USB_STORAGE */
+
+static int do_usb_stop_keyboard(int force)
+{
+#if !defined CONFIG_DM_USB && defined CONFIG_USB_KEYBOARD
+ if (usb_kbd_deregister(force) != 0) {
+ printf("USB not stopped: usbkbd still using USB\n");
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+static void do_usb_start(void)
+{
+ bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
+
+ if (usb_init() < 0)
+ return;
+
+ /* Driver model will probe the devices as they are found */
+# ifdef CONFIG_USB_STORAGE
+ /* try to recognize storage devices immediately */
+ usb_stor_curr_dev = usb_stor_scan(1);
+# endif
+#ifndef CONFIG_DM_USB
+# ifdef CONFIG_USB_KEYBOARD
+ drv_usb_kbd_init();
+# endif
+#endif /* !CONFIG_DM_USB */
+#ifdef CONFIG_USB_HOST_ETHER
+# ifdef CONFIG_DM_ETH
+# ifndef CONFIG_DM_USB
+# error "You must use CONFIG_DM_USB if you want to use CONFIG_USB_HOST_ETHER with CONFIG_DM_ETH"
+# endif
+# else
+ /* try to recognize ethernet devices immediately */
+ usb_ether_curr_dev = usb_host_eth_scan(1);
+# endif
+#endif
+}
+
+#ifdef CONFIG_DM_USB
+static void usb_show_info(struct usb_device *udev)
+{
+ struct udevice *child;
+
+ usb_display_desc(udev);
+ usb_display_config(udev);
+ for (device_find_first_child(udev->dev, &child);
+ child;
+ device_find_next_child(&child)) {
+ if (device_active(child) &&
+ (device_get_uclass_id(child) != UCLASS_USB_EMUL) &&
+ (device_get_uclass_id(child) != UCLASS_BLK)) {
+ udev = dev_get_parent_priv(child);
+ usb_show_info(udev);
+ }
+ }
+}
+#endif
+
+/******************************************************************************
+ * usb command intepreter
+ */
+static int do_usb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct usb_device *udev = NULL;
+ int i;
+ extern char usb_started;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (strncmp(argv[1], "start", 5) == 0) {
+ if (usb_started)
+ return 0; /* Already started */
+ printf("starting USB...\n");
+ do_usb_start();
+ return 0;
+ }
+
+ if (strncmp(argv[1], "reset", 5) == 0) {
+ printf("resetting USB...\n");
+ if (do_usb_stop_keyboard(1) != 0)
+ return 1;
+ usb_stop();
+ do_usb_start();
+ return 0;
+ }
+ if (strncmp(argv[1], "stop", 4) == 0) {
+ if (argc != 2)
+ console_assign(stdin, "serial");
+ if (do_usb_stop_keyboard(0) != 0)
+ return 1;
+ printf("stopping USB..\n");
+ usb_stop();
+ return 0;
+ }
+ if (!usb_started) {
+ printf("USB is stopped. Please issue 'usb start' first.\n");
+ return 1;
+ }
+ if (strncmp(argv[1], "tree", 4) == 0) {
+ puts("USB device tree:\n");
+ usb_show_tree();
+ return 0;
+ }
+ if (strncmp(argv[1], "inf", 3) == 0) {
+ if (argc == 2) {
+#ifdef CONFIG_DM_USB
+ usb_for_each_root_dev(usb_show_info);
+#else
+ int d;
+ for (d = 0; d < USB_MAX_DEVICE; d++) {
+ udev = usb_get_dev_index(d);
+ if (udev == NULL)
+ break;
+ usb_display_desc(udev);
+ usb_display_config(udev);
+ }
+#endif
+ return 0;
+ } else {
+ /*
+ * With driver model this isn't right since we can
+ * have multiple controllers and the device numbering
+ * starts at 1 on each bus.
+ */
+ i = simple_strtoul(argv[2], NULL, 10);
+ printf("config for device %d\n", i);
+ udev = usb_find_device(i);
+ if (udev == NULL) {
+ printf("*** No device available ***\n");
+ return 0;
+ } else {
+ usb_display_desc(udev);
+ usb_display_config(udev);
+ }
+ }
+ return 0;
+ }
+ if (strncmp(argv[1], "test", 4) == 0) {
+ if (argc < 5)
+ return CMD_RET_USAGE;
+ i = simple_strtoul(argv[2], NULL, 10);
+ udev = usb_find_device(i);
+ if (udev == NULL) {
+ printf("Device %d does not exist.\n", i);
+ return 1;
+ }
+ i = simple_strtoul(argv[3], NULL, 10);
+ return usb_test(udev, i, argv[4]);
+ }
+#ifdef CONFIG_USB_STORAGE
+ if (strncmp(argv[1], "stor", 4) == 0)
+ return usb_stor_info();
+
+ return blk_common_cmd(argc, argv, IF_TYPE_USB, &usb_stor_curr_dev);
+#else
+ return CMD_RET_USAGE;
+#endif /* CONFIG_USB_STORAGE */
+}
+
+U_BOOT_CMD(
+ usb, 5, 1, do_usb,
+ "USB sub-system",
+ "start - start (scan) USB controller\n"
+ "usb reset - reset (rescan) USB controller\n"
+ "usb stop [f] - stop USB [f]=force stop\n"
+ "usb tree - show USB device tree\n"
+ "usb info [dev] - show available USB devices\n"
+ "usb test [dev] [port] [mode] - set USB 2.0 test mode\n"
+ " (specify port 0 to indicate the device's upstream port)\n"
+ " Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n"
+#ifdef CONFIG_USB_STORAGE
+ "usb storage - show details of USB storage devices\n"
+ "usb dev [dev] - show or set current USB storage device\n"
+ "usb part [dev] - print partition table of one or all USB storage"
+ " devices\n"
+ "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
+ " to memory address `addr'\n"
+ "usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n"
+ " from memory address `addr'"
+#endif /* CONFIG_USB_STORAGE */
+);
+
+
+#ifdef CONFIG_USB_STORAGE
+U_BOOT_CMD(
+ usbboot, 3, 1, do_usbboot,
+ "boot from USB device",
+ "loadAddr dev:part"
+);
+#endif /* CONFIG_USB_STORAGE */
diff --git a/roms/u-boot/cmd/usb_gadget_sdp.c b/roms/u-boot/cmd/usb_gadget_sdp.c
new file mode 100644
index 000000000..1af82e113
--- /dev/null
+++ b/roms/u-boot/cmd/usb_gadget_sdp.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * cmd_sdp.c -- sdp command
+ *
+ * Copyright (C) 2016 Toradex
+ * Author: Stefan Agner <stefan.agner@toradex.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <g_dnl.h>
+#include <sdp.h>
+#include <usb.h>
+
+static int do_sdp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ char *usb_controller = argv[1];
+ int controller_index = simple_strtoul(usb_controller, NULL, 0);
+ usb_gadget_initialize(controller_index);
+
+ g_dnl_clear_detach();
+ ret = g_dnl_register("usb_dnl_sdp");
+ if (ret) {
+ pr_err("SDP dnl register failed: %d\n", ret);
+ goto exit_register;
+ }
+
+ ret = sdp_init(controller_index);
+ if (ret) {
+ pr_err("SDP init failed: %d\n", ret);
+ goto exit;
+ }
+
+ /* This command typically does not return but jumps to an image */
+ sdp_handle(controller_index);
+ pr_err("SDP ended\n");
+
+exit:
+ g_dnl_unregister();
+exit_register:
+ usb_gadget_release(controller_index);
+
+ return CMD_RET_FAILURE;
+}
+
+U_BOOT_CMD(sdp, 2, 1, do_sdp,
+ "Serial Downloader Protocol",
+ "<USB_controller>\n"
+ " - serial downloader protocol via <USB_controller>\n"
+);
diff --git a/roms/u-boot/cmd/usb_mass_storage.c b/roms/u-boot/cmd/usb_mass_storage.c
new file mode 100644
index 000000000..14fa7233c
--- /dev/null
+++ b/roms/u-boot/cmd/usb_mass_storage.c
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <command.h>
+#include <console.h>
+#include <errno.h>
+#include <g_dnl.h>
+#include <malloc.h>
+#include <part.h>
+#include <usb.h>
+#include <usb_mass_storage.h>
+#include <watchdog.h>
+#include <linux/delay.h>
+
+static int ums_read_sector(struct ums *ums_dev,
+ ulong start, lbaint_t blkcnt, void *buf)
+{
+ struct blk_desc *block_dev = &ums_dev->block_dev;
+ lbaint_t blkstart = start + ums_dev->start_sector;
+
+ return blk_dread(block_dev, blkstart, blkcnt, buf);
+}
+
+static int ums_write_sector(struct ums *ums_dev,
+ ulong start, lbaint_t blkcnt, const void *buf)
+{
+ struct blk_desc *block_dev = &ums_dev->block_dev;
+ lbaint_t blkstart = start + ums_dev->start_sector;
+
+ return blk_dwrite(block_dev, blkstart, blkcnt, buf);
+}
+
+static struct ums *ums;
+static int ums_count;
+
+static void ums_fini(void)
+{
+ int i;
+
+ for (i = 0; i < ums_count; i++)
+ free((void *)ums[i].name);
+ free(ums);
+ ums = NULL;
+ ums_count = 0;
+}
+
+#define UMS_NAME_LEN 16
+
+static int ums_init(const char *devtype, const char *devnums_part_str)
+{
+ char *s, *t, *devnum_part_str, *name;
+ struct blk_desc *block_dev;
+ struct disk_partition info;
+ int partnum;
+ int ret = -1;
+ struct ums *ums_new;
+
+ s = strdup(devnums_part_str);
+ if (!s)
+ return -1;
+
+ t = s;
+ ums_count = 0;
+
+ for (;;) {
+ devnum_part_str = strsep(&t, ",");
+ if (!devnum_part_str)
+ break;
+
+ partnum = blk_get_device_part_str(devtype, devnum_part_str,
+ &block_dev, &info, 1);
+
+ if (partnum < 0)
+ goto cleanup;
+
+ /* Check if the argument is in legacy format. If yes,
+ * expose all partitions by setting the partnum = 0
+ * e.g. ums 0 mmc 0
+ */
+ if (!strchr(devnum_part_str, ':'))
+ partnum = 0;
+
+ /* f_mass_storage.c assumes SECTOR_SIZE sectors */
+ if (block_dev->blksz != SECTOR_SIZE)
+ goto cleanup;
+
+ ums_new = realloc(ums, (ums_count + 1) * sizeof(*ums));
+ if (!ums_new)
+ goto cleanup;
+ ums = ums_new;
+
+ /* if partnum = 0, expose all partitions */
+ if (partnum == 0) {
+ ums[ums_count].start_sector = 0;
+ ums[ums_count].num_sectors = block_dev->lba;
+ } else {
+ ums[ums_count].start_sector = info.start;
+ ums[ums_count].num_sectors = info.size;
+ }
+
+ ums[ums_count].read_sector = ums_read_sector;
+ ums[ums_count].write_sector = ums_write_sector;
+
+ name = malloc(UMS_NAME_LEN);
+ if (!name)
+ goto cleanup;
+ snprintf(name, UMS_NAME_LEN, "UMS disk %d", ums_count);
+ ums[ums_count].name = name;
+ ums[ums_count].block_dev = *block_dev;
+
+ printf("UMS: LUN %d, dev %s %d, hwpart %d, sector %#x, count %#x\n",
+ ums_count, devtype, ums[ums_count].block_dev.devnum,
+ ums[ums_count].block_dev.hwpart,
+ ums[ums_count].start_sector,
+ ums[ums_count].num_sectors);
+
+ ums_count++;
+ }
+
+ if (ums_count)
+ ret = 0;
+
+cleanup:
+ free(s);
+
+ if (ret < 0)
+ ums_fini();
+
+ return ret;
+}
+
+static int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ const char *usb_controller;
+ const char *devtype;
+ const char *devnum;
+ unsigned int controller_index;
+ int rc;
+ int cable_ready_timeout __maybe_unused;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ usb_controller = argv[1];
+ if (argc >= 4) {
+ devtype = argv[2];
+ devnum = argv[3];
+ } else {
+ devtype = "mmc";
+ devnum = argv[2];
+ }
+
+ rc = ums_init(devtype, devnum);
+ if (rc < 0)
+ return CMD_RET_FAILURE;
+
+ controller_index = (unsigned int)(simple_strtoul(
+ usb_controller, NULL, 0));
+ if (usb_gadget_initialize(controller_index)) {
+ pr_err("Couldn't init USB controller.\n");
+ rc = CMD_RET_FAILURE;
+ goto cleanup_ums_init;
+ }
+
+ rc = fsg_init(ums, ums_count, controller_index);
+ if (rc) {
+ pr_err("fsg_init failed\n");
+ rc = CMD_RET_FAILURE;
+ goto cleanup_board;
+ }
+
+ rc = g_dnl_register("usb_dnl_ums");
+ if (rc) {
+ pr_err("g_dnl_register failed\n");
+ rc = CMD_RET_FAILURE;
+ goto cleanup_board;
+ }
+
+ /* Timeout unit: seconds */
+ cable_ready_timeout = UMS_CABLE_READY_TIMEOUT;
+
+ if (!g_dnl_board_usb_cable_connected()) {
+ /*
+ * Won't execute if we don't know whether the cable is
+ * connected.
+ */
+ puts("Please connect USB cable.\n");
+
+ while (!g_dnl_board_usb_cable_connected()) {
+ if (ctrlc()) {
+ puts("\rCTRL+C - Operation aborted.\n");
+ rc = CMD_RET_SUCCESS;
+ goto cleanup_register;
+ }
+ if (!cable_ready_timeout) {
+ puts("\rUSB cable not detected.\n" \
+ "Command exit.\n");
+ rc = CMD_RET_SUCCESS;
+ goto cleanup_register;
+ }
+
+ printf("\rAuto exit in: %.2d s.", cable_ready_timeout);
+ mdelay(1000);
+ cable_ready_timeout--;
+ }
+ puts("\r\n");
+ }
+
+ while (1) {
+ usb_gadget_handle_interrupts(controller_index);
+
+ rc = fsg_main_thread(NULL);
+ if (rc) {
+ /* Check I/O error */
+ if (rc == -EIO)
+ printf("\rCheck USB cable connection\n");
+
+ /* Check CTRL+C */
+ if (rc == -EPIPE)
+ printf("\rCTRL+C - Operation aborted\n");
+
+ rc = CMD_RET_SUCCESS;
+ goto cleanup_register;
+ }
+
+ WATCHDOG_RESET();
+ }
+
+cleanup_register:
+ g_dnl_unregister();
+cleanup_board:
+ usb_gadget_release(controller_index);
+cleanup_ums_init:
+ ums_fini();
+
+ return rc;
+}
+
+U_BOOT_CMD(ums, 4, 1, do_usb_mass_storage,
+ "Use the UMS [USB Mass Storage]",
+ "<USB_controller> [<devtype>] <dev[:part]> e.g. ums 0 mmc 0\n"
+ " devtype defaults to mmc"
+);
diff --git a/roms/u-boot/cmd/version.c b/roms/u-boot/cmd/version.c
new file mode 100644
index 000000000..685b458ce
--- /dev/null
+++ b/roms/u-boot/cmd/version.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <version.h>
+#include <linux/compiler.h>
+#ifdef CONFIG_SYS_COREBOOT
+#include <asm/cb_sysinfo.h>
+#endif
+
+const char __weak version_string[] = U_BOOT_VERSION_STRING;
+
+static int do_version(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char buf[DISPLAY_OPTIONS_BANNER_LENGTH];
+
+ printf(display_options_get_banner(false, buf, sizeof(buf)));
+#ifdef CC_VERSION_STRING
+ puts(CC_VERSION_STRING "\n");
+#endif
+#ifdef LD_VERSION_STRING
+ puts(LD_VERSION_STRING "\n");
+#endif
+#ifdef CONFIG_SYS_COREBOOT
+ printf("coreboot-%s (%s)\n", lib_sysinfo.version, lib_sysinfo.build);
+#endif
+ return 0;
+}
+
+U_BOOT_CMD(
+ version, 1, 1, do_version,
+ "print monitor, compiler and linker version",
+ ""
+);
diff --git a/roms/u-boot/cmd/virtio.c b/roms/u-boot/cmd/virtio.c
new file mode 100644
index 000000000..3dace5344
--- /dev/null
+++ b/roms/u-boot/cmd/virtio.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <command.h>
+#include <dm.h>
+#include <virtio_types.h>
+#include <virtio.h>
+
+static int virtio_curr_dev;
+
+static int do_virtio(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ if (argc == 2 && !strcmp(argv[1], "scan")) {
+ /* make sure all virtio devices are enumerated */
+ virtio_init();
+
+ return CMD_RET_SUCCESS;
+ }
+
+ return blk_common_cmd(argc, argv, IF_TYPE_VIRTIO, &virtio_curr_dev);
+}
+
+U_BOOT_CMD(
+ virtio, 8, 1, do_virtio,
+ "virtio block devices sub-system",
+ "scan - initialize virtio bus\n"
+ "virtio info - show all available virtio block devices\n"
+ "virtio device [dev] - show or set current virtio block device\n"
+ "virtio part [dev] - print partition table of one or all virtio block devices\n"
+ "virtio read addr blk# cnt - read `cnt' blocks starting at block\n"
+ " `blk#' to memory address `addr'\n"
+ "virtio write addr blk# cnt - write `cnt' blocks starting at block\n"
+ " `blk#' from memory address `addr'"
+);
diff --git a/roms/u-boot/cmd/w1.c b/roms/u-boot/cmd/w1.c
new file mode 100644
index 000000000..d0f0ee123
--- /dev/null
+++ b/roms/u-boot/cmd/w1.c
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * (C) Copyright 2018
+ * Microchip Technology, Inc.
+ * Eugen Hristev <eugen.hristev@microchip.com>
+ */
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <w1.h>
+#include <w1-eeprom.h>
+#include <dm/device-internal.h>
+
+static int w1_bus(void)
+{
+ struct udevice *bus, *dev;
+ int ret;
+
+ ret = w1_get_bus(0, &bus);
+ if (ret) {
+ printf("one wire interface not found\n");
+ return CMD_RET_FAILURE;
+ }
+ printf("Bus %d:\t%s", dev_seq(bus), bus->name);
+ if (device_active(bus))
+ printf(" (active)");
+ printf("\n");
+
+ for (device_find_first_child(bus, &dev);
+ dev;
+ device_find_next_child(&dev)) {
+ ret = device_probe(dev);
+
+ printf("\t%s (%d) uclass %s : ", dev->name, dev_seq(dev),
+ dev->uclass->uc_drv->name);
+
+ if (ret)
+ printf("device error\n");
+ else
+ printf("family 0x%x\n", w1_get_device_family(dev));
+ }
+ return CMD_RET_SUCCESS;
+}
+
+static int w1_read(int argc, char *const argv[])
+{
+ int bus_n = 0, dev_n = 0, offset = 0, len = 512;
+ int i;
+ struct udevice *bus, *dev;
+ int ret;
+ u8 buf[512];
+
+ if (argc > 2)
+ bus_n = simple_strtoul(argv[2], NULL, 10);
+
+ if (argc > 3)
+ dev_n = simple_strtoul(argv[3], NULL, 10);
+
+ if (argc > 4)
+ offset = simple_strtoul(argv[4], NULL, 10);
+
+ if (argc > 5)
+ len = simple_strtoul(argv[5], NULL, 10);
+
+ if (len > 512) {
+ printf("len needs to be <= 512\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = w1_get_bus(bus_n, &bus);
+ if (ret) {
+ printf("one wire interface not found\n");
+ return CMD_RET_FAILURE;
+ }
+
+ for (device_find_first_child(bus, &dev), i = 0;
+ dev && i <= dev_n;
+ device_find_next_child(&dev), i++) {
+ ret = device_probe(dev);
+ if (!ret && i == dev_n)
+ break;
+ }
+
+ if (i != dev_n || ret || !dev) {
+ printf("invalid dev\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (strcmp(dev->uclass->uc_drv->name, "w1_eeprom")) {
+ printf("the device present on the interface is of unknown device class\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = w1_eeprom_read_buf(dev, offset, (u8 *)buf, len);
+ if (ret) {
+ printf("error reading device %s\n", dev->name);
+ return CMD_RET_FAILURE;
+ }
+
+ for (i = 0; i < len; i++)
+ printf("%x", buf[i]);
+ printf("\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+int do_w1(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(argv[1], "bus"))
+ return w1_bus();
+
+ if (!strcmp(argv[1], "read"))
+ return w1_read(argc, argv);
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(w1, 6, 0, do_w1,
+ "onewire interface utility commands",
+ "bus - show onewire bus info (all)\n"
+ "w1 read [<bus> [<dev> [offset [length]]]]"
+ " - read from onewire device 'dev' on onewire bus 'bus'"
+ " starting from offset 'offset' and length 'length'\n"
+ " defaults: bus 0, dev 0, offset 0, length 512 bytes.");
diff --git a/roms/u-boot/cmd/wdt.c b/roms/u-boot/cmd/wdt.c
new file mode 100644
index 000000000..27410981e
--- /dev/null
+++ b/roms/u-boot/cmd/wdt.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Watchdog commands
+ *
+ * Copyright (c) 2019 Michael Walle <michael@walle.cc>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <wdt.h>
+
+static struct udevice *currdev;
+
+static int do_wdt_list(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret;
+
+ ret = uclass_get(UCLASS_WDT, &uc);
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ uclass_foreach_dev(dev, uc)
+ printf("%s (%s)\n", dev->name, dev->driver->name);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_wdt_dev(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+
+ if (argc > 1) {
+ ret = uclass_get_device_by_name(UCLASS_WDT, argv[1], &currdev);
+ if (ret) {
+ printf("Can't get the watchdog timer: %s\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+ } else {
+ if (!currdev) {
+ printf("No watchdog timer device set!\n");
+ return CMD_RET_FAILURE;
+ }
+ printf("dev: %s\n", currdev->name);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int check_currdev(void)
+{
+ if (!currdev) {
+ printf("No device set, use 'wdt dev' first\n");
+ return CMD_RET_FAILURE;
+ }
+ return 0;
+}
+
+static int do_wdt_start(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+ u64 timeout;
+ ulong flags = 0;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ ret = check_currdev();
+ if (ret)
+ return ret;
+
+ timeout = simple_strtoull(argv[1], NULL, 0);
+ if (argc > 2)
+ flags = simple_strtoul(argv[2], NULL, 0);
+
+ ret = wdt_start(currdev, timeout, flags);
+ if (ret == -ENOSYS) {
+ printf("Starting watchdog timer not supported.\n");
+ return CMD_RET_FAILURE;
+ } else if (ret) {
+ printf("Starting watchdog timer failed (%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_wdt_stop(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+
+ ret = check_currdev();
+ if (ret)
+ return ret;
+
+ ret = wdt_stop(currdev);
+ if (ret == -ENOSYS) {
+ printf("Stopping watchdog timer not supported.\n");
+ return CMD_RET_FAILURE;
+ } else if (ret) {
+ printf("Stopping watchdog timer failed (%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_wdt_reset(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+
+ ret = check_currdev();
+ if (ret)
+ return ret;
+
+ ret = wdt_reset(currdev);
+ if (ret == -ENOSYS) {
+ printf("Resetting watchdog timer not supported.\n");
+ return CMD_RET_FAILURE;
+ } else if (ret) {
+ printf("Resetting watchdog timer failed (%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_wdt_expire(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+ ulong flags = 0;
+
+ ret = check_currdev();
+ if (ret)
+ return ret;
+
+ if (argc > 1)
+ flags = simple_strtoul(argv[1], NULL, 0);
+
+ ret = wdt_expire_now(currdev, flags);
+ if (ret == -ENOSYS) {
+ printf("Expiring watchdog timer not supported.\n");
+ return CMD_RET_FAILURE;
+ } else if (ret) {
+ printf("Expiring watchdog timer failed (%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static char wdt_help_text[] =
+ "list - list watchdog devices\n"
+ "wdt dev [<name>] - get/set current watchdog device\n"
+ "wdt start <timeout ms> [flags] - start watchdog timer\n"
+ "wdt stop - stop watchdog timer\n"
+ "wdt reset - reset watchdog timer\n"
+ "wdt expire [flags] - expire watchdog timer immediately\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(wdt, "Watchdog sub-system", wdt_help_text,
+ U_BOOT_SUBCMD_MKENT(list, 1, 1, do_wdt_list),
+ U_BOOT_SUBCMD_MKENT(dev, 2, 1, do_wdt_dev),
+ U_BOOT_SUBCMD_MKENT(start, 3, 1, do_wdt_start),
+ U_BOOT_SUBCMD_MKENT(stop, 1, 1, do_wdt_stop),
+ U_BOOT_SUBCMD_MKENT(reset, 1, 1, do_wdt_reset),
+ U_BOOT_SUBCMD_MKENT(expire, 2, 1, do_wdt_expire));
diff --git a/roms/u-boot/cmd/wol.c b/roms/u-boot/cmd/wol.c
new file mode 100644
index 000000000..f0d634322
--- /dev/null
+++ b/roms/u-boot/cmd/wol.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018
+ * Lothar Felte, lothar.felten@gmail.com
+ */
+
+/*
+ * Wake-on-LAN support
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+
+#if defined(CONFIG_CMD_WOL)
+void wol_set_timeout(ulong);
+
+int do_wol(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ /* Validate arguments */
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ wol_set_timeout(simple_strtol(argv[1], NULL, 10) * 1000);
+ if (net_loop(WOL) < 0)
+ return CMD_RET_FAILURE;
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ wol, 2, 1, do_wol,
+ "wait for an incoming wake-on-lan packet",
+ "Timeout"
+);
+#endif
diff --git a/roms/u-boot/cmd/x86/Makefile b/roms/u-boot/cmd/x86/Makefile
new file mode 100644
index 000000000..5f82204c8
--- /dev/null
+++ b/roms/u-boot/cmd/x86/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_CMD_CBSYSINFO) += cbsysinfo.o
+obj-y += mtrr.o
+obj-$(CONFIG_CMD_EXCEPTION) += exception.o
+obj-$(CONFIG_USE_HOB) += hob.o
+obj-$(CONFIG_HAVE_FSP) += fsp.o
diff --git a/roms/u-boot/cmd/x86/cbsysinfo.c b/roms/u-boot/cmd/x86/cbsysinfo.c
new file mode 100644
index 000000000..34fdaf5b1
--- /dev/null
+++ b/roms/u-boot/cmd/x86/cbsysinfo.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <command.h>
+#include <console.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void cbprompt(const char *name)
+{
+ for (; *name == '>'; name++)
+ puts(" ");
+ printf("%-12s: ", name);
+}
+
+static void print_dec(const char *name, int value)
+{
+ cbprompt(name);
+ printf(value > 9 ? "0d%d\n" : "%d\n", value);
+}
+
+static void print_hex(const char *name, int value)
+{
+ cbprompt(name);
+ printf("%x\n", value);
+}
+
+static void print_addr(const char *name, ulong value)
+{
+ cbprompt(name);
+ printf("%08lx\n", value);
+}
+
+static void print_addr64(const char *name, u64 value)
+{
+ cbprompt(name);
+ printf("%16llx\n", value);
+}
+
+static void print_ptr(const char *name, const void *value)
+{
+ cbprompt(name);
+ printf("%p\n", value);
+}
+
+static void print_str(const char *name, const char *value)
+{
+ if (value) {
+ cbprompt(name);
+ printf("%s\n", value);
+ }
+}
+
+static void print_idx(const char *name, uint idx, const u8 *strings)
+{
+ const char *ptr;
+
+ cbprompt(name);
+ ptr = (char *)strings + idx;
+ printf("%d: %s\n", idx, ptr ? ptr : "(unknown)");
+}
+
+static const char *const cb_mem_name[] = {
+ NULL,
+ "ram",
+ "reserved",
+ "acpi",
+ "nvs",
+ "unusable",
+ "vendor",
+};
+
+static const char *get_mem_name(int tag)
+{
+ if (tag >= CB_MEM_RAM && tag <= CB_MEM_VENDOR_RSVD)
+ return cb_mem_name[tag];
+
+ if (tag == CB_MEM_TABLE)
+ return "table";
+
+ return "(unknown)";
+}
+
+static const struct timestamp_id_to_name {
+ uint id;
+ const char *name;
+} timestamp_ids[] = {
+ /* Marker to report base_time */
+ { 0, "1st timestamp" },
+ { TS_START_ROMSTAGE, "start of romstage" },
+ { TS_BEFORE_INITRAM, "before ram initialization" },
+ { TS_AFTER_INITRAM, "after ram initialization" },
+ { TS_END_ROMSTAGE, "end of romstage" },
+ { TS_START_VBOOT, "start of verified boot" },
+ { TS_END_VBOOT, "end of verified boot" },
+ { TS_START_COPYRAM, "starting to load ramstage" },
+ { TS_END_COPYRAM, "finished loading ramstage" },
+ { TS_START_RAMSTAGE, "start of ramstage" },
+ { TS_START_BOOTBLOCK, "start of bootblock" },
+ { TS_END_BOOTBLOCK, "end of bootblock" },
+ { TS_START_COPYROM, "starting to load romstage" },
+ { TS_END_COPYROM, "finished loading romstage" },
+ { TS_START_ULZMA, "starting LZMA decompress (ignore for x86)" },
+ { TS_END_ULZMA, "finished LZMA decompress (ignore for x86)" },
+ { TS_START_ULZ4F, "starting LZ4 decompress (ignore for x86)" },
+ { TS_END_ULZ4F, "finished LZ4 decompress (ignore for x86)" },
+ { TS_DEVICE_ENUMERATE, "device enumeration" },
+ { TS_DEVICE_CONFIGURE, "device configuration" },
+ { TS_DEVICE_ENABLE, "device enable" },
+ { TS_DEVICE_INITIALIZE, "device initialization" },
+ { TS_DEVICE_DONE, "device setup done" },
+ { TS_CBMEM_POST, "cbmem post" },
+ { TS_WRITE_TABLES, "write tables" },
+ { TS_FINALIZE_CHIPS, "finalize chips" },
+ { TS_LOAD_PAYLOAD, "load payload" },
+ { TS_ACPI_WAKE_JUMP, "ACPI wake jump" },
+ { TS_SELFBOOT_JUMP, "selfboot jump" },
+
+ { TS_START_COPYVER, "starting to load verstage" },
+ { TS_END_COPYVER, "finished loading verstage" },
+ { TS_START_TPMINIT, "starting to initialize TPM" },
+ { TS_END_TPMINIT, "finished TPM initialization" },
+ { TS_START_VERIFY_SLOT, "starting to verify keyblock/preamble (RSA)" },
+ { TS_END_VERIFY_SLOT, "finished verifying keyblock/preamble (RSA)" },
+ { TS_START_HASH_BODY, "starting to verify body (load+SHA2+RSA) " },
+ { TS_DONE_LOADING, "finished loading body (ignore for x86)" },
+ { TS_DONE_HASHING, "finished calculating body hash (SHA2)" },
+ { TS_END_HASH_BODY, "finished verifying body signature (RSA)" },
+
+ { TS_START_COPYVPD, "starting to load Chrome OS VPD" },
+ { TS_END_COPYVPD_RO, "finished loading Chrome OS VPD (RO)" },
+ { TS_END_COPYVPD_RW, "finished loading Chrome OS VPD (RW)" },
+
+ { TS_U_BOOT_INITTED, "U-Boot start" },
+ { TS_RO_PARAMS_INIT, "RO parameter init" },
+ { TS_RO_VB_INIT, "RO vboot init" },
+ { TS_RO_VB_SELECT_FIRMWARE, "RO vboot select firmware" },
+ { TS_RO_VB_SELECT_AND_LOAD_KERNEL, "RO vboot select&load kernel" },
+ { TS_RW_VB_SELECT_AND_LOAD_KERNEL, "RW vboot select&load kernel" },
+ { TS_VB_SELECT_AND_LOAD_KERNEL, "vboot select&load kernel" },
+ { TS_VB_EC_VBOOT_DONE, "finished EC verification" },
+ { TS_VB_STORAGE_INIT_DONE, "finished storage device initialization" },
+ { TS_VB_READ_KERNEL_DONE, "finished reading kernel from disk" },
+ { TS_VB_VBOOT_DONE, "finished vboot kernel verification" },
+ { TS_KERNEL_DECOMPRESSION, "starting kernel decompression/relocation" },
+ { TS_START_KERNEL, "jumping to kernel" },
+ { TS_U_BOOT_START_KERNEL, "just before jump to kernel" },
+
+ /* Intel ME-related timestamps */
+ { TS_ME_INFORM_DRAM_WAIT, "waiting for ME acknowledgment of raminit"},
+ { TS_ME_INFORM_DRAM_DONE, "finished waiting for ME response"},
+
+ /* FSP-related timestamps */
+ { TS_FSP_MEMORY_INIT_START, "calling FspMemoryInit" },
+ { TS_FSP_MEMORY_INIT_END, "returning from FspMemoryInit" },
+ { TS_FSP_TEMP_RAM_EXIT_START, "calling FspTempRamExit" },
+ { TS_FSP_TEMP_RAM_EXIT_END, "returning from FspTempRamExit" },
+ { TS_FSP_SILICON_INIT_START, "calling FspSiliconInit" },
+ { TS_FSP_SILICON_INIT_END, "returning from FspSiliconInit" },
+ { TS_FSP_BEFORE_ENUMERATE, "calling FspNotify(AfterPciEnumeration)" },
+ { TS_FSP_AFTER_ENUMERATE,
+ "returning from FspNotify(AfterPciEnumeration)" },
+ { TS_FSP_BEFORE_FINALIZE, "calling FspNotify(ReadyToBoot)" },
+ { TS_FSP_AFTER_FINALIZE, "returning from FspNotify(ReadyToBoot)" },
+ { TS_FSP_BEFORE_END_OF_FIRMWARE, "calling FspNotify(EndOfFirmware)" },
+ { TS_FSP_AFTER_END_OF_FIRMWARE,
+ "returning from FspNotify(EndOfFirmware)" },
+};
+
+static const char *timestamp_name(uint32_t id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(timestamp_ids); i++) {
+ if (timestamp_ids[i].id == id)
+ return timestamp_ids[i].name;
+ }
+
+ return "<unknown>";
+}
+
+static void show_table(struct sysinfo_t *info, bool verbose)
+{
+ struct cb_serial *ser = info->serial;
+ int i;
+
+ printf("Coreboot table at %lx, decoded to %p",
+ gd->arch.coreboot_table, info);
+ if (info->header)
+ printf(", forwarded to %p\n", info->header);
+ printf("\n");
+
+ print_dec("CPU KHz", info->cpu_khz);
+
+ print_addr("Serial I/O port", info->ser_ioport);
+ print_addr(">base", info->ser_base);
+ print_ptr(">pointer", ser);
+ if (ser) {
+ print_hex(">type", ser->type);
+ print_addr(">base", ser->baseaddr);
+ print_dec(">baud", ser->baud);
+ print_hex(">regwidth", ser->regwidth);
+ print_dec(">input_hz", ser->input_hertz);
+ print_addr(">PCI addr", ser->uart_pci_addr);
+ }
+
+ print_dec("Mem ranges", info->n_memranges);
+ printf("%12s: %-11s || base || size\n", "id", "type");
+ for (i = 0; i < info->n_memranges; i++) {
+ const struct memrange *mr = &info->memrange[i];
+
+ printf("%12d: %02x:%-8s %016llx %016llx\n", i, mr->type,
+ get_mem_name(mr->type), mr->base, mr->size);
+ }
+ print_ptr("option_table", info->option_table);
+
+ print_hex("CMOS start", info->cmos_range_start);
+ if (info->cmos_range_start) {
+ print_hex(">CMOS end", info->cmos_range_end);
+ print_hex(">CMOS csum loc", info->cmos_checksum_location);
+ }
+
+ print_hex("VBNV start", info->vbnv_start);
+ print_hex("VBNV size", info->vbnv_size);
+
+ print_str("CB version", info->cb_version);
+ print_str(">Extra", info->extra_version);
+ print_str(">Build", info->build);
+ print_str(">Time", info->compile_time);
+ print_str(">By", info->compile_by);
+ print_str(">Host", info->compile_host);
+ print_str(">Domain", info->compile_domain);
+ print_str(">Compiler", info->compiler);
+ print_str(">Linker", info->linker);
+ print_str(">Assembler", info->assembler);
+
+ print_ptr("Framebuffer", info->framebuffer);
+ if (info->framebuffer) {
+ struct cb_framebuffer *fb = info->framebuffer;
+
+ print_addr64(">Phys addr", fb->physical_address);
+ print_dec(">X res", fb->x_resolution);
+ print_dec(">X res", fb->y_resolution);
+ print_hex(">Bytes / line", fb->bytes_per_line);
+ print_dec(">Bpp", fb->bits_per_pixel);
+ printf(" %-12s red %d/%d, green %d/%d, blue %d/%d, reserved %d/%d\n",
+ "pos/size", fb->red_mask_pos, fb->red_mask_size,
+ fb->green_mask_pos, fb->green_mask_size,
+ fb->blue_mask_pos, fb->blue_mask_size,
+ fb->reserved_mask_pos, fb->reserved_mask_size);
+ }
+
+ print_dec("GPIOs", info->num_gpios);
+ printf("%12s: %4s %12s %3s %s\n", "id", "port", "polarity", "val",
+ "name");
+ for (i = 0; i < info->num_gpios; i++) {
+ const struct cb_gpio *gpio = &info->gpios[i];
+ char portstr[4];
+
+ if (gpio->port == 0xffffffff)
+ strcpy(portstr, "-");
+ else
+ sprintf(portstr, "%x", gpio->port);
+ printf("%12d: %4s %12s %3d %s\n", i, portstr,
+ gpio->polarity == CB_GPIO_ACTIVE_LOW ? "active-low" :
+ "active-high", gpio->value, gpio->name);
+ }
+ print_dec("MACs", info->num_macs);
+ for (i = 0; i < info->num_macs; i++) {
+ const struct mac_address *mac = &info->macs[i];
+ int j;
+
+ printf("%12d: ", i);
+ for (j = 0; j < sizeof(mac->mac_addr); j++)
+ printf("%s%02x", j ? ":" : "", mac->mac_addr[j]);
+ printf("\n");
+ }
+ print_str(">Serial #", info->serialno);
+ print_ptr("Multiboot tab", info->mbtable);
+ print_ptr("CB header", info->header);
+ print_ptr("CB mainboard", info->mainboard);
+ if (info->mainboard) {
+ struct cb_mainboard *mb = info->mainboard;
+
+ print_idx(">vendor", mb->vendor_idx, mb->strings);
+ print_idx(">part_number", mb->part_number_idx, mb->strings);
+ }
+ print_ptr("vboot handoff", info->vboot_handoff);
+ print_hex(">size", info->vboot_handoff_size);
+ print_ptr(">vdat addr", info->vdat_addr);
+ print_hex(">size", info->vdat_size);
+
+ print_addr64("SMBIOS", info->smbios_start);
+ print_hex(">size", info->smbios_size);
+ print_hex("ROM MTRR", info->x86_rom_var_mtrr_index);
+
+ print_ptr("Tstamp table", info->tstamp_table);
+ if (verbose && info->tstamp_table) {
+ struct timestamp_table *ts = info->tstamp_table;
+
+ printf("%-12s", "Base_time");
+ print_grouped_ull(ts->base_time, 12);
+ printf("\n");
+ print_dec("Tick MHz", ts->tick_freq_mhz);
+ for (i = 0; i < ts->num_entries; i++) {
+ const struct timestamp_entry *tse;
+
+ tse = &ts->entries[i];
+ printf(" ");
+ print_grouped_ull(tse->entry_stamp, 12);
+ printf(" %s\n", timestamp_name(tse->entry_id));
+ }
+ }
+
+ print_ptr("CBmem cons", info->cbmem_cons);
+ if (info->cbmem_cons) {
+ struct cbmem_console *cons = info->cbmem_cons;
+ int i;
+
+ print_hex("Size", cons->size);
+ print_hex("Cursor", cons->cursor);
+ if (verbose) {
+ for (i = 0; i < cons->cursor; i++) {
+ int ch = cons->body[i];
+
+ putc(ch);
+
+ if (ch == '\n') {
+ /* check for ctrl-c to abort... */
+ if (ctrlc()) {
+ puts("Abort\n");
+ return;
+ }
+ printf(" ");
+ }
+ }
+ printf("\n");
+ }
+ }
+
+ print_ptr("MRC cache", info->mrc_cache);
+ print_ptr("ACPI GNVS", info->acpi_gnvs);
+ print_hex("Board ID", info->board_id);
+ print_hex("RAM code", info->ram_code);
+ print_ptr("WiFi calib", info->wifi_calibration);
+ print_addr64("Ramoops buff", info->ramoops_buffer);
+ print_hex(">size", info->ramoops_buffer_size);
+ print_hex("SF size", info->spi_flash.size);
+ print_hex("SF sector", info->spi_flash.sector_size);
+ print_hex("SF erase cmd", info->spi_flash.erase_cmd);
+
+ print_addr64("FMAP offset", info->fmap_offset);
+ print_addr64("CBFS offset", info->cbfs_offset);
+ print_addr64("CBFS size", info->cbfs_size);
+ print_addr64("Boot media size", info->boot_media_size);
+ print_addr64("MTC start", info->mtc_start);
+ print_hex("MTC size", info->mtc_size);
+
+ print_ptr("Chrome OS VPD", info->chromeos_vpd);
+}
+
+static int do_cbsysinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ bool verbose = false;
+
+ if (argc > 1) {
+ if (!strcmp("-v", argv[1]))
+ verbose = true;
+ else
+ return CMD_RET_USAGE;
+ }
+
+ if (!gd->arch.coreboot_table) {
+ printf("No coreboot sysinfo table found\n");
+ return CMD_RET_FAILURE;
+ }
+ show_table(&lib_sysinfo, verbose);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ cbsysinfo, 2, 1, do_cbsysinfo,
+ "Show coreboot sysinfo table",
+ "[-v] Dumps out the contents of the sysinfo table. This only\n"
+ "works if U-Boot is booted from coreboot"
+);
diff --git a/roms/u-boot/cmd/x86/exception.c b/roms/u-boot/cmd/x86/exception.c
new file mode 100644
index 000000000..82faaa913
--- /dev/null
+++ b/roms/u-boot/cmd/x86/exception.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The 'exception' command can be used for testing exception handling.
+ *
+ * Copyright (c) 2018, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <command.h>
+
+static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ asm volatile (".word 0xffff\n");
+ return CMD_RET_FAILURE;
+}
+
+static struct cmd_tbl cmd_sub[] = {
+ U_BOOT_CMD_MKENT(undefined, CONFIG_SYS_MAXARGS, 1, do_undefined,
+ "", ""),
+};
+
+static char exception_help_text[] =
+ "<ex>\n"
+ " The following exceptions are available:\n"
+ " undefined - undefined instruction\n"
+ ;
+
+#include <exception.h>
diff --git a/roms/u-boot/cmd/x86/fsp.c b/roms/u-boot/cmd/x86/fsp.c
new file mode 100644
index 000000000..82e4415b1
--- /dev/null
+++ b/roms/u-boot/cmd/x86/fsp.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014-2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/fsp/fsp_support.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int do_hdr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct fsp_header *hdr;
+ u32 img_addr;
+ char *sign;
+ uint addr;
+ int i;
+
+#ifdef CONFIG_FSP_VERSION2
+ /*
+ * Only FSP-S is displayed. FSP-M was used in SPL but may not still be
+ * around, and we didn't keep a pointer to it.
+ */
+ hdr = gd->arch.fsp_s_hdr;
+ img_addr = hdr->img_base;
+ addr = img_addr;
+#else
+ addr = CONFIG_FSP_ADDR;
+ hdr = fsp_find_header();
+ img_addr = hdr->img_base;
+#endif
+ sign = (char *)&hdr->sign;
+
+ printf("FSP : binary %08x, header %08x\n", addr, (int)hdr);
+ printf("Header : sign ");
+ for (i = 0; i < sizeof(hdr->sign); i++)
+ printf("%c", *sign++);
+ printf(", size %x, rev %d\n", hdr->hdr_len, hdr->hdr_rev);
+ printf("Image : rev ");
+ if (hdr->hdr_rev == FSP_HEADER_REVISION_1) {
+ printf("%d.%d",
+ (hdr->img_rev >> 8) & 0xff, hdr->img_rev & 0xff);
+ } else {
+ printf("%d.%d.%d.%d",
+ (hdr->img_rev >> 24) & 0xff, (hdr->img_rev >> 16) & 0xff,
+ (hdr->img_rev >> 8) & 0xff, hdr->img_rev & 0xff);
+ }
+ printf(", id ");
+ for (i = 0; i < ARRAY_SIZE(hdr->img_id); i++)
+ printf("%c", hdr->img_id[i]);
+ printf(", addr %08x, size %x\n", img_addr, hdr->img_size);
+ if (hdr->hdr_rev >= FSP_HEADER_REVISION_1) {
+ printf("GFX :%ssupported\n",
+ hdr->img_attr & FSP_ATTR_GRAPHICS_SUPPORT ? " " : " un");
+ }
+ printf("VPD : addr %08x, size %x\n",
+ hdr->cfg_region_off + img_addr, hdr->cfg_region_size);
+ if (hdr->hdr_rev <= FSP_HEADER_REVISION_2)
+ printf("\nNumber of APIs Supported : %d\n", hdr->api_num);
+ if (hdr->fsp_tempram_init)
+ printf("\tTempRamInit : %08x\n",
+ hdr->fsp_tempram_init + img_addr);
+ if (hdr->fsp_init)
+ printf("\tFspInit : %08x\n", hdr->fsp_init + img_addr);
+ if (hdr->fsp_notify)
+ printf("\tFspNotify : %08x\n", hdr->fsp_notify + img_addr);
+ if (hdr->hdr_rev >= FSP_HEADER_REVISION_1) {
+ if (hdr->fsp_mem_init)
+ printf("\tMemoryInit : %08x\n",
+ hdr->fsp_mem_init + img_addr);
+ if (hdr->fsp_tempram_exit)
+ printf("\tTempRamExit : %08x\n",
+ hdr->fsp_tempram_exit + img_addr);
+ if (hdr->fsp_silicon_init)
+ printf("\tSiliconInit : %08x\n",
+ hdr->fsp_silicon_init + img_addr);
+ }
+
+ return 0;
+}
+
+static struct cmd_tbl fsp_commands[] = {
+ U_BOOT_CMD_MKENT(hdr, 0, 1, do_hdr, "", ""),
+};
+
+static int do_fsp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct cmd_tbl *fsp_cmd;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ fsp_cmd = find_cmd_tbl(argv[1], fsp_commands, ARRAY_SIZE(fsp_commands));
+ argc -= 2;
+ argv += 2;
+ if (!fsp_cmd || argc > fsp_cmd->maxargs)
+ return CMD_RET_USAGE;
+
+ ret = fsp_cmd->cmd(fsp_cmd, flag, argc, argv);
+
+ return cmd_process_error(fsp_cmd, ret);
+}
+
+U_BOOT_CMD(
+ fsp, 2, 1, do_fsp,
+ "Show Intel Firmware Support Package (FSP) related information",
+ "hdr - Print FSP header information"
+);
diff --git a/roms/u-boot/cmd/x86/hob.c b/roms/u-boot/cmd/x86/hob.c
new file mode 100644
index 000000000..01db93eb3
--- /dev/null
+++ b/roms/u-boot/cmd/x86/hob.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014-2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <efi.h>
+#include <uuid.h>
+#include <asm/global_data.h>
+#include <asm/hob.h>
+#include <asm/fsp/fsp_hob.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char *hob_type[] = {
+ "reserved",
+ "Hand-off",
+ "Mem Alloc",
+ "Res Desc",
+ "GUID Ext",
+ "FV",
+ "CPU",
+ "Mem Pool",
+ "reserved",
+ "FV2",
+ "Load PEIM",
+ "Capsule",
+};
+
+static char *res_type[] = {
+ "System",
+ "Memory-mapped I/O",
+ "I/O",
+ "Firmware device",
+ "Memory-mapped I/O port",
+ "Reserved",
+ "I/O reserved",
+};
+
+static struct guid_name {
+ efi_guid_t guid;
+ const char *name;
+} guid_name[] = {
+ { FSP_HOB_RESOURCE_OWNER_TSEG_GUID, "TSEG" },
+ { FSP_HOB_RESOURCE_OWNER_FSP_GUID, "FSP" },
+ { FSP_HOB_RESOURCE_OWNER_SMM_PEI_SMRAM_GUID, "SMM PEI SMRAM" },
+ { FSP_NON_VOLATILE_STORAGE_HOB_GUID, "NVS" },
+ { FSP_VARIABLE_NV_DATA_HOB_GUID, "Variable NVS" },
+ { FSP_GRAPHICS_INFO_HOB_GUID, "Graphics info" },
+ { FSP_HOB_RESOURCE_OWNER_PCD_DATABASE_GUID1, "PCD database ea" },
+ { FSP_HOB_RESOURCE_OWNER_PCD_DATABASE_GUID2, "PCD database 9b" },
+ { FSP_HOB_RESOURCE_OWNER_PEIM_DXE_GUID, "PEIM Init DXE" },
+ { FSP_HOB_RESOURCE_OWNER_ALLOC_STACK_GUID, "Alloc stack" },
+ { FSP_HOB_RESOURCE_OWNER_SMBIOS_MEMORY_GUID, "SMBIOS memory" },
+ { {}, "zero-guid" },
+ {}
+};
+
+static const char *guid_to_name(const efi_guid_t *guid)
+{
+ struct guid_name *entry;
+
+ for (entry = guid_name; entry->name; entry++) {
+ if (!guidcmp(guid, &entry->guid))
+ return entry->name;
+ }
+
+ return NULL;
+}
+
+static void show_hob_details(const struct hob_header *hdr)
+{
+ const void *ptr = hdr;
+
+ switch (hdr->type) {
+ case HOB_TYPE_RES_DESC: {
+ const struct hob_res_desc *res = ptr;
+ const char *typename;
+
+ typename = res->type > 0 && res->type <= RES_MAX_MEM_TYPE ?
+ res_type[res->type] : "unknown";
+
+ printf(" base = %08llx, len = %08llx, end = %08llx, type = %d (%s)\n\n",
+ res->phys_start, res->len, res->phys_start + res->len,
+ res->type, typename);
+ break;
+ }
+ }
+}
+
+static int do_hob(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const struct hob_header *hdr;
+ uint type;
+ char *desc;
+ int i = 0;
+ efi_guid_t *guid;
+ char uuid[UUID_STR_LEN + 1];
+ bool verbose = false;
+ int seq = -1; /* Show all by default */
+
+ argc--;
+ argv++;
+ if (argc) {
+ if (!strcmp("-v", *argv)) {
+ verbose = true;
+ argc--;
+ argv++;
+ }
+ if (argc)
+ seq = simple_strtol(*argv, NULL, 16);
+ }
+ hdr = gd->arch.hob_list;
+
+ printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
+
+ printf("# | Address | Type | Len | ");
+ printf("%36s\n", "GUID");
+ printf("---|----------|-----------|------|-");
+ printf("------------------------------------\n");
+ for (i = 0; !end_of_hob(hdr); i++, hdr = get_next_hob(hdr)) {
+ if (seq != -1 && seq != i)
+ continue;
+ printf("%02x | %08x | ", i, (unsigned int)hdr);
+ type = hdr->type;
+ if (type == HOB_TYPE_UNUSED)
+ desc = "*Unused*";
+ else if (type == HOB_TYPE_EOH)
+ desc = "*EOH*";
+ else if (type >= 0 && type <= ARRAY_SIZE(hob_type))
+ desc = hob_type[type];
+ else
+ desc = "*Invalid*";
+ printf("%-9s | %04x | ", desc, hdr->len);
+
+ if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC ||
+ type == HOB_TYPE_GUID_EXT) {
+ const char *name;
+
+ guid = (efi_guid_t *)(hdr + 1);
+ name = guid_to_name(guid);
+ if (!name) {
+ uuid_bin_to_str(guid->b, uuid,
+ UUID_STR_FORMAT_GUID);
+ name = uuid;
+ }
+ printf("%36s", name);
+ } else {
+ printf("%36s", "Not Available");
+ }
+ printf("\n");
+ if (verbose)
+ show_hob_details(hdr);
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(hob, 3, 1, do_hob,
+ "[-v] [seq] Print Hand-Off Block (HOB) information"
+ " -v - Show detailed HOB information where available"
+ " seq - Record # to show (all by default)",
+ ""
+);
diff --git a/roms/u-boot/cmd/x86/mtrr.c b/roms/u-boot/cmd/x86/mtrr.c
new file mode 100644
index 000000000..fc61a549b
--- /dev/null
+++ b/roms/u-boot/cmd/x86/mtrr.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 Google, Inc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <log.h>
+#include <asm/msr.h>
+#include <asm/mp.h>
+#include <asm/mtrr.h>
+
+static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
+ "Uncacheable",
+ "Combine",
+ "2",
+ "3",
+ "Through",
+ "Protect",
+ "Back",
+};
+
+static void read_mtrrs(void *arg)
+{
+ struct mtrr_info *info = arg;
+
+ mtrr_read_all(info);
+}
+
+static int do_mtrr_list(int reg_count, int cpu_select)
+{
+ struct mtrr_info info;
+ int ret;
+ int i;
+
+ printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||",
+ "Mask ||", "Size ||");
+ memset(&info, '\0', sizeof(info));
+ ret = mp_run_on_cpus(cpu_select, read_mtrrs, &info);
+ if (ret)
+ return log_msg_ret("run", ret);
+ for (i = 0; i < reg_count; i++) {
+ const char *type = "Invalid";
+ uint64_t base, mask, size;
+ bool valid;
+
+ base = info.mtrr[i].base;
+ mask = info.mtrr[i].mask;
+ size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
+ size |= (1 << 12) - 1;
+ size += 1;
+ valid = mask & MTRR_PHYS_MASK_VALID;
+ type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
+ printf("%d %-5s %-12s %016llx %016llx %016llx\n", i,
+ valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
+ mask & ~MTRR_PHYS_MASK_VALID, size);
+ }
+
+ return 0;
+}
+
+static int do_mtrr_set(int cpu_select, uint reg, int argc, char *const argv[])
+{
+ const char *typename = argv[0];
+ uint32_t start, size;
+ uint64_t base, mask;
+ int i, type = -1;
+ bool valid;
+ int ret;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+ for (i = 0; i < MTRR_TYPE_COUNT; i++) {
+ if (*typename == *mtrr_type_name[i])
+ type = i;
+ }
+ if (type == -1) {
+ printf("Invalid type name %s\n", typename);
+ return CMD_RET_USAGE;
+ }
+ start = simple_strtoul(argv[1], NULL, 16);
+ size = simple_strtoul(argv[2], NULL, 16);
+
+ base = start | type;
+ valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID;
+ mask = ~((uint64_t)size - 1);
+ mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+ if (valid)
+ mask |= MTRR_PHYS_MASK_VALID;
+
+ ret = mtrr_set(cpu_select, reg, base, mask);
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ return 0;
+}
+
+static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int reg_count = mtrr_get_var_count();
+ int cmd;
+ int cpu_select;
+ uint reg;
+ int ret;
+
+ cpu_select = MP_SELECT_BSP;
+ if (argc >= 3 && !strcmp("-c", argv[1])) {
+ const char *cpustr;
+
+ cpustr = argv[2];
+ if (*cpustr == 'a')
+ cpu_select = MP_SELECT_ALL;
+ else
+ cpu_select = simple_strtol(cpustr, NULL, 16);
+ argc -= 2;
+ argv += 2;
+ }
+ argc--;
+ argv++;
+ cmd = argv[0] ? *argv[0] : 0;
+ if (argc < 1 || !cmd) {
+ cmd = 'l';
+ reg = 0;
+ }
+ if (cmd != 'l') {
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ reg = simple_strtoul(argv[1], NULL, 16);
+ if (reg >= reg_count) {
+ printf("Invalid register number\n");
+ return CMD_RET_USAGE;
+ }
+ }
+ if (cmd == 'l') {
+ bool first;
+ int i;
+
+ i = mp_first_cpu(cpu_select);
+ if (i < 0) {
+ printf("Invalid CPU (err=%d)\n", i);
+ return CMD_RET_FAILURE;
+ }
+ first = true;
+ for (; i >= 0; i = mp_next_cpu(cpu_select, i)) {
+ if (!first)
+ printf("\n");
+ printf("CPU %d:\n", i);
+ ret = do_mtrr_list(reg_count, i);
+ if (ret) {
+ printf("Failed to read CPU %d (err=%d)\n", i,
+ ret);
+ return CMD_RET_FAILURE;
+ }
+ first = false;
+ }
+ } else {
+ switch (cmd) {
+ case 'e':
+ ret = mtrr_set_valid(cpu_select, reg, true);
+ break;
+ case 'd':
+ ret = mtrr_set_valid(cpu_select, reg, false);
+ break;
+ case 's':
+ ret = do_mtrr_set(cpu_select, reg, argc - 2, argv + 2);
+ break;
+ default:
+ return CMD_RET_USAGE;
+ }
+ if (ret) {
+ printf("Operation failed (err=%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ mtrr, 8, 1, do_mtrr,
+ "Use x86 memory type range registers (32-bit only)",
+ "[list] - list current registers\n"
+ "set <reg> <type> <start> <size> - set a register\n"
+ "\t<type> is Uncacheable, Combine, Through, Protect, Back\n"
+ "disable <reg> - disable a register\n"
+ "enable <reg> - enable a register\n"
+ "\n"
+ "Precede command with '-c <n>|all' to access a particular hex CPU, e.g.\n"
+ " mtrr -c all list; mtrr -c 2e list"
+);
diff --git a/roms/u-boot/cmd/ximg.c b/roms/u-boot/cmd/ximg.c
new file mode 100644
index 000000000..ef738ebfa
--- /dev/null
+++ b/roms/u-boot/cmd/ximg.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2003
+ * Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.de>
+ */
+
+
+/*
+ * Multi Image extract
+ */
+#include <common.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <env.h>
+#include <gzip.h>
+#include <image.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <watchdog.h>
+#if defined(CONFIG_BZIP2)
+#include <bzlib.h>
+#endif
+#include <asm/byteorder.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+#ifndef CONFIG_SYS_XIMG_LEN
+/* use 8MByte as default max gunzip size */
+#define CONFIG_SYS_XIMG_LEN 0x800000
+#endif
+
+static int
+do_imgextract(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ ulong addr = image_load_addr;
+ ulong dest = 0;
+ ulong data, len;
+ int verify;
+ int part = 0;
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ ulong count;
+ image_header_t *hdr = NULL;
+#endif
+#if defined(CONFIG_FIT)
+ const char *uname = NULL;
+ const void* fit_hdr;
+ int noffset;
+ const void *fit_data;
+ size_t fit_len;
+#endif
+#ifdef CONFIG_GZIP
+ uint unc_len = CONFIG_SYS_XIMG_LEN;
+#endif
+ uint8_t comp;
+
+ verify = env_get_yesno("verify");
+
+ if (argc > 1) {
+ addr = simple_strtoul(argv[1], NULL, 16);
+ }
+ if (argc > 2) {
+ part = simple_strtoul(argv[2], NULL, 16);
+#if defined(CONFIG_FIT)
+ uname = argv[2];
+#endif
+ }
+ if (argc > 3) {
+ dest = simple_strtoul(argv[3], NULL, 16);
+ }
+
+ switch (genimg_get_format((void *)addr)) {
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ case IMAGE_FORMAT_LEGACY:
+
+ printf("## Copying part %d from legacy image "
+ "at %08lx ...\n", part, addr);
+
+ hdr = (image_header_t *)addr;
+ if (!image_check_magic(hdr)) {
+ printf("Bad Magic Number\n");
+ return 1;
+ }
+
+ if (!image_check_hcrc(hdr)) {
+ printf("Bad Header Checksum\n");
+ return 1;
+ }
+#ifdef DEBUG
+ image_print_contents(hdr);
+#endif
+
+ if (!image_check_type(hdr, IH_TYPE_MULTI) &&
+ !image_check_type(hdr, IH_TYPE_SCRIPT)) {
+ printf("Wrong Image Type for %s command\n",
+ cmdtp->name);
+ return 1;
+ }
+
+ comp = image_get_comp(hdr);
+ if ((comp != IH_COMP_NONE) && (argc < 4)) {
+ printf("Must specify load address for %s command "
+ "with compressed image\n",
+ cmdtp->name);
+ return 1;
+ }
+
+ if (verify) {
+ printf(" Verifying Checksum ... ");
+ if (!image_check_dcrc(hdr)) {
+ printf("Bad Data CRC\n");
+ return 1;
+ }
+ printf("OK\n");
+ }
+
+ count = image_multi_count(hdr);
+ if (part >= count) {
+ printf("Bad Image Part\n");
+ return 1;
+ }
+
+ image_multi_getimg(hdr, part, &data, &len);
+ break;
+#endif
+#if defined(CONFIG_FIT)
+ case IMAGE_FORMAT_FIT:
+ if (uname == NULL) {
+ puts("No FIT subimage unit name\n");
+ return 1;
+ }
+
+ printf("## Copying '%s' subimage from FIT image "
+ "at %08lx ...\n", uname, addr);
+
+ fit_hdr = (const void *)addr;
+ if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
+ puts("Bad FIT image format\n");
+ return 1;
+ }
+
+ /* get subimage node offset */
+ noffset = fit_image_get_node(fit_hdr, uname);
+ if (noffset < 0) {
+ printf("Can't find '%s' FIT subimage\n", uname);
+ return 1;
+ }
+
+ if (!fit_image_check_comp(fit_hdr, noffset, IH_COMP_NONE)
+ && (argc < 4)) {
+ printf("Must specify load address for %s command "
+ "with compressed image\n",
+ cmdtp->name);
+ return 1;
+ }
+
+ /* verify integrity */
+ if (verify) {
+ if (!fit_image_verify(fit_hdr, noffset)) {
+ puts("Bad Data Hash\n");
+ return 1;
+ }
+ }
+
+ /* get subimage/external data address and length */
+ if (fit_image_get_data_and_size(fit_hdr, noffset,
+ &fit_data, &fit_len)) {
+ puts("Could not find script subimage data\n");
+ return 1;
+ }
+
+ if (fit_image_get_comp(fit_hdr, noffset, &comp)) {
+ puts("Could not find script subimage "
+ "compression type\n");
+ return 1;
+ }
+
+ data = (ulong)fit_data;
+ len = (ulong)fit_len;
+ break;
+#endif
+ default:
+ puts("Invalid image type for imxtract\n");
+ return 1;
+ }
+
+ if (argc > 3) {
+ switch (comp) {
+ case IH_COMP_NONE:
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ {
+ size_t l = len;
+ size_t tail;
+ void *to = (void *) dest;
+ void *from = (void *)data;
+
+ printf(" Loading part %d ... ", part);
+
+ while (l > 0) {
+ tail = (l > CHUNKSZ) ? CHUNKSZ : l;
+ WATCHDOG_RESET();
+ memmove(to, from, tail);
+ to += tail;
+ from += tail;
+ l -= tail;
+ }
+ }
+#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */
+ printf(" Loading part %d ... ", part);
+ memmove((char *) dest, (char *)data, len);
+#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */
+ break;
+#ifdef CONFIG_GZIP
+ case IH_COMP_GZIP:
+ printf(" Uncompressing part %d ... ", part);
+ if (gunzip((void *) dest, unc_len,
+ (uchar *) data, &len) != 0) {
+ puts("GUNZIP ERROR - image not loaded\n");
+ return 1;
+ }
+ break;
+#endif
+#if defined(CONFIG_BZIP2) && defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ case IH_COMP_BZIP2:
+ {
+ int i;
+
+ printf(" Uncompressing part %d ... ", part);
+ /*
+ * If we've got less than 4 MB of malloc()
+ * space, use slower decompression algorithm
+ * which requires at most 2300 KB of memory.
+ */
+ i = BZ2_bzBuffToBuffDecompress(
+ map_sysmem(ntohl(hdr->ih_load), 0),
+ &unc_len, (char *)data, len,
+ CONFIG_SYS_MALLOC_LEN < (4096 * 1024),
+ 0);
+ if (i != BZ_OK) {
+ printf("BUNZIP2 ERROR %d - "
+ "image not loaded\n", i);
+ return 1;
+ }
+ }
+ break;
+#endif /* CONFIG_BZIP2 */
+ default:
+ printf("Unimplemented compression type %d\n", comp);
+ return 1;
+ }
+ puts("OK\n");
+ }
+
+ flush_cache(dest, ALIGN(len, ARCH_DMA_MINALIGN));
+
+ env_set_hex("fileaddr", data);
+ env_set_hex("filesize", len);
+
+ return 0;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char imgextract_help_text[] =
+ "addr part [dest]\n"
+ " - extract <part> from legacy image at <addr> and copy to <dest>"
+#if defined(CONFIG_FIT)
+ "\n"
+ "addr uname [dest]\n"
+ " - extract <uname> subimage from FIT image at <addr> and copy to <dest>"
+#endif
+ "";
+#endif
+
+U_BOOT_CMD(
+ imxtract, 4, 1, do_imgextract,
+ "extract a part of a multi-image", imgextract_help_text
+);
diff --git a/roms/u-boot/cmd/yaffs2.c b/roms/u-boot/cmd/yaffs2.c
new file mode 100644
index 000000000..f29ebcc02
--- /dev/null
+++ b/roms/u-boot/cmd/yaffs2.c
@@ -0,0 +1,326 @@
+/* Yaffs commands.
+ * Modified by Charles Manning by adding ydevconfig command.
+ *
+ * Use ydevconfig to configure a mountpoint before use.
+ * For example:
+ * # Configure mountpt xxx using nand device 0 using blocks 100-500
+ * ydevconfig xxx 0 100 500
+ * # Mount it
+ * ymount xxx
+ * # yls, yrdm etc
+ * yls -l xxx
+ * yrdm xxx/boot-image 82000000
+ * ...
+ */
+
+#include <common.h>
+
+#include <config.h>
+#include <command.h>
+
+#ifdef YAFFS2_DEBUG
+#define PRINTF(fmt, args...) printf(fmt, ##args)
+#else
+#define PRINTF(fmt, args...) do { } while (0)
+#endif
+
+extern void cmd_yaffs_dev_ls(void);
+extern void cmd_yaffs_tracemask(unsigned set, unsigned mask);
+extern void cmd_yaffs_devconfig(char *mp, int flash_dev,
+ int start_block, int end_block);
+extern void cmd_yaffs_mount(char *mp);
+extern void cmd_yaffs_umount(char *mp);
+extern void cmd_yaffs_read_file(char *fn);
+extern void cmd_yaffs_write_file(char *fn, char bval, int sizeOfFile);
+extern void cmd_yaffs_ls(const char *mountpt, int longlist);
+extern void cmd_yaffs_mwrite_file(char *fn, char *addr, int size);
+extern void cmd_yaffs_mread_file(char *fn, char *addr);
+extern void cmd_yaffs_mkdir(const char *dir);
+extern void cmd_yaffs_rmdir(const char *dir);
+extern void cmd_yaffs_rm(const char *path);
+extern void cmd_yaffs_mv(const char *oldPath, const char *newPath);
+
+extern int yaffs_dump_dev(const char *path);
+
+/* ytrace - show/set yaffs trace mask */
+int do_ytrace(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc > 1)
+ cmd_yaffs_tracemask(1, simple_strtol(argv[1], NULL, 16));
+ else
+ cmd_yaffs_tracemask(0, 0);
+
+ return 0;
+}
+
+/* ydevls - lists yaffs mount points. */
+int do_ydevls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ cmd_yaffs_dev_ls();
+
+ return 0;
+}
+
+/* ydevconfig mount_pt mtd_dev_num start_block end_block */
+int do_ydevconfig(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *mtpoint;
+ int mtd_dev;
+ int start_block;
+ int end_block;
+
+ if (argc != 5) {
+ printf
+ ("Bad arguments: ydevconfig mount_pt mtd_dev start_block end_block\n");
+ return -1;
+ }
+
+ mtpoint = argv[1];
+ mtd_dev = simple_strtol(argv[2], NULL, 16);
+ start_block = simple_strtol(argv[3], NULL, 16);
+ end_block = simple_strtol(argv[4], NULL, 16);
+
+ cmd_yaffs_devconfig(mtpoint, mtd_dev, start_block, end_block);
+
+ return 0;
+}
+
+int do_ymount(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *mtpoint;
+
+ if (argc != 2) {
+ printf("Bad arguments: ymount mount_pt\n");
+ return -1;
+ }
+
+ mtpoint = argv[1];
+ printf("Mounting yaffs2 mount point %s\n", mtpoint);
+
+ cmd_yaffs_mount(mtpoint);
+
+ return 0;
+}
+
+int do_yumount(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *mtpoint;
+
+ if (argc != 2) {
+ printf("Bad arguments: yumount mount_pt\n");
+ return -1;
+ }
+
+ mtpoint = argv[1];
+ printf("Unmounting yaffs2 mount point %s\n", mtpoint);
+ cmd_yaffs_umount(mtpoint);
+
+ return 0;
+}
+
+int do_yls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *dirname;
+
+ if (argc < 2 || argc > 3 || (argc == 3 && strcmp(argv[1], "-l"))) {
+ printf("Bad arguments: yls [-l] dir\n");
+ return -1;
+ }
+
+ dirname = argv[argc - 1];
+
+ cmd_yaffs_ls(dirname, (argc > 2) ? 1 : 0);
+
+ return 0;
+}
+
+int do_yrd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *filename;
+
+ if (argc != 2) {
+ printf("Bad arguments: yrd file_name\n");
+ return -1;
+ }
+
+ filename = argv[1];
+
+ printf("Reading file %s ", filename);
+
+ cmd_yaffs_read_file(filename);
+
+ printf("done\n");
+ return 0;
+}
+
+int do_ywr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *filename;
+ ulong value;
+ ulong numValues;
+
+ if (argc != 4) {
+ printf("Bad arguments: ywr file_name value n_values\n");
+ return -1;
+ }
+
+ filename = argv[1];
+ value = simple_strtoul(argv[2], NULL, 16);
+ numValues = simple_strtoul(argv[3], NULL, 16);
+
+ printf("Writing value (%lx) %lx times to %s... ", value, numValues,
+ filename);
+
+ cmd_yaffs_write_file(filename, value, numValues);
+
+ printf("done\n");
+ return 0;
+}
+
+int do_yrdm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *filename;
+ ulong addr;
+
+ if (argc != 3) {
+ printf("Bad arguments: yrdm file_name addr\n");
+ return -1;
+ }
+
+ filename = argv[1];
+ addr = simple_strtoul(argv[2], NULL, 16);
+
+ cmd_yaffs_mread_file(filename, (char *)addr);
+
+ return 0;
+}
+
+int do_ywrm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *filename;
+ ulong addr;
+ ulong size;
+
+ if (argc != 4) {
+ printf("Bad arguments: ywrm file_name addr size\n");
+ return -1;
+ }
+
+ filename = argv[1];
+ addr = simple_strtoul(argv[2], NULL, 16);
+ size = simple_strtoul(argv[3], NULL, 16);
+
+ cmd_yaffs_mwrite_file(filename, (char *)addr, size);
+
+ return 0;
+}
+
+int do_ymkdir(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *dirname;
+
+ if (argc != 2) {
+ printf("Bad arguments: ymkdir dir_name\n");
+ return -1;
+ }
+
+ dirname = argv[1];
+ cmd_yaffs_mkdir(dirname);
+
+ return 0;
+}
+
+int do_yrmdir(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *dirname;
+
+ if (argc != 2) {
+ printf("Bad arguments: yrmdir dir_name\n");
+ return -1;
+ }
+
+ dirname = argv[1];
+ cmd_yaffs_rmdir(dirname);
+
+ return 0;
+}
+
+int do_yrm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *name;
+
+ if (argc != 2) {
+ printf("Bad arguments: yrm name\n");
+ return -1;
+ }
+
+ name = argv[1];
+
+ cmd_yaffs_rm(name);
+
+ return 0;
+}
+
+int do_ymv(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *oldPath;
+ char *newPath;
+
+ if (argc != 3) {
+ printf("Bad arguments: ymv old_path new_path\n");
+ return -1;
+ }
+
+ oldPath = argv[1];
+ newPath = argv[2];
+
+ cmd_yaffs_mv(newPath, oldPath);
+
+ return 0;
+}
+
+U_BOOT_CMD(ytrace, 2, 0, do_ytrace,
+ "show/set yaffs trace mask",
+ "[new_mask] show/set yaffs trace mask");
+
+U_BOOT_CMD(ydevls, 1, 0, do_ydevls,
+ "list yaffs mount points", "list yaffs mount points");
+
+U_BOOT_CMD(ydevconfig, 5, 0, do_ydevconfig,
+ "configure yaffs mount point",
+ "mtpoint mtd_id start_block end_block configures a yaffs2 mount point");
+
+U_BOOT_CMD(ymount, 2, 0, do_ymount,
+ "mount yaffs", "mtpoint mounts a yaffs2 mount point");
+
+U_BOOT_CMD(yumount, 2, 0, do_yumount,
+ "unmount yaffs", "mtpoint unmounts a yaffs2 mount point");
+
+U_BOOT_CMD(yls, 3, 0, do_yls, "yaffs ls", "[-l] dirname");
+
+U_BOOT_CMD(yrd, 2, 0, do_yrd,
+ "read file from yaffs", "path read file from yaffs");
+
+U_BOOT_CMD(ywr, 4, 0, do_ywr,
+ "write file to yaffs",
+ "filename value num_vlues write values to yaffs file");
+
+U_BOOT_CMD(yrdm, 3, 0, do_yrdm,
+ "read file to memory from yaffs",
+ "filename offset reads yaffs file into memory");
+
+U_BOOT_CMD(ywrm, 4, 0, do_ywrm,
+ "write file from memory to yaffs",
+ "filename offset size writes memory to yaffs file");
+
+U_BOOT_CMD(ymkdir, 2, 0, do_ymkdir,
+ "YAFFS mkdir", "dir create a yaffs directory");
+
+U_BOOT_CMD(yrmdir, 2, 0, do_yrmdir,
+ "YAFFS rmdir", "dirname removes a yaffs directory");
+
+U_BOOT_CMD(yrm, 2, 0, do_yrm, "YAFFS rm", "path removes a yaffs file");
+
+U_BOOT_CMD(ymv, 4, 0, do_ymv,
+ "YAFFS mv",
+ "old_path new_path moves/rename files within a yaffs mount point");
diff --git a/roms/u-boot/cmd/zfs.c b/roms/u-boot/cmd/zfs.c
new file mode 100644
index 000000000..e429ac88d
--- /dev/null
+++ b/roms/u-boot/cmd/zfs.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *
+ * ZFS filesystem porting to Uboot by
+ * Jorgen Lundman <lundman at lundman.net>
+ *
+ * zfsfs support
+ * made from existing GRUB Sources by Sun, GNU and others.
+ */
+
+#include <common.h>
+#include <part.h>
+#include <config.h>
+#include <command.h>
+#include <env.h>
+#include <image.h>
+#include <linux/ctype.h>
+#include <asm/byteorder.h>
+#include <zfs_common.h>
+#include <linux/stat.h>
+#include <malloc.h>
+
+#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
+#include <usb.h>
+#endif
+
+#if !CONFIG_IS_ENABLED(DOS_PARTITION) && !CONFIG_IS_ENABLED(EFI_PARTITION)
+#error DOS or EFI partition support must be selected
+#endif
+
+#define DOS_PART_MAGIC_OFFSET 0x1fe
+#define DOS_FS_TYPE_OFFSET 0x36
+#define DOS_FS32_TYPE_OFFSET 0x52
+
+static int do_zfs_load(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ char *filename = NULL;
+ int dev;
+ int part;
+ ulong addr = 0;
+ struct disk_partition info;
+ struct blk_desc *dev_desc;
+ unsigned long count;
+ const char *addr_str;
+ struct zfs_file zfile;
+ struct device_s vdev;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ count = 0;
+ addr = simple_strtoul(argv[3], NULL, 16);
+ filename = env_get("bootfile");
+ switch (argc) {
+ case 3:
+ addr_str = env_get("loadaddr");
+ if (addr_str != NULL)
+ addr = simple_strtoul(addr_str, NULL, 16);
+ else
+ addr = CONFIG_SYS_LOAD_ADDR;
+
+ break;
+ case 4:
+ break;
+ case 5:
+ filename = argv[4];
+ break;
+ case 6:
+ filename = argv[4];
+ count = simple_strtoul(argv[5], NULL, 16);
+ break;
+
+ default:
+ return cmd_usage(cmdtp);
+ }
+
+ if (!filename) {
+ puts("** No boot file defined **\n");
+ return 1;
+ }
+
+ part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
+ if (part < 0)
+ return 1;
+
+ dev = dev_desc->devnum;
+ printf("Loading file \"%s\" from %s device %d%c%c\n",
+ filename, argv[1], dev,
+ part ? ':' : ' ', part ? part + '0' : ' ');
+
+ zfs_set_blk_dev(dev_desc, &info);
+ vdev.part_length = info.size;
+
+ memset(&zfile, 0, sizeof(zfile));
+ zfile.device = &vdev;
+ if (zfs_open(&zfile, filename)) {
+ printf("** File not found %s **\n", filename);
+ return 1;
+ }
+
+ if ((count < zfile.size) && (count != 0))
+ zfile.size = (uint64_t)count;
+
+ if (zfs_read(&zfile, (char *)addr, zfile.size) != zfile.size) {
+ printf("** Unable to read \"%s\" from %s %d:%d **\n",
+ filename, argv[1], dev, part);
+ zfs_close(&zfile);
+ return 1;
+ }
+
+ zfs_close(&zfile);
+
+ /* Loading ok, update default load address */
+ image_load_addr = addr;
+
+ printf("%llu bytes read\n", zfile.size);
+ env_set_hex("filesize", zfile.size);
+
+ return 0;
+}
+
+
+int zfs_print(const char *entry, const struct zfs_dirhook_info *data)
+{
+ printf("%s %s\n",
+ data->dir ? "<DIR> " : " ",
+ entry);
+ return 0; /* 0 continue, 1 stop */
+}
+
+
+static int do_zfs_ls(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ const char *filename = "/";
+ int part;
+ struct blk_desc *dev_desc;
+ struct disk_partition info;
+ struct device_s vdev;
+
+ if (argc < 2)
+ return cmd_usage(cmdtp);
+
+ if (argc == 4)
+ filename = argv[3];
+
+ part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
+ if (part < 0)
+ return 1;
+
+ zfs_set_blk_dev(dev_desc, &info);
+ vdev.part_length = info.size;
+
+ zfs_ls(&vdev, filename,
+ zfs_print);
+
+ return 0;
+}
+
+
+U_BOOT_CMD(zfsls, 4, 1, do_zfs_ls,
+ "list files in a directory (default /)",
+ "<interface> <dev[:part]> [directory]\n"
+ " - list files from 'dev' on 'interface' in a '/DATASET/@/$dir/'");
+
+U_BOOT_CMD(zfsload, 6, 0, do_zfs_load,
+ "load binary file from a ZFS filesystem",
+ "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
+ " - load binary file '/DATASET/@/$dir/$file' from 'dev' on 'interface'\n"
+ " to address 'addr' from ZFS filesystem");
diff --git a/roms/u-boot/cmd/zip.c b/roms/u-boot/cmd/zip.c
new file mode 100644
index 000000000..8ad376846
--- /dev/null
+++ b/roms/u-boot/cmd/zip.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2012
+ * Lei Wen <leiwen@marvell.com>, Marvell Inc.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <gzip.h>
+
+static int do_zip(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ unsigned long src, dst;
+ unsigned long src_len, dst_len = ~0UL;
+
+ switch (argc) {
+ case 5:
+ dst_len = simple_strtoul(argv[4], NULL, 16);
+ /* fall through */
+ case 4:
+ src = simple_strtoul(argv[1], NULL, 16);
+ src_len = simple_strtoul(argv[2], NULL, 16);
+ dst = simple_strtoul(argv[3], NULL, 16);
+ break;
+ default:
+ return cmd_usage(cmdtp);
+ }
+
+ if (gzip((void *) dst, &dst_len, (void *) src, src_len) != 0)
+ return 1;
+
+ printf("Compressed size: %lu = 0x%lX\n", dst_len, dst_len);
+ env_set_hex("filesize", dst_len);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ zip, 5, 1, do_zip,
+ "zip a memory region",
+ "srcaddr srcsize dstaddr [dstsize]"
+);