From 2e192b245ed36a63bab0ef576999a95e23f60ecd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 17 Jan 2016 20:53:52 -0700 Subject: Remove the cmd_ prefix from command files Now that they are in their own directory, we can remove this prefix. This makes it easier to find a file since the prefix does not get in the way. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Reviewed-by: Heiko Schocher Acked-by: Stefan Roese Acked-by: Przemyslaw Marczak diff --git a/cmd/Makefile b/cmd/Makefile index 880a886..03f7e0a 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -7,160 +7,160 @@ ifndef CONFIG_SPL_BUILD # core command -obj-y += cmd_boot.o -obj-$(CONFIG_CMD_BOOTM) += cmd_bootm.o -obj-y += cmd_help.o -obj-y += cmd_version.o +obj-y += boot.o +obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-y += help.o +obj-y += version.o # command -obj-$(CONFIG_CMD_AES) += cmd_aes.o -obj-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o -obj-$(CONFIG_CMD_ARMFLASH) += cmd_armflash.o -obj-$(CONFIG_SOURCE) += cmd_source.o -obj-$(CONFIG_CMD_SOURCE) += cmd_source.o -obj-$(CONFIG_CMD_BDI) += cmd_bdinfo.o -obj-$(CONFIG_CMD_BEDBUG) += cmd_bedbug.o -obj-$(CONFIG_CMD_BMP) += cmd_bmp.o -obj-$(CONFIG_CMD_BOOTMENU) += cmd_bootmenu.o -obj-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o -obj-$(CONFIG_CMD_BOOTSTAGE) += cmd_bootstage.o -obj-$(CONFIG_CMD_CACHE) += cmd_cache.o -obj-$(CONFIG_CMD_CBFS) += cmd_cbfs.o -obj-$(CONFIG_CMD_CLK) += cmd_clk.o -obj-$(CONFIG_CMD_CONSOLE) += cmd_console.o -obj-$(CONFIG_CMD_CPLBINFO) += cmd_cplbinfo.o -obj-$(CONFIG_CMD_CPU) += cmd_cpu.o -obj-$(CONFIG_DATAFLASH_MMC_SELECT) += cmd_dataflash_mmc_mux.o -obj-$(CONFIG_CMD_DATE) += cmd_date.o -obj-$(CONFIG_CMD_DEMO) += cmd_demo.o -obj-$(CONFIG_CMD_SOUND) += cmd_sound.o +obj-$(CONFIG_CMD_AES) += aes.o +obj-$(CONFIG_CMD_AMBAPP) += ambapp.o +obj-$(CONFIG_CMD_ARMFLASH) += armflash.o +obj-$(CONFIG_SOURCE) += source.o +obj-$(CONFIG_CMD_SOURCE) += source.o +obj-$(CONFIG_CMD_BDI) += bdinfo.o +obj-$(CONFIG_CMD_BEDBUG) += bedbug.o +obj-$(CONFIG_CMD_BMP) += bmp.o +obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o +obj-$(CONFIG_CMD_BOOTLDR) += bootldr.o +obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o +obj-$(CONFIG_CMD_CACHE) += cache.o +obj-$(CONFIG_CMD_CBFS) += cbfs.o +obj-$(CONFIG_CMD_CLK) += clk.o +obj-$(CONFIG_CMD_CONSOLE) += console.o +obj-$(CONFIG_CMD_CPLBINFO) += cplbinfo.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_SOUND) += sound.o ifdef CONFIG_4xx -obj-$(CONFIG_CMD_SETGETDCR) += cmd_dcr.o +obj-$(CONFIG_CMD_SETGETDCR) += dcr.o endif ifdef CONFIG_POST -obj-$(CONFIG_CMD_DIAG) += cmd_diag.o +obj-$(CONFIG_CMD_DIAG) += diag.o endif -obj-$(CONFIG_CMD_DISPLAY) += cmd_display.o -obj-$(CONFIG_CMD_DTT) += cmd_dtt.o -obj-$(CONFIG_CMD_ECHO) += cmd_echo.o -obj-$(CONFIG_ENV_IS_IN_EEPROM) += cmd_eeprom.o -obj-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o -obj-$(CONFIG_EFI_STUB) += cmd_efi.o -obj-$(CONFIG_CMD_ELF) += cmd_elf.o -obj-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o -obj-$(CONFIG_CMD_EXT4) += cmd_ext4.o -obj-$(CONFIG_CMD_EXT2) += cmd_ext2.o -obj-$(CONFIG_CMD_FAT) += cmd_fat.o -obj-$(CONFIG_CMD_FDC) += cmd_fdc.o -obj-$(CONFIG_OF_LIBFDT) += cmd_fdt.o -obj-$(CONFIG_CMD_FITUPD) += cmd_fitupd.o -obj-$(CONFIG_CMD_FLASH) += cmd_flash.o +obj-$(CONFIG_CMD_DISPLAY) += display.o +obj-$(CONFIG_CMD_DTT) += dtt.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_ELF) += elf.o +obj-$(CONFIG_SYS_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_FDC) += fdc.o +obj-$(CONFIG_OF_LIBFDT) += fdt.o +obj-$(CONFIG_CMD_FITUPD) += fitupd.o +obj-$(CONFIG_CMD_FLASH) += flash.o ifdef CONFIG_FPGA -obj-$(CONFIG_CMD_FPGA) += cmd_fpga.o +obj-$(CONFIG_CMD_FPGA) += fpga.o endif -obj-$(CONFIG_CMD_FPGAD) += cmd_fpgad.o -obj-$(CONFIG_CMD_FS_GENERIC) += cmd_fs.o -obj-$(CONFIG_CMD_FUSE) += cmd_fuse.o -obj-$(CONFIG_CMD_GETTIME) += cmd_gettime.o -obj-$(CONFIG_CMD_GPIO) += cmd_gpio.o -obj-$(CONFIG_CMD_I2C) += cmd_i2c.o -obj-$(CONFIG_CMD_IOTRACE) += cmd_iotrace.o -obj-$(CONFIG_CMD_HASH) += cmd_hash.o -obj-$(CONFIG_CMD_IDE) += cmd_ide.o -obj-$(CONFIG_CMD_IMMAP) += cmd_immap.o -obj-$(CONFIG_CMD_INI) += cmd_ini.o -obj-$(CONFIG_CMD_IRQ) += cmd_irq.o -obj-$(CONFIG_CMD_ITEST) += cmd_itest.o -obj-$(CONFIG_CMD_JFFS2) += cmd_jffs2.o -obj-$(CONFIG_CMD_CRAMFS) += cmd_cramfs.o -obj-$(CONFIG_CMD_LDRINFO) += cmd_ldrinfo.o -obj-$(CONFIG_CMD_LED) += cmd_led.o -obj-$(CONFIG_CMD_LICENSE) += cmd_license.o -obj-y += cmd_load.o -obj-$(CONFIG_LOGBUFFER) += cmd_log.o -obj-$(CONFIG_ID_EEPROM) += cmd_mac.o -obj-$(CONFIG_CMD_MD5SUM) += cmd_md5sum.o -obj-$(CONFIG_CMD_MEMORY) += cmd_mem.o -obj-$(CONFIG_CMD_IO) += cmd_io.o -obj-$(CONFIG_CMD_MFSL) += cmd_mfsl.o -obj-$(CONFIG_CMD_MII) += cmd_mii.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_I2C) += i2c.o +obj-$(CONFIG_CMD_IOTRACE) += iotrace.o +obj-$(CONFIG_CMD_HASH) += hash.o +obj-$(CONFIG_CMD_IDE) += ide.o +obj-$(CONFIG_CMD_IMMAP) += immap.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_CMD_LDRINFO) += ldrinfo.o +obj-$(CONFIG_CMD_LED) += led.o +obj-$(CONFIG_CMD_LICENSE) += license.o +obj-y += load.o +obj-$(CONFIG_LOGBUFFER) += log.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 ifdef CONFIG_PHYLIB -obj-$(CONFIG_CMD_MII) += cmd_mdio.o +obj-$(CONFIG_CMD_MII) += mdio.o endif -obj-$(CONFIG_CMD_MISC) += cmd_misc.o -obj-$(CONFIG_CMD_MMC) += cmd_mmc.o -obj-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o -obj-$(CONFIG_MP) += cmd_mp.o -obj-$(CONFIG_CMD_MTDPARTS) += cmd_mtdparts.o -obj-$(CONFIG_CMD_NAND) += cmd_nand.o -obj-$(CONFIG_CMD_NET) += cmd_net.o -obj-$(CONFIG_CMD_ONENAND) += cmd_onenand.o -obj-$(CONFIG_CMD_OTP) += cmd_otp.o -obj-$(CONFIG_CMD_PART) += cmd_part.o +obj-$(CONFIG_CMD_MISC) += misc.o +obj-$(CONFIG_CMD_MMC) += mmc.o +obj-$(CONFIG_CMD_MMC_SPI) += mmc_spi.o +obj-$(CONFIG_MP) += mp.o +obj-$(CONFIG_CMD_MTDPARTS) += mtdparts.o +obj-$(CONFIG_CMD_NAND) += nand.o +obj-$(CONFIG_CMD_NET) += net.o +obj-$(CONFIG_CMD_ONENAND) += onenand.o +obj-$(CONFIG_CMD_OTP) += otp.o +obj-$(CONFIG_CMD_PART) += part.o ifdef CONFIG_PCI -obj-$(CONFIG_CMD_PCI) += cmd_pci.o +obj-$(CONFIG_CMD_PCI) += pci.o endif -obj-y += cmd_pcmcia.o -obj-$(CONFIG_CMD_PORTIO) += cmd_portio.o -obj-$(CONFIG_CMD_PXE) += cmd_pxe.o -obj-$(CONFIG_CMD_READ) += cmd_read.o -obj-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o -obj-$(CONFIG_CMD_REISER) += cmd_reiser.o -obj-$(CONFIG_CMD_REMOTEPROC) += cmd_remoteproc.o -obj-$(CONFIG_SANDBOX) += cmd_host.o -obj-$(CONFIG_CMD_SATA) += cmd_sata.o -obj-$(CONFIG_CMD_SF) += cmd_sf.o -obj-$(CONFIG_CMD_SCSI) += cmd_scsi.o -obj-$(CONFIG_CMD_SHA1SUM) += cmd_sha1sum.o -obj-$(CONFIG_CMD_SETEXPR) += cmd_setexpr.o -obj-$(CONFIG_CMD_SOFTSWITCH) += cmd_softswitch.o -obj-$(CONFIG_CMD_SPI) += cmd_spi.o -obj-$(CONFIG_CMD_SPIBOOTLDR) += cmd_spibootldr.o -obj-$(CONFIG_CMD_STRINGS) += cmd_strings.o -obj-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o -obj-$(CONFIG_CMD_TIME) += cmd_time.o -obj-$(CONFIG_CMD_TRACE) += cmd_trace.o -obj-$(CONFIG_SYS_HUSH_PARSER) += cmd_test.o -obj-$(CONFIG_CMD_TPM) += cmd_tpm.o -obj-$(CONFIG_CMD_TPM_TEST) += cmd_tpm_test.o -obj-$(CONFIG_CMD_TSI148) += cmd_tsi148.o -obj-$(CONFIG_CMD_UBI) += cmd_ubi.o -obj-$(CONFIG_CMD_UBIFS) += cmd_ubifs.o -obj-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o -obj-$(CONFIG_CMD_UNZIP) += cmd_unzip.o +obj-y += pcmcia.o +obj-$(CONFIG_CMD_PORTIO) += portio.o +obj-$(CONFIG_CMD_PXE) += pxe.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_SANDBOX) += host.o +obj-$(CONFIG_CMD_SATA) += sata.o +obj-$(CONFIG_CMD_SF) += sf.o +obj-$(CONFIG_CMD_SCSI) += scsi.o +obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o +obj-$(CONFIG_CMD_SETEXPR) += setexpr.o +obj-$(CONFIG_CMD_SOFTSWITCH) += softswitch.o +obj-$(CONFIG_CMD_SPI) += spi.o +obj-$(CONFIG_CMD_SPIBOOTLDR) += spibootldr.o +obj-$(CONFIG_CMD_STRINGS) += strings.o +obj-$(CONFIG_CMD_TERMINAL) += terminal.o +obj-$(CONFIG_CMD_TIME) += time.o +obj-$(CONFIG_CMD_TRACE) += trace.o +obj-$(CONFIG_SYS_HUSH_PARSER) += test.o +obj-$(CONFIG_CMD_TPM) += tpm.o +obj-$(CONFIG_CMD_TPM_TEST) += tpm_test.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_UNZIP) += unzip.o ifdef CONFIG_LZMA -obj-$(CONFIG_CMD_LZMADEC) += cmd_lzmadec.o +obj-$(CONFIG_CMD_LZMADEC) += lzmadec.o endif -obj-$(CONFIG_CMD_USB) += cmd_usb.o -obj-$(CONFIG_CMD_FASTBOOT) += cmd_fastboot.o -obj-$(CONFIG_CMD_FS_UUID) += cmd_fs_uuid.o +obj-$(CONFIG_CMD_USB) += usb.o +obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o +obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o -obj-$(CONFIG_CMD_USB_MASS_STORAGE) += cmd_usb_mass_storage.o -obj-$(CONFIG_CMD_THOR_DOWNLOAD) += cmd_thordown.o -obj-$(CONFIG_CMD_XIMG) += cmd_ximg.o -obj-$(CONFIG_YAFFS2) += cmd_yaffs2.o -obj-$(CONFIG_CMD_SPL) += cmd_spl.o -obj-$(CONFIG_CMD_ZIP) += cmd_zip.o -obj-$(CONFIG_CMD_ZFS) += cmd_zfs.o +obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o +obj-$(CONFIG_CMD_THOR_DOWNLOAD) += thordown.o +obj-$(CONFIG_CMD_XIMG) += ximg.o +obj-$(CONFIG_YAFFS2) += yaffs2.o +obj-$(CONFIG_CMD_SPL) += spl.o +obj-$(CONFIG_CMD_ZIP) += zip.o +obj-$(CONFIG_CMD_ZFS) += zfs.o -obj-$(CONFIG_CMD_DFU) += cmd_dfu.o -obj-$(CONFIG_CMD_GPT) += cmd_gpt.o -obj-$(CONFIG_CMD_ETHSW) += cmd_ethsw.o +obj-$(CONFIG_CMD_DFU) += dfu.o +obj-$(CONFIG_CMD_GPT) += gpt.o +obj-$(CONFIG_CMD_ETHSW) += ethsw.o # Power -obj-$(CONFIG_CMD_PMIC) += cmd_pmic.o -obj-$(CONFIG_CMD_REGULATOR) += cmd_regulator.o +obj-$(CONFIG_CMD_PMIC) += pmic.o +obj-$(CONFIG_CMD_REGULATOR) += regulator.o endif # !CONFIG_SPL_BUILD ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_SATA_SUPPORT -obj-$(CONFIG_CMD_SCSI) += cmd_scsi.o +obj-$(CONFIG_CMD_SCSI) += scsi.o endif endif # CONFIG_SPL_BUILD -obj-$(CONFIG_CMD_BLOB) += cmd_blob.o +obj-$(CONFIG_CMD_BLOB) += blob.o # core command -obj-y += cmd_nvedit.o -obj-y += cmd_disk.o +obj-y += nvedit.o +obj-y += disk.o diff --git a/cmd/aes.c b/cmd/aes.c new file mode 100644 index 0000000..76da3ef --- /dev/null +++ b/cmd/aes.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2014 Marek Vasut + * + * Command for en/de-crypting block of memory with AES-128-CBC cipher. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/** + * 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(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + uint32_t key_addr, src_addr, dst_addr, len; + uint8_t *key_ptr, *src_ptr, *dst_ptr; + uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; + uint32_t aes_blocks; + int enc; + + 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; + + key_addr = simple_strtoul(argv[2], NULL, 16); + src_addr = simple_strtoul(argv[3], NULL, 16); + dst_addr = simple_strtoul(argv[4], NULL, 16); + len = simple_strtoul(argv[5], NULL, 16); + + key_ptr = (uint8_t *)key_addr; + src_ptr = (uint8_t *)src_addr; + dst_ptr = (uint8_t *)dst_addr; + + /* First we expand the key. */ + aes_expand_key(key_ptr, key_exp); + + /* Calculate the number of AES blocks to encrypt. */ + aes_blocks = DIV_ROUND_UP(len, AES_KEY_LENGTH); + + if (enc) + aes_cbc_encrypt_blocks(key_exp, src_ptr, dst_ptr, aes_blocks); + else + aes_cbc_decrypt_blocks(key_exp, src_ptr, dst_ptr, aes_blocks); + + return 0; +} + +/***************************************************/ +#ifdef CONFIG_SYS_LONGHELP +static char aes_help_text[] = + "enc key src dst len - Encrypt block of data $len bytes long\n" + " at address $src using a key at address\n" + " $key and store the result at address\n" + " $dst. The $len size must be multiple of\n" + " 16 bytes and $key must be 16 bytes long.\n" + "aes dec key src dst len - Decrypt block of data $len bytes long\n" + " at address $src using a key at address\n" + " $key and store the result at address\n" + " $dst. The $len size must be multiple of\n" + " 16 bytes and $key must be 16 bytes long."; +#endif + +U_BOOT_CMD( + aes, 6, 1, do_aes, + "AES 128 CBC encryption", + aes_help_text +); diff --git a/cmd/ambapp.c b/cmd/ambapp.c new file mode 100644 index 0000000..4b6d174 --- /dev/null +++ b/cmd/ambapp.c @@ -0,0 +1,575 @@ +/* + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * AMBA Plug&Play information list command + * + */ +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +typedef struct { + int device_id; + char *name; + char *desc; +} ambapp_device_name; + +typedef struct { + unsigned int vendor_id; + char *name; + char *desc; + ambapp_device_name *devices; +} ambapp_vendor_devnames; + +/** Vendor GAISLER devices */ +static ambapp_device_name GAISLER_devices[] = { + {GAISLER_LEON2DSU, "LEON2DSU", "Leon2 Debug Support Unit"}, + {GAISLER_LEON3, "LEON3", "Leon3 SPARC V8 Processor"}, + {GAISLER_LEON3DSU, "LEON3DSU", "Leon3 Debug Support Unit"}, + {GAISLER_ETHAHB, "ETHAHB", "OC ethernet AHB interface"}, + {GAISLER_APBMST, "APBMST", "AHB/APB Bridge"}, + {GAISLER_AHBUART, "AHBUART", "AHB Debug UART"}, + {GAISLER_SRCTRL, "SRCTRL", "Simple SRAM Controller"}, + {GAISLER_SDCTRL, "SDCTRL", "PC133 SDRAM Controller"}, + {GAISLER_SSRCTRL, "SSRCTRL", "Synchronous SRAM Controller"}, + {GAISLER_APBUART, "APBUART", "Generic UART"}, + {GAISLER_IRQMP, "IRQMP", "Multi-processor Interrupt Ctrl."}, + {GAISLER_AHBRAM, "AHBRAM", "Single-port AHB SRAM module"}, + {GAISLER_AHBDPRAM, "AHBDPRAM", "Dual-port AHB SRAM module"}, + {GAISLER_GPTIMER, "GPTIMER", "Modular Timer Unit"}, + {GAISLER_PCITRG, "PCITRG", "Simple 32-bit PCI Target"}, + {GAISLER_PCISBRG, "PCISBRG", "Simple 32-bit PCI Bridge"}, + {GAISLER_PCIFBRG, "PCIFBRG", "Fast 32-bit PCI Bridge"}, + {GAISLER_PCITRACE, "PCITRACE", "32-bit PCI Trace Buffer"}, + {GAISLER_DMACTRL, "DMACTRL", "AMBA DMA controller"}, + {GAISLER_AHBTRACE, "AHBTRACE", "AMBA Trace Buffer"}, + {GAISLER_DSUCTRL, "DSUCTRL", "DSU/ETH controller"}, + {GAISLER_CANAHB, "CANAHB", "OC CAN AHB interface"}, + {GAISLER_GPIO, "GPIO", "General Purpose I/O port"}, + {GAISLER_AHBROM, "AHBROM", "Generic AHB ROM"}, + {GAISLER_AHBJTAG, "AHBJTAG", "JTAG Debug Link"}, + {GAISLER_ETHMAC, "ETHMAC", "GR Ethernet MAC"}, + {GAISLER_SWNODE, "SWNODE", "SpaceWire Node Interface"}, + {GAISLER_SPW, "SPW", "SpaceWire Serial Link"}, + {GAISLER_AHB2AHB, "AHB2AHB", "AHB-to-AHB Bridge"}, + {GAISLER_USBDC, "USBDC", "GR USB 2.0 Device Controller"}, + {GAISLER_USB_DCL, "USB_DCL", "USB Debug Communication Link"}, + {GAISLER_DDRMP, "DDRMP", "Multi-port DDR controller"}, + {GAISLER_ATACTRL, "ATACTRL", "ATA controller"}, + {GAISLER_DDRSP, "DDRSP", "Single-port DDR266 controller"}, + {GAISLER_EHCI, "EHCI", "USB Enhanced Host Controller"}, + {GAISLER_UHCI, "UHCI", "USB Universal Host Controller"}, + {GAISLER_I2CMST, "I2CMST", "AMBA Wrapper for OC I2C-master"}, + {GAISLER_SPW2, "SPW2", "GRSPW2 SpaceWire Serial Link"}, + {GAISLER_AHBDMA, "AHBDMA", ""}, + {GAISLER_NUHOSP3, "NUHOSP3", "Nuhorizons Spartan3 IO I/F"}, + {GAISLER_CLKGATE, "CLKGATE", "Clock gating unit"}, + {GAISLER_SPICTRL, "SPICTRL", "SPI Controller"}, + {GAISLER_DDR2SP, "DDR2SP", "Single-port DDR2 controller"}, + {GAISLER_SLINK, "SLINK", "SLINK Master"}, + {GAISLER_GRTM, "GRTM", "CCSDS Telemetry Encoder"}, + {GAISLER_GRTC, "GRTC", "CCSDS Telecommand Decoder"}, + {GAISLER_GRPW, "GRPW", "PacketWire to AMBA AHB I/F"}, + {GAISLER_GRCTM, "GRCTM", "CCSDS Time Manager"}, + {GAISLER_GRHCAN, "GRHCAN", "ESA HurriCANe CAN with DMA"}, + {GAISLER_GRFIFO, "GRFIFO", "FIFO Controller"}, + {GAISLER_GRADCDAC, "GRADCDAC", "ADC / DAC Interface"}, + {GAISLER_GRPULSE, "GRPULSE", "General Purpose I/O with Pulses"}, + {GAISLER_GRTIMER, "GRTIMER", "Timer Unit with Latches"}, + {GAISLER_AHB2PP, "AHB2PP", "AMBA AHB to Packet Parallel I/F"}, + {GAISLER_GRVERSION, "GRVERSION", "Version and Revision Register"}, + {GAISLER_APB2PW, "APB2PW", "PacketWire Transmit Interface"}, + {GAISLER_PW2APB, "PW2APB", "PacketWire Receive Interface"}, + {GAISLER_GRCAN, "GRCAN", "CAN Controller with DMA"}, + {GAISLER_I2CSLV, "I2CSLV", "I2C Slave"}, + {GAISLER_U16550, "U16550", "Simple 16550 UART"}, + {GAISLER_AHBMST_EM, "AHBMST_EM", "AMBA Master Emulator"}, + {GAISLER_AHBSLV_EM, "AHBSLV_EM", "AMBA Slave Emulator"}, + {GAISLER_GRTESTMOD, "GRTESTMOD", "Test report module"}, + {GAISLER_ASCS, "ASCS", "ASCS Master"}, + {GAISLER_IPMVBCTRL, "IPMVBCTRL", "IPM-bus/MVBC memory controller"}, + {GAISLER_SPIMCTRL, "SPIMCTRL", "SPI Memory Controller"}, + {GAISLER_L4STAT, "L4STAT", "Leon4 Statistics Module"}, + {GAISLER_LEON4, "LEON4", "Leon4 SPARC V8 Processor"}, + {GAISLER_LEON4DSU, "LEON4DSU", "Leon4 Debug Support Unit"}, + {GAISLER_PWM, "PWM", "PWM generator"}, + {GAISLER_L2CACHE, "L2CACHE", "L2-Cache Controller"}, + {GAISLER_SDCTRL64, "SDCTRL64", "64-bit PC133 SDRAM Controller"}, + {GAISLER_GR1553B, "GR1553B", "MIL-STD-1553B Interface"}, + {GAISLER_1553TST, "1553TST", "MIL-STD-1553B Test Device"}, + {GAISLER_GRIOMMU, "GRIOMMU", "I/O Memory Management Unit"}, + {GAISLER_FTAHBRAM, "FTAHBRAM", "Generic FT AHB SRAM module"}, + {GAISLER_FTSRCTRL, "FTSRCTRL", "Simple FT SRAM Controller"}, + {GAISLER_AHBSTAT, "AHBSTAT", "AHB Status Register"}, + {GAISLER_LEON3FT, "LEON3FT", "Leon3-FT SPARC V8 Processor"}, + {GAISLER_FTMCTRL, "FTMCTRL", "Memory controller with EDAC"}, + {GAISLER_FTSDCTRL, "FTSDCTRL", "FT PC133 SDRAM Controller"}, + {GAISLER_FTSRCTRL8, "FTSRCTRL8", "FT 8-bit SRAM/16-bit IO Ctrl"}, + {GAISLER_MEMSCRUB, "MEMSCRUB", "AHB Memory Scrubber"}, + {GAISLER_FTSDCTRL64, "FTSDCTRL64", "64-bit FT SDRAM Controller"}, + {GAISLER_APBPS2, "APBPS2", "PS2 interface"}, + {GAISLER_VGACTRL, "VGACTRL", "VGA controller"}, + {GAISLER_LOGAN, "LOGAN", "On chip Logic Analyzer"}, + {GAISLER_SVGACTRL, "SVGACTRL", "SVGA frame buffer"}, + {GAISLER_T1AHB, "T1AHB", "Niagara T1 PCX/AHB bridge"}, + {GAISLER_MP7WRAP, "MP7WRAP", "CoreMP7 wrapper"}, + {GAISLER_GRSYSMON, "GRSYSMON", "AMBA wrapper for System Monitor"}, + {GAISLER_GRACECTRL, "GRACECTRL", "System ACE I/F Controller"}, + {GAISLER_ATAHBSLV, "ATAHBSLV", "AMBA Test Framework AHB Slave"}, + {GAISLER_ATAHBMST, "ATAHBMST", "AMBA Test Framework AHB Master"}, + {GAISLER_ATAPBSLV, "ATAPBSLV", "AMBA Test Framework APB Slave"}, + {GAISLER_B1553BC, "B1553BC", "AMBA Wrapper for Core1553BBC"}, + {GAISLER_B1553RT, "B1553RT", "AMBA Wrapper for Core1553BRT"}, + {GAISLER_B1553BRM, "B1553BRM", "AMBA Wrapper for Core1553BRM"}, + {GAISLER_AES, "AES", "Advanced Encryption Standard"}, + {GAISLER_ECC, "ECC", "Elliptic Curve Cryptography"}, + {GAISLER_PCIF, "PCIF", "AMBA Wrapper for CorePCIF"}, + {GAISLER_CLKMOD, "CLKMOD", "CPU Clock Switching Ctrl module"}, + {GAISLER_HAPSTRAK, "HAPSTRAK", "HAPS HapsTrak I/O Port"}, + {GAISLER_TEST_1X2, "TEST_1X2", "HAPS TEST_1x2 interface"}, + {GAISLER_WILD2AHB, "WILD2AHB", "WildCard CardBus interface"}, + {GAISLER_BIO1, "BIO1", "Basic I/O board BIO1"}, + {GAISLER_AESDMA, "AESDMA", "AES 256 DMA"}, + {GAISLER_SATCAN, "SATCAN", "SatCAN controller"}, + {GAISLER_CANMUX, "CANMUX", "CAN Bus multiplexer"}, + {GAISLER_GRTMRX, "GRTMRX", "CCSDS Telemetry Receiver"}, + {GAISLER_GRTCTX, "GRTCTX", "CCSDS Telecommand Transmitter"}, + {GAISLER_GRTMDESC, "GRTMDESC", "CCSDS Telemetry Descriptor"}, + {GAISLER_GRTMVC, "GRTMVC", "CCSDS Telemetry VC Generator"}, + {GAISLER_GEFFE, "GEFFE", "Geffe Generator"}, + {GAISLER_GPREG, "GPREG", "General Purpose Register"}, + {GAISLER_GRTMPAHB, "GRTMPAHB", "CCSDS Telemetry VC AHB Input"}, + {GAISLER_SPWCUC, "SPWCUC", "CCSDS CUC / SpaceWire I/F"}, + {GAISLER_SPW2_DMA, "SPW2_DMA", "GRSPW Router DMA interface"}, + {GAISLER_SPWROUTER, "SPWROUTER", "GRSPW Router"}, + {0, NULL, NULL} +}; + + +/** Vendor PENDER devices */ +static ambapp_device_name PENDER_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor ESA devices */ +static ambapp_device_name ESA_devices[] = { + {ESA_LEON2, "LEON2", "Leon2 SPARC V8 Processor"}, + {ESA_LEON2APB, "LEON2APB", "Leon2 Peripheral Bus"}, + {ESA_IRQ, "IRQ", "Leon2 Interrupt Controller"}, + {ESA_TIMER, "TIMER", "Leon2 Timer"}, + {ESA_UART, "UART", "Leon2 UART"}, + {ESA_CFG, "CFG", "Leon2 Configuration Register"}, + {ESA_IO, "IO", "Leon2 Input/Output"}, + {ESA_MCTRL, "MCTRL", "Leon2 Memory Controller"}, + {ESA_PCIARB, "PCIARB", "PCI Arbiter"}, + {ESA_HURRICANE, "HURRICANE", "HurriCANe/HurryAMBA CAN Ctrl"}, + {ESA_SPW_RMAP, "SPW_RMAP", "UoD/Saab SpaceWire/RMAP link"}, + {ESA_AHBUART, "AHBUART", "Leon2 AHB Debug UART"}, + {ESA_SPWA, "SPWA", "ESA/ASTRIUM SpaceWire link"}, + {ESA_BOSCHCAN, "BOSCHCAN", "SSC/BOSCH CAN Ctrl"}, + {ESA_IRQ2, "IRQ2", "Leon2 Secondary Irq Controller"}, + {ESA_AHBSTAT, "AHBSTAT", "Leon2 AHB Status Register"}, + {ESA_WPROT, "WPROT", "Leon2 Write Protection"}, + {ESA_WPROT2, "WPROT2", "Leon2 Extended Write Protection"}, + {ESA_PDEC3AMBA, "PDEC3AMBA", "ESA CCSDS PDEC3AMBA TC Decoder"}, + {ESA_PTME3AMBA, "PTME3AMBA", "ESA CCSDS PTME3AMBA TM Encoder"}, + {0, NULL, NULL} +}; + + +/** Vendor ASTRIUM devices */ +static ambapp_device_name ASTRIUM_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor OPENCHIP devices */ +static ambapp_device_name OPENCHIP_devices[] = { + {OPENCHIP_APBGPIO, "APBGPIO", "APB General Purpose IO"}, + {OPENCHIP_APBI2C, "APBI2C", "APB I2C Interface"}, + {OPENCHIP_APBSPI, "APBSPI", "APB SPI Interface"}, + {OPENCHIP_APBCHARLCD, "APBCHARLCD", "APB Character LCD"}, + {OPENCHIP_APBPWM, "APBPWM", "APB PWM"}, + {OPENCHIP_APBPS2, "APBPS2", "APB PS/2 Interface"}, + {OPENCHIP_APBMMCSD, "APBMMCSD", "APB MMC/SD Card Interface"}, + {OPENCHIP_APBNAND, "APBNAND", "APB NAND(SmartMedia) Interface"}, + {OPENCHIP_APBLPC, "APBLPC", "APB LPC Interface"}, + {OPENCHIP_APBCF, "APBCF", "APB CompactFlash (IDE)"}, + {OPENCHIP_APBSYSACE, "APBSYSACE", "APB SystemACE Interface"}, + {OPENCHIP_APB1WIRE, "APB1WIRE", "APB 1-Wire Interface"}, + {OPENCHIP_APBJTAG, "APBJTAG", "APB JTAG TAP Master"}, + {OPENCHIP_APBSUI, "APBSUI", "APB Simple User Interface"}, + {0, NULL, NULL} +}; + + +/** Vendor OPENCORES devices */ +static ambapp_device_name OPENCORES_devices[] = { + {OPENCORES_PCIBR, "PCIBR", "PCI Bridge"}, + {OPENCORES_ETHMAC, "ETHMAC", "Ethernet MAC"}, + {0, NULL} +}; + + +/** Vendor CONTRIB devices */ +static ambapp_device_name CONTRIB_devices[] = { + {CONTRIB_CORE1, "CORE1", "Contributed core 1"}, + {CONTRIB_CORE2, "CORE2", "Contributed core 2"}, + {0, NULL, NULL} +}; + + +/** Vendor EONIC devices */ +static ambapp_device_name EONIC_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor RADIONOR devices */ +static ambapp_device_name RADIONOR_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor GLEICHMANN devices */ +static ambapp_device_name GLEICHMANN_devices[] = { + {GLEICHMANN_CUSTOM, "CUSTOM", "Custom device"}, + {GLEICHMANN_GEOLCD01, "GEOLCD01", "GEOLCD01 graphics system"}, + {GLEICHMANN_DAC, "DAC", "Sigma delta DAC"}, + {GLEICHMANN_HPI, "HPI", "AHB-to-HPI bridge"}, + {GLEICHMANN_SPI, "SPI", "SPI master"}, + {GLEICHMANN_HIFC, "HIFC", "Human interface controller"}, + {GLEICHMANN_ADCDAC, "ADCDAC", "Sigma delta ADC/DAC"}, + {GLEICHMANN_SPIOC, "SPIOC", ""}, + {GLEICHMANN_AC97, "AC97", ""}, + {0, NULL, NULL} +}; + + +/** Vendor MENTA devices */ +static ambapp_device_name MENTA_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor SUN devices */ +static ambapp_device_name SUN_devices[] = { + {SUN_T1, "T1", "Niagara T1 SPARC V9 Processor"}, + {SUN_S1, "S1", "Niagara S1 SPARC V9 Processor"}, + {0, NULL, NULL} +}; + + +/** Vendor MOVIDIA devices */ +static ambapp_device_name MOVIDIA_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor ORBITA devices */ +static ambapp_device_name ORBITA_devices[] = { + {ORBITA_1553B, "1553B", "MIL-STD-1553B Controller"}, + {ORBITA_429, "429", "429 Interface"}, + {ORBITA_SPI, "SPI", "SPI Interface"}, + {ORBITA_I2C, "I2C", "I2C Interface"}, + {ORBITA_SMARTCARD, "SMARTCARD", "Smart Card Reader"}, + {ORBITA_SDCARD, "SDCARD", "SD Card Reader"}, + {ORBITA_UART16550, "UART16550", "16550 UART"}, + {ORBITA_CRYPTO, "CRYPTO", "Crypto Engine"}, + {ORBITA_SYSIF, "SYSIF", "System Interface"}, + {ORBITA_PIO, "PIO", "Programmable IO module"}, + {ORBITA_RTC, "RTC", "Real-Time Clock"}, + {ORBITA_COLORLCD, "COLORLCD", "Color LCD Controller"}, + {ORBITA_PCI, "PCI", "PCI Module"}, + {ORBITA_DSP, "DSP", "DPS Co-Processor"}, + {ORBITA_USBHOST, "USBHOST", "USB Host"}, + {ORBITA_USBDEV, "USBDEV", "USB Device"}, + {0, NULL, NULL} +}; + + +/** Vendor SYNOPSYS devices */ +static ambapp_device_name SYNOPSYS_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor NASA devices */ +static ambapp_device_name NASA_devices[] = { + {NASA_EP32, "EP32", "EP32 Forth processor"}, + {0, NULL, NULL} +}; + + +/** Vendor CAL devices */ +static ambapp_device_name CAL_devices[] = { + {CAL_DDRCTRL, "DDRCTRL", ""}, + {0, NULL, NULL} +}; + + +/** Vendor EMBEDDIT devices */ +static ambapp_device_name EMBEDDIT_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor CETON devices */ +static ambapp_device_name CETON_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor S3 devices */ +static ambapp_device_name S3_devices[] = { + {0, NULL, NULL} +}; + + +/** Vendor ACTEL devices */ +static ambapp_device_name ACTEL_devices[] = { + {ACTEL_COREMP7, "COREMP7", "CoreMP7 Processor"}, + {0, NULL, NULL} +}; + + +/** Vendor APPLECORE devices */ +static ambapp_device_name APPLECORE_devices[] = { + {APPLECORE_UTLEON3, "UTLEON3", "AppleCore uT-LEON3 Processor"}, + {APPLECORE_UTLEON3DSU, "UTLEON3DSU", "AppleCore uT-LEON3 DSU"}, + {0, NULL, NULL} +}; + + +/** Vendors and their devices */ +static ambapp_vendor_devnames vendors[] = { + {VENDOR_GAISLER, "GAISLER", "Gaisler Research", GAISLER_devices}, + {VENDOR_PENDER, "PENDER", "", PENDER_devices}, + {VENDOR_ESA, "ESA", "European Space Agency", ESA_devices}, + {VENDOR_ASTRIUM, "ASTRIUM", "", ASTRIUM_devices}, + {VENDOR_OPENCHIP, "OPENCHIP", "OpenChip", OPENCHIP_devices}, + {VENDOR_OPENCORES, "OPENCORES", "OpenCores", OPENCORES_devices}, + {VENDOR_CONTRIB, "CONTRIB", "Various contributions", CONTRIB_devices}, + {VENDOR_EONIC, "EONIC", "Eonic BV", EONIC_devices}, + {VENDOR_RADIONOR, "RADIONOR", "Radionor Communications", RADIONOR_devices}, + {VENDOR_GLEICHMANN, "GLEICHMANN", "Gleichmann Electronics", GLEICHMANN_devices}, + {VENDOR_MENTA, "MENTA", "Menta", MENTA_devices}, + {VENDOR_SUN, "SUN", "Sun Microsystems", SUN_devices}, + {VENDOR_MOVIDIA, "MOVIDIA", "", MOVIDIA_devices}, + {VENDOR_ORBITA, "ORBITA", "Orbita", ORBITA_devices}, + {VENDOR_SYNOPSYS, "SYNOPSYS", "Synopsys Inc.", SYNOPSYS_devices}, + {VENDOR_NASA, "NASA", "NASA", NASA_devices}, + {VENDOR_S3, "S3", "S3 Group", S3_devices}, + {VENDOR_CAL, "CAL", "", CAL_devices}, + {VENDOR_EMBEDDIT, "EMBEDDIT", "Embedd.it", EMBEDDIT_devices}, + {VENDOR_CETON, "CETON", "Ceton Corporation", CETON_devices}, + {VENDOR_ACTEL, "ACTEL", "Actel Corporation", ACTEL_devices}, + {VENDOR_APPLECORE, "APPLECORE", "AppleCore", APPLECORE_devices}, + {0, NULL, NULL, NULL} +}; + +static ambapp_device_name *ambapp_get_dev(ambapp_device_name *devs, int id) +{ + if (!devs) + return NULL; + + while (devs->device_id > 0) { + if (devs->device_id == id) + return devs; + devs++; + } + return NULL; +} + +char *ambapp_device_id2str(int vendor, int id) +{ + ambapp_vendor_devnames *ven = &vendors[0]; + ambapp_device_name *dev; + + while (ven->vendor_id > 0) { + if (ven->vendor_id == vendor) { + dev = ambapp_get_dev(ven->devices, id); + if (!dev) + return NULL; + return dev->name; + } + ven++; + } + return NULL; +} + +char *ambapp_device_id2desc(int vendor, int id) +{ + ambapp_vendor_devnames *ven = &vendors[0]; + ambapp_device_name *dev; + + while (ven->vendor_id > 0) { + if (ven->vendor_id == vendor) { + dev = ambapp_get_dev(ven->devices, id); + if (!dev) + return NULL; + return dev->desc; + } + ven++; + } + return NULL; +} + +char *ambapp_vendor_id2str(int vendor) +{ + ambapp_vendor_devnames *ven = &vendors[0]; + + while (ven->vendor_id > 0) { + if (ven->vendor_id == vendor) { + return ven->name; + } + ven++; + } + return NULL; +} + +static char *unknown = "unknown"; + +char *ambapp_type_names[4] = { + /* 0 */ "UNUSED", + /* 1 */ "apb", + /* 2 */ "ahbmem", + /* 3 */ "ahbio" +}; + +/* Print one APB device */ +void ambapp_print_apb(ambapp_apbdev *dev, int index) +{ + char *dev_str, *ven_str; + unsigned int freq; + + ven_str = ambapp_vendor_id2str(dev->vendor); + if (!ven_str) { + ven_str = unknown; + dev_str = unknown; + } else { + dev_str = ambapp_device_id2str(dev->vendor, dev->device); + if (!dev_str) + dev_str = unknown; + } + + /* Get Frequency of Core */ + freq = ambapp_bus_freq(&ambapp_plb, dev->ahb_bus_index); + + printf("0x%02x:0x%02x:0x%02x: %s %s (%dkHz)\n" + " apb: 0x%08x - 0x%08x\n" + " irq: %-2d (ver: %-2d)\n", + index, dev->vendor, dev->device, ven_str, dev_str, freq / 1000, + dev->address, dev->address + (dev->mask-1), + dev->irq, dev->ver); +} + +void ambapp_print_ahb(ambapp_ahbdev *dev, int index) +{ + char *dev_str, *ven_str, *type_str; + int i; + unsigned int freq; + + ven_str = ambapp_vendor_id2str(dev->vendor); + if (!ven_str) { + ven_str = unknown; + dev_str = unknown; + } else { + dev_str = ambapp_device_id2str(dev->vendor, dev->device); + if (!dev_str) + dev_str = unknown; + } + + /* Get Frequency of Core */ + freq = ambapp_bus_freq(&ambapp_plb, dev->ahb_bus_index); + + printf("0x%02x:0x%02x:0x%02x: %s %s (%dkHz)\n", + index, dev->vendor, dev->device, ven_str, dev_str, freq / 1000); + + for (i = 0; i < 4; i++) { + if (dev->type[i] == 0) + continue; + type_str = ambapp_type_names[dev->type[i]]; + printf(" %-7s: 0x%08x - 0x%08x\n", type_str, dev->address[i], + dev->address[i] + (dev->mask[i]-1)); + } + + printf(" irq: %-2d (ver: %d)\n", dev->irq, dev->ver); +} + +int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + int index; + ambapp_apbdev apbdev; + ambapp_ahbdev ahbdev; + + /* Print AHB Masters */ + puts("\n--------- AHB Masters ---------\n"); + index = 0; + while (ambapp_ahbmst_find(&ambapp_plb, 0, 0, index, &ahbdev) == 1) { + /* Found a AHB Master Device */ + ambapp_print_ahb(&ahbdev, index); + index++; + } + + /* Print AHB Slaves */ + puts("\n--------- AHB Slaves ---------\n"); + index = 0; + while (ambapp_ahbslv_find(&ambapp_plb, 0, 0, index, &ahbdev) == 1) { + /* Found a AHB Slave Device */ + ambapp_print_ahb(&ahbdev, index); + index++; + } + + /* Print APB Slaves */ + puts("\n--------- APB Slaves ---------\n"); + index = 0; + while (ambapp_apb_find(&ambapp_plb, 0, 0, index, &apbdev) == 1) { + /* Found a APB Slave Device */ + ambapp_print_apb(&apbdev, index); + index++; + } + + puts("\n"); + return 0; +} + +int ambapp_init_reloc(void) +{ + ambapp_vendor_devnames *vend = vendors; + ambapp_device_name *dev; + + while (vend->vendor_id && vend->name) { + vend->name = (char *)((unsigned int)vend->name + gd->reloc_off); + vend->desc = (char *)((unsigned int)vend->desc + gd->reloc_off); + vend->devices = (ambapp_device_name *) + ((unsigned int)vend->devices + gd->reloc_off); + dev = vend->devices; + vend++; + if (!dev) + continue; + while (dev->device_id && dev->name) { + dev->name = + (char *)((unsigned int)dev->name + gd->reloc_off); + dev->desc = + (char *)((unsigned int)dev->desc + gd->reloc_off); + dev++; + } + } + return 0; +} + +U_BOOT_CMD( + ambapp, 1, 1, do_ambapp_print, + "list AMBA Plug&Play information", + "ambapp\n" + " - lists AMBA (AHB & APB) Plug&Play devices present on the system" +); diff --git a/cmd/armflash.c b/cmd/armflash.c new file mode 100644 index 0000000..b94d128 --- /dev/null +++ b/cmd/armflash.c @@ -0,0 +1,300 @@ +/* + * (C) Copyright 2015 + * Linus Walleij, Linaro + * + * Support for ARM Flash Partitions + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include + +#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(cmd_tbl_t *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 \n" + " - returns 1 if an image exists, else 0\n" + "load \n" + " - load an image to the location indicated in the header\n" + "load 0x
\n" + " - load an image to the location specified\n"); diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c new file mode 100644 index 0000000..deed6d8 --- /dev/null +++ b/cmd/bdinfo.c @@ -0,0 +1,574 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Boot support + */ +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +__maybe_unused +static void print_num(const char *name, ulong value) +{ + printf("%-12s= 0x%08lX\n", name, value); +} + +__maybe_unused +static void print_eth(int idx) +{ + char name[10], *val; + if (idx) + sprintf(name, "eth%iaddr", idx); + else + strcpy(name, "ethaddr"); + val = getenv(name); + if (!val) + val = "(not set)"; + printf("%-12s= %s\n", name, val); +} + +#ifndef CONFIG_DM_ETH +__maybe_unused +static void print_eths(void) +{ + struct eth_device *dev; + int i = 0; + + do { + dev = eth_get_dev_by_index(i); + if (dev) { + printf("eth%dname = %s\n", i, dev->name); + print_eth(i); + i++; + } + } while (dev); + + printf("current eth = %s\n", eth_get_name()); + printf("ip_addr = %s\n", getenv("ipaddr")); +} +#endif + +__maybe_unused +static void print_lnum(const char *name, unsigned long long value) +{ + printf("%-12s= 0x%.8llX\n", name, value); +} + +__maybe_unused +static void print_mhz(const char *name, unsigned long hz) +{ + char buf[32]; + + printf("%-12s= %6s MHz\n", name, strmhz(buf, hz)); +} + +#if defined(CONFIG_PPC) +void __weak board_detail(void) +{ + /* Please define boot_detail() for your platform */ +} + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + +#ifdef DEBUG + print_num("bd address", (ulong)bd); +#endif + print_num("memstart", bd->bi_memstart); + print_lnum("memsize", bd->bi_memsize); + print_num("flashstart", bd->bi_flashstart); + print_num("flashsize", bd->bi_flashsize); + print_num("flashoffset", bd->bi_flashoffset); + print_num("sramstart", bd->bi_sramstart); + print_num("sramsize", bd->bi_sramsize); +#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || \ + defined(CONFIG_MPC8260) || defined(CONFIG_E500) + print_num("immr_base", bd->bi_immr_base); +#endif + print_num("bootflags", bd->bi_bootflags); +#if defined(CONFIG_405EP) || \ + defined(CONFIG_405GP) || \ + defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ + defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ + defined(CONFIG_XILINX_405) + print_mhz("procfreq", bd->bi_procfreq); + print_mhz("plb_busfreq", bd->bi_plb_busfreq); +#if defined(CONFIG_405EP) || defined(CONFIG_405GP) || \ + defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ + defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \ + defined(CONFIG_440SPE) || defined(CONFIG_XILINX_405) + print_mhz("pci_busfreq", bd->bi_pci_busfreq); +#endif +#else /* ! CONFIG_405GP, CONFIG_405EP, CONFIG_XILINX_405, CONFIG_440EP CONFIG_440GR */ +#if defined(CONFIG_CPM2) + print_mhz("vco", bd->bi_vco); + print_mhz("sccfreq", bd->bi_sccfreq); + print_mhz("brgfreq", bd->bi_brgfreq); +#endif + print_mhz("intfreq", bd->bi_intfreq); +#if defined(CONFIG_CPM2) + print_mhz("cpmfreq", bd->bi_cpmfreq); +#endif + print_mhz("busfreq", bd->bi_busfreq); +#endif /* CONFIG_405GP, CONFIG_405EP, CONFIG_XILINX_405, CONFIG_440EP CONFIG_440GR */ + +#ifdef CONFIG_ENABLE_36BIT_PHYS +#ifdef CONFIG_PHYS_64BIT + puts("addressing = 36-bit\n"); +#else + puts("addressing = 32-bit\n"); +#endif +#endif + + print_eth(0); +#if defined(CONFIG_HAS_ETH1) + print_eth(1); +#endif +#if defined(CONFIG_HAS_ETH2) + print_eth(2); +#endif +#if defined(CONFIG_HAS_ETH3) + print_eth(3); +#endif +#if defined(CONFIG_HAS_ETH4) + print_eth(4); +#endif +#if defined(CONFIG_HAS_ETH5) + print_eth(5); +#endif + + printf("IP addr = %s\n", getenv("ipaddr")); + printf("baudrate = %6u bps\n", gd->baudrate); + print_num("relocaddr", gd->relocaddr); + board_detail(); + return 0; +} + +#elif defined(CONFIG_NIOS2) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int i; + bd_t *bd = gd->bd; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { + print_num("DRAM bank", i); + print_num("-> start", bd->bi_dram[i].start); + print_num("-> size", bd->bi_dram[i].size); + } + + print_num("flash start", (ulong)bd->bi_flashstart); + print_num("flash size", (ulong)bd->bi_flashsize); + print_num("flash offset", (ulong)bd->bi_flashoffset); + +#if defined(CONFIG_SYS_SRAM_BASE) + print_num ("sram start", (ulong)bd->bi_sramstart); + print_num ("sram size", (ulong)bd->bi_sramsize); +#endif + +#if defined(CONFIG_CMD_NET) + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); +#endif + + printf("baudrate = %u bps\n", gd->baudrate); + + return 0; +} + +#elif defined(CONFIG_MICROBLAZE) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { + print_num("DRAM bank", i); + print_num("-> start", bd->bi_dram[i].start); + print_num("-> size", bd->bi_dram[i].size); + } + + print_num("flash start ", (ulong)bd->bi_flashstart); + print_num("flash size ", (ulong)bd->bi_flashsize); + print_num("flash offset ", (ulong)bd->bi_flashoffset); +#if defined(CONFIG_SYS_SRAM_BASE) + print_num("sram start ", (ulong)bd->bi_sramstart); + print_num("sram size ", (ulong)bd->bi_sramsize); +#endif +#if defined(CONFIG_CMD_NET) + print_eths(); +#endif + printf("baudrate = %u bps\n", gd->baudrate); + print_num("relocaddr", gd->relocaddr); + print_num("reloc off", gd->reloc_off); + print_num("fdt_blob", (ulong)gd->fdt_blob); + print_num("new_fdt", (ulong)gd->new_fdt); + print_num("fdt_size", (ulong)gd->fdt_size); + + return 0; +} + +#elif defined(CONFIG_SPARC) + +int do_bdinfo(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + +#ifdef DEBUG + print_num("bd address ", (ulong) bd); +#endif + print_num("memstart ", bd->bi_memstart); + print_lnum("memsize ", bd->bi_memsize); + print_num("flashstart ", bd->bi_flashstart); + print_num("CONFIG_SYS_MONITOR_BASE ", CONFIG_SYS_MONITOR_BASE); + print_num("CONFIG_ENV_ADDR ", CONFIG_ENV_ADDR); + printf("CONFIG_SYS_RELOC_MONITOR_BASE = 0x%x (%d)\n", CONFIG_SYS_RELOC_MONITOR_BASE, + CONFIG_SYS_MONITOR_LEN); + printf("CONFIG_SYS_MALLOC_BASE = 0x%x (%d)\n", CONFIG_SYS_MALLOC_BASE, + CONFIG_SYS_MALLOC_LEN); + printf("CONFIG_SYS_INIT_SP_OFFSET = 0x%x (%d)\n", CONFIG_SYS_INIT_SP_OFFSET, + CONFIG_SYS_STACK_SIZE); + printf("CONFIG_SYS_PROM_OFFSET = 0x%x (%d)\n", CONFIG_SYS_PROM_OFFSET, + CONFIG_SYS_PROM_SIZE); + printf("CONFIG_SYS_GBL_DATA_OFFSET = 0x%x (%d)\n", CONFIG_SYS_GBL_DATA_OFFSET, + GENERATED_GBL_DATA_SIZE); + +#if defined(CONFIG_CMD_NET) + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); +#endif + printf("baudrate = %6u bps\n", gd->baudrate); + return 0; +} + +#elif defined(CONFIG_M68K) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + + print_num("memstart", (ulong)bd->bi_memstart); + print_lnum("memsize", (u64)bd->bi_memsize); + print_num("flashstart", (ulong)bd->bi_flashstart); + print_num("flashsize", (ulong)bd->bi_flashsize); + print_num("flashoffset", (ulong)bd->bi_flashoffset); +#if defined(CONFIG_SYS_INIT_RAM_ADDR) + print_num("sramstart", (ulong)bd->bi_sramstart); + print_num("sramsize", (ulong)bd->bi_sramsize); +#endif +#if defined(CONFIG_SYS_MBAR) + print_num("mbar", bd->bi_mbar_base); +#endif + print_mhz("cpufreq", bd->bi_intfreq); + print_mhz("busfreq", bd->bi_busfreq); +#ifdef CONFIG_PCI + print_mhz("pcifreq", bd->bi_pcifreq); +#endif +#ifdef CONFIG_EXTRA_CLOCK + print_mhz("flbfreq", bd->bi_flbfreq); + print_mhz("inpfreq", bd->bi_inpfreq); + print_mhz("vcofreq", bd->bi_vcofreq); +#endif +#if defined(CONFIG_CMD_NET) + print_eth(0); +#if defined(CONFIG_HAS_ETH1) + print_eth(1); +#endif +#if defined(CONFIG_HAS_ETH2) + print_eth(2); +#endif +#if defined(CONFIG_HAS_ETH3) + print_eth(3); +#endif + + printf("ip_addr = %s\n", getenv("ipaddr")); +#endif + printf("baudrate = %u bps\n", gd->baudrate); + + return 0; +} + +#elif defined(CONFIG_BLACKFIN) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + + printf("U-Boot = %s\n", bd->bi_r_version); + printf("CPU = %s\n", bd->bi_cpu); + printf("Board = %s\n", bd->bi_board_name); + print_mhz("VCO", bd->bi_vco); + print_mhz("CCLK", bd->bi_cclk); + print_mhz("SCLK", bd->bi_sclk); + + print_num("boot_params", (ulong)bd->bi_boot_params); + print_num("memstart", (ulong)bd->bi_memstart); + print_lnum("memsize", (u64)bd->bi_memsize); + print_num("flashstart", (ulong)bd->bi_flashstart); + print_num("flashsize", (ulong)bd->bi_flashsize); + print_num("flashoffset", (ulong)bd->bi_flashoffset); + + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); + printf("baudrate = %u bps\n", gd->baudrate); + + return 0; +} + +#elif defined(CONFIG_MIPS) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + + print_num("boot_params", (ulong)bd->bi_boot_params); + print_num("memstart", (ulong)bd->bi_memstart); + print_lnum("memsize", (u64)bd->bi_memsize); + print_num("flashstart", (ulong)bd->bi_flashstart); + print_num("flashsize", (ulong)bd->bi_flashsize); + print_num("flashoffset", (ulong)bd->bi_flashoffset); + + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); + printf("baudrate = %u bps\n", gd->baudrate); + + return 0; +} + +#elif defined(CONFIG_AVR32) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + + print_num("boot_params", (ulong)bd->bi_boot_params); + print_num("memstart", (ulong)bd->bi_dram[0].start); + print_lnum("memsize", (u64)bd->bi_dram[0].size); + print_num("flashstart", (ulong)bd->bi_flashstart); + print_num("flashsize", (ulong)bd->bi_flashsize); + print_num("flashoffset", (ulong)bd->bi_flashoffset); + + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); + printf("baudrate = %u bps\n", gd->baudrate); + + return 0; +} + +#elif defined(CONFIG_ARM) + +static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int i; + bd_t *bd = gd->bd; + + print_num("arch_number", bd->bi_arch_number); + print_num("boot_params", (ulong)bd->bi_boot_params); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { + print_num("DRAM bank", i); + print_num("-> start", bd->bi_dram[i].start); + print_num("-> size", bd->bi_dram[i].size); + } + +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + if (gd->secure_ram & MEM_RESERVE_SECURE_SECURED) { + print_num("Secure ram", + gd->secure_ram & MEM_RESERVE_SECURE_ADDR_MASK); + } +#endif +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH) + print_eths(); +#endif + printf("baudrate = %u bps\n", gd->baudrate); +#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) + print_num("TLB addr", gd->arch.tlb_addr); +#endif + print_num("relocaddr", gd->relocaddr); + print_num("reloc off", gd->reloc_off); + print_num("irq_sp", gd->irq_sp); /* irq stack pointer */ + print_num("sp start ", gd->start_addr_sp); +#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) + print_num("FB base ", gd->fb_base); +#endif + /* + * TODO: Currently only support for davinci SOC's is added. + * Remove this check once all the board implement this. + */ +#ifdef CONFIG_CLOCKS + printf("ARM frequency = %ld MHz\n", gd->bd->bi_arm_freq); + printf("DSP frequency = %ld MHz\n", gd->bd->bi_dsp_freq); + printf("DDR frequency = %ld MHz\n", gd->bd->bi_ddr_freq); +#endif +#ifdef CONFIG_BOARD_TYPES + printf("Board Type = %ld\n", gd->board_type); +#endif + return 0; +} + +#elif defined(CONFIG_SH) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + print_num("mem start ", (ulong)bd->bi_memstart); + print_lnum("mem size ", (u64)bd->bi_memsize); + print_num("flash start ", (ulong)bd->bi_flashstart); + print_num("flash size ", (ulong)bd->bi_flashsize); + print_num("flash offset ", (ulong)bd->bi_flashoffset); + +#if defined(CONFIG_CMD_NET) + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); +#endif + printf("baudrate = %u bps\n", gd->baudrate); + return 0; +} + +#elif defined(CONFIG_X86) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int i; + bd_t *bd = gd->bd; + + print_num("boot_params", (ulong)bd->bi_boot_params); + print_num("bi_memstart", bd->bi_memstart); + print_num("bi_memsize", bd->bi_memsize); + print_num("bi_flashstart", bd->bi_flashstart); + print_num("bi_flashsize", bd->bi_flashsize); + print_num("bi_flashoffset", bd->bi_flashoffset); + print_num("bi_sramstart", bd->bi_sramstart); + print_num("bi_sramsize", bd->bi_sramsize); + print_num("bi_bootflags", bd->bi_bootflags); + print_mhz("cpufreq", bd->bi_intfreq); + print_mhz("busfreq", bd->bi_busfreq); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { + print_num("DRAM bank", i); + print_num("-> start", bd->bi_dram[i].start); + print_num("-> size", bd->bi_dram[i].size); + } + +#if defined(CONFIG_CMD_NET) + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); + print_mhz("ethspeed", bd->bi_ethspeed); +#endif + printf("baudrate = %u bps\n", gd->baudrate); + + return 0; +} + +#elif defined(CONFIG_SANDBOX) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int i; + bd_t *bd = gd->bd; + + print_num("boot_params", (ulong)bd->bi_boot_params); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { + print_num("DRAM bank", i); + print_num("-> start", bd->bi_dram[i].start); + print_num("-> size", bd->bi_dram[i].size); + } + +#if defined(CONFIG_CMD_NET) + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); +#endif +#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) + print_num("FB base ", gd->fb_base); +#endif + return 0; +} + +#elif defined(CONFIG_NDS32) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int i; + bd_t *bd = gd->bd; + + print_num("arch_number", bd->bi_arch_number); + print_num("boot_params", (ulong)bd->bi_boot_params); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { + print_num("DRAM bank", i); + print_num("-> start", bd->bi_dram[i].start); + print_num("-> size", bd->bi_dram[i].size); + } + +#if defined(CONFIG_CMD_NET) + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); +#endif + printf("baudrate = %u bps\n", gd->baudrate); + + return 0; +} + +#elif defined(CONFIG_OPENRISC) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + + print_num("mem start", (ulong)bd->bi_memstart); + print_lnum("mem size", (u64)bd->bi_memsize); + print_num("flash start", (ulong)bd->bi_flashstart); + print_num("flash size", (ulong)bd->bi_flashsize); + print_num("flash offset", (ulong)bd->bi_flashoffset); + +#if defined(CONFIG_CMD_NET) + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); +#endif + + printf("baudrate = %u bps\n", gd->baudrate); + + return 0; +} + +#elif defined(CONFIG_ARC) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bd_t *bd = gd->bd; + + print_num("mem start", bd->bi_memstart); + print_lnum("mem size", bd->bi_memsize); + +#if defined(CONFIG_CMD_NET) + print_eth(0); + printf("ip_addr = %s\n", getenv("ipaddr")); +#endif + printf("baudrate = %d bps\n", gd->baudrate); + + return 0; +} + +#else + #error "a case for this architecture does not exist!" +#endif + +/* -------------------------------------------------------------------- */ + +U_BOOT_CMD( + bdinfo, 1, 1, do_bdinfo, + "print Board Info structure", + "" +); diff --git a/cmd/bedbug.c b/cmd/bedbug.c new file mode 100644 index 0000000..69afeaf --- /dev/null +++ b/cmd/bedbug.c @@ -0,0 +1,422 @@ +/* + * BedBug Functions + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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. + * ====================================================================== */ + +void bedbug_init (void) +{ + /* -------------------------------------------------- */ + +#if defined(CONFIG_4xx) + void bedbug405_init (void); + + bedbug405_init (); +#elif defined(CONFIG_8xx) + void bedbug860_init (void); + + bedbug860_init (); +#endif + +#if defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260) + /* Processors that are 603e core based */ + void bedbug603e_init (void); + + bedbug603e_init (); +#endif + + return; +} /* bedbug_init */ + + + +/* ====================================================================== + * Entry point from the interpreter to the disassembler. Repeated calls + * will resume from the last disassembled address. + * ====================================================================== */ +int do_bedbug_dis (cmd_tbl_t * 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
[# 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 (cmd_tbl_t * 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
"); + +/* ====================================================================== + * Used to set a break point from the interpreter. Simply calls into the + * CPU-specific break point set routine. + * ====================================================================== */ + +int do_bedbug_break (cmd_tbl_t * 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
- Break at an address\n" + "break off - 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 ("\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 (cmd_tbl_t * 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 (cmd_tbl_t * 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 (cmd_tbl_t * 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 (cmd_tbl_t * 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->bd->bi_memstart + gd->bd->bi_memsize; + 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 (cmd_tbl_t * 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/cmd/blob.c b/cmd/blob.c new file mode 100644 index 0000000..ac8b268 --- /dev/null +++ b/cmd/blob.c @@ -0,0 +1,111 @@ +/* + * + * Command for encapsulating/decapsulating blob of memory. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/** + * 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(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + uint32_t 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 (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/cmd/bmp.c b/cmd/bmp.c new file mode 100644 index 0000000..fd5b7db --- /dev/null +++ b/cmd/bmp.c @@ -0,0 +1,275 @@ +/* + * (C) Copyright 2002 + * Detlev Zundel, DENX Software Engineering, dzu@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * BMP handling routines + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 *)((((unsigned int)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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + ulong addr; + + switch (argc) { + case 1: /* use load_addr as default address */ + addr = 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(cmd_tbl_t * 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 load_addr as default address */ + addr = load_addr; + break; + case 2: /* use argument */ + addr = simple_strtoul(argv[1], NULL, 16); + break; + case 4: + addr = simple_strtoul(argv[1], NULL, 16); + x = simple_strtoul(argv[2], NULL, 10); + y = simple_strtoul(argv[3], NULL, 10); + break; + default: + return CMD_RET_USAGE; + } + + return (bmp_display(addr, x, y)); +} + +static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *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 - display image info\n" + "bmp display [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(UCLASS_VIDEO, &dev); + if (!ret) { + if (!dev) + ret = -ENODEV; + if (!ret) { + bool align = false; + +# ifdef CONFIG_SPLASH_SCREEN_ALIGN + align = true; +# endif /* CONFIG_SPLASH_SCREEN_ALIGN */ + ret = video_bmp_display(dev, addr, x, y, align); + } + } + return ret ? CMD_RET_FAILURE : 0; +#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; +} diff --git a/cmd/boot.c b/cmd/boot.c new file mode 100644 index 0000000..72f2cf3 --- /dev/null +++ b/cmd/boot.c @@ -0,0 +1,71 @@ +/* + * (C) Copyright 2000-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Misc boot support + */ +#include +#include +#include + +#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(cmd_tbl_t *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, 1, 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/cmd/bootldr.c b/cmd/bootldr.c new file mode 100644 index 0000000..bc5c1f9 --- /dev/null +++ b/cmd/bootldr.c @@ -0,0 +1,170 @@ +/* + * U-boot - bootldr.c + * + * Copyright (c) 2005-2008 Analog Devices Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include + +#include +#include + +/* Simple sanity check on the specified address to make sure it contains + * an LDR image of some sort. + */ +static bool ldr_valid_signature(uint8_t *data) +{ +#if defined(__ADSPBF561__) + + /* BF56x has a 4 byte global header */ + if (data[3] == (GFLAG_56X_SIGN_MAGIC << (GFLAG_56X_SIGN_SHIFT - 24))) + return true; + +#elif defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ + defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ + defined(__ADSPBF538__) || defined(__ADSPBF539__) + + /* all the BF53x should start at this address mask */ + uint32_t addr; + memmove(&addr, data, sizeof(addr)); + if ((addr & 0xFF0FFF0F) == 0xFF000000) + return true; +#else + + /* everything newer has a magic byte */ + uint32_t count; + memmove(&count, data + 8, sizeof(count)); + if (data[3] == 0xAD && count == 0) + return true; + +#endif + + return false; +} + +/* If the Blackfin is new enough, the Blackfin on-chip ROM supports loading + * LDRs from random memory addresses. So whenever possible, use that. In + * the older cases (BF53x/BF561), parse the LDR format ourselves. + */ +static void ldr_load(uint8_t *base_addr) +{ +#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ + /*defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) ||*/\ + defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) + + uint32_t addr; + uint32_t count; + uint16_t flags; + + /* the bf56x has a 4 byte global header ... but it is useless to + * us when booting an LDR from a memory address, so skip it + */ +# ifdef __ADSPBF561__ + base_addr += 4; +# endif + + memmove(&flags, base_addr + 8, sizeof(flags)); + bfin_write_EVT1(flags & BFLAG_53X_RESVECT ? 0xFFA00000 : 0xFFA08000); + + do { + /* block header may not be aligned */ + memmove(&addr, base_addr, sizeof(addr)); + memmove(&count, base_addr+4, sizeof(count)); + memmove(&flags, base_addr+8, sizeof(flags)); + base_addr += sizeof(addr) + sizeof(count) + sizeof(flags); + + printf("loading to 0x%08x (%#x bytes) flags: 0x%04x\n", + addr, count, flags); + + if (!(flags & BFLAG_53X_IGNORE)) { + if (flags & BFLAG_53X_ZEROFILL) + memset((void *)addr, 0x00, count); + else + memcpy((void *)addr, base_addr, count); + + if (flags & BFLAG_53X_INIT) { + void (*init)(void) = (void *)addr; + init(); + } + } + + if (!(flags & BFLAG_53X_ZEROFILL)) + base_addr += count; + } while (!(flags & BFLAG_53X_FINAL)); + +#endif +} + +/* For BF537, we use the _BOOTROM_BOOT_DXE_FLASH funky ROM function. + * For all other BF53x/BF56x, we just call the entry point. + * For everything else (newer), we use _BOOTROM_MEMBOOT ROM function. + */ +static void ldr_exec(void *addr) +{ +#if defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) + + /* restore EVT1 to reset value as this is what the bootrom uses as + * the default entry point when booting the final block of LDRs + */ + bfin_write_EVT1(L1_INST_SRAM); + __asm__("call (%0);" : : "a"(_BOOTROM_MEMBOOT), "q7"(addr) : "RETS", "memory"); + +#elif defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ + defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) + + void (*ldr_entry)(void) = (void *)bfin_read_EVT1(); + ldr_entry(); + +#else + + int32_t (*BOOTROM_MEM)(void *, int32_t, int32_t, void *) = (void *)_BOOTROM_MEMBOOT; + BOOTROM_MEM(addr, 0, 0, NULL); + +#endif +} + +/* + * the bootldr command loads an address, checks to see if there + * is a Boot stream that the on-chip BOOTROM can understand, + * and loads it via the BOOTROM Callback. It is possible + * to also add booting from SPI, or TWI, but this function does + * not currently support that. + */ +int do_bootldr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + void *addr; + + /* Get the address */ + if (argc < 2) + addr = (void *)load_addr; + else + addr = (void *)simple_strtoul(argv[1], NULL, 16); + + /* Check if it is a LDR file */ + if (ldr_valid_signature(addr)) { + printf("## Booting ldr image at 0x%p ...\n", addr); + ldr_load(addr); + + icache_disable(); + dcache_disable(); + + ldr_exec(addr); + } else + printf("## No ldr image at address 0x%p\n", addr); + + return 0; +} + +U_BOOT_CMD( + bootldr, 2, 0, do_bootldr, + "boot ldr image from memory", + "[addr]\n" + "" +); diff --git a/cmd/bootm.c b/cmd/bootm.c new file mode 100644 index 0000000..48738ac --- /dev/null +++ b/cmd/bootm.c @@ -0,0 +1,775 @@ +/* + * (C) Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Boot support + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_CMD_IMI) +static int image_info(unsigned long addr); +#endif + +#if defined(CONFIG_CMD_IMLS) +#include +#include +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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +#endif + +bootm_headers_t images; /* pointers to os/initrd/fdt images */ + +/* we overload the cmd field with our state machine info instead of a + * function pointer */ +static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int ret = 0; + long state; + cmd_tbl_t *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(cmd_tbl_t *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 | +#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(cmd_tbl_t *cmdtp, const char *cmd) +{ + const char *ep = getenv("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", 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 extened to include component or configuration unit name:\n" + "\taddr: - direct component image specification\n" + "\taddr# - 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_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return run_command(getenv("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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int arg; + ulong addr; + int rcode = 0; + + if (argc < 2) { + return image_info(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 *)addr; + + printf("\n## Checking Image at %08lx ...\n", addr); + + switch (genimg_get_format(hdr)) { +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + case IMAGE_FORMAT_LEGACY: + puts(" Legacy image found\n"); + if (!image_check_magic(hdr)) { + puts(" Bad Magic Number\n"); + return 1; + } + + if (!image_check_hcrc(hdr)) { + puts(" Bad Header Checksum\n"); + return 1; + } + + image_print_contents(hdr); + + puts(" Verifying Checksum ... "); + if (!image_check_dcrc(hdr)) { + puts(" Bad Data CRC\n"); + return 1; + } + puts("OK\n"); + return 0; +#endif +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + puts(" FIT image found\n"); + + if (!fit_check_format(hdr)) { + puts("Bad FIT image format!\n"); + return 1; + } + + fit_print_contents(hdr); + + if (!fit_all_image_verify(hdr)) { + puts("Bad hash in FIT image!\n"); + return 1; + } + + return 0; +#endif + default: + puts("Unknown image format!\n"); + break; + } + + 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_IMAGE_FORMAT_LEGACY) + 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)) + 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(nand_info_t *nand, 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(nand, off, &len, + 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(nand_info_t *nand, 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(nand, off, &len, + imgdata); + if (ret < 0 && ret != -EUCLEAN) { + free(imgdata); + return ret; + } + + if (!fit_check_format(imgdata)) { + 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) +{ + nand_info_t *nand; + 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++) { + nand = &nand_info[nand_dev]; + if (!nand->name || !nand->size) + continue; + + for (off = 0; off < nand->size; off += nand->erasesize) { + const image_header_t *header; + int ret; + + if (nand_block_isbad(nand, off)) + continue; + + len = sizeof(buffer); + + ret = nand_read(nand, 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_IMAGE_FORMAT_LEGACY) + case IMAGE_FORMAT_LEGACY: + header = (const image_header_t *)buffer; + + len = image_get_image_size(header); + nand_imls_legacyimage(nand, nand_dev, off, len); + break; +#endif +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + len = fit_get_size(buffer); + nand_imls_fitimage(nand, nand_dev, off, len); + break; +#endif + } + } + } + + return 0; +} +#endif + +#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) +static int do_imls(cmd_tbl_t *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 + +#ifdef CONFIG_CMD_BOOTZ + +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(cmd_tbl_t *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 = load_addr; + debug("* kernel: default image load address = 0x%08lx\n", + 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)) + return 1; + + return 0; +} + +int do_bootz(cmd_tbl_t *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, + 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 +); +#endif /* CONFIG_CMD_BOOTZ */ + +#ifdef CONFIG_CMD_BOOTI +/* See Documentation/arm64/booting.txt in the Linux kernel */ +struct Image_header { + uint32_t code0; /* Executable code */ + uint32_t code1; /* Executable code */ + uint64_t text_offset; /* Image load offset, LE */ + uint64_t image_size; /* Effective Image size, LE */ + uint64_t res1; /* reserved */ + uint64_t res2; /* reserved */ + uint64_t res3; /* reserved */ + uint64_t res4; /* reserved */ + uint32_t magic; /* Magic number */ + uint32_t res5; +}; + +#define LINUX_ARM64_IMAGE_MAGIC 0x644d5241 + +static int booti_setup(bootm_headers_t *images) +{ + struct Image_header *ih; + uint64_t dst; + + ih = (struct Image_header *)map_sysmem(images->ep, 0); + + if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) { + puts("Bad Linux ARM64 Image magic!\n"); + return 1; + } + + if (ih->image_size == 0) { + puts("Image lacks image_size field, assuming 16MiB\n"); + ih->image_size = (16 << 20); + } + + /* + * If we are not at the correct run-time location, set the new + * correct location and then move the image there. + */ + dst = gd->bd->bi_dram[0].start + le32_to_cpu(ih->text_offset); + if (images->ep != dst) { + void *src; + + debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst); + + src = (void *)images->ep; + images->ep = dst; + memmove((void *)dst, src, le32_to_cpu(ih->image_size)); + } + + return 0; +} + +/* + * Image booting support + */ +static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[], bootm_headers_t *images) +{ + int ret; + struct Image_header *ih; + + ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START, + images, 1); + + /* Setup Linux kernel Image entry point */ + if (!argc) { + images->ep = load_addr; + debug("* kernel: default image load address = 0x%08lx\n", + load_addr); + } else { + images->ep = simple_strtoul(argv[0], NULL, 16); + debug("* kernel: cmdline image address = 0x%08lx\n", + images->ep); + } + + ret = booti_setup(images); + if (ret != 0) + return 1; + + ih = (struct Image_header *)map_sysmem(images->ep, 0); + + lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->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)) + return 1; + + return 0; +} + +int do_booti(cmd_tbl_t *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; + ret = do_bootm_states(cmdtp, flag, argc, argv, + 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 Image 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) + "\tSince booting a Linux kernelrequires 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.\n" +#endif + ""; +#endif + +U_BOOT_CMD( + booti, CONFIG_SYS_MAXARGS, 1, do_booti, + "boot arm64 Linux Image image from memory", booti_help_text +); +#endif /* CONFIG_CMD_BOOTI */ diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c new file mode 100644 index 0000000..5879065 --- /dev/null +++ b/cmd/bootmenu.c @@ -0,0 +1,500 @@ +/* + * (C) Copyright 2011-2013 Pali Rohár + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +/* 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, +}; + +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 getenv(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 = getc(); + + switch (c) { + case '\e': + *esc = 1; + *key = KEY_NONE; + break; + case '\r': + *key = KEY_SELECT; + 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; + + while (!tstc()) { + WATCHDOG_RESET(); + mdelay(10); + } + + c = getc(); + + 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 { + *esc = 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; +} + +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; + 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; + struct bootmenu_entry *entry; + + menu = malloc(sizeof(struct bootmenu_data)); + if (!menu) + return NULL; + + menu->delay = delay; + menu->active = 0; + menu->first = NULL; + + 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; + return menu; + +cleanup: + bootmenu_destroy(menu); + return NULL; +} + +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, 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 +} + +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"); + puts(ANSI_CLEAR_LINE_TO_END); + printf(ANSI_CURSOR_POSITION, menu->count + 7, 1); + puts(ANSI_CLEAR_LINE); +} + +#ifdef CONFIG_MENU_SHOW +int menu_show(int bootdelay) +{ + bootmenu_show(bootdelay); + return -1; /* -1 - abort boot and run monitor code */ +} +#endif + +int do_bootmenu(cmd_tbl_t *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 = getenv("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/cmd/bootstage.c b/cmd/bootstage.c new file mode 100644 index 0000000..788ab16 --- /dev/null +++ b/cmd/bootstage.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2012, Google Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +static int do_bootstage_report(cmd_tbl_t *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(cmd_tbl_t *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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *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 [ []] - Stash data into memory\n" + "unstash [ []] - Unstash data from memory" +); diff --git a/cmd/cache.c b/cmd/cache.c new file mode 100644 index 0000000..37ab345 --- /dev/null +++ b/cmd/cache.c @@ -0,0 +1,106 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Cache support: switch on or off, get status + */ +#include +#include +#include + +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"); +} + +static int do_icache(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + switch (argc) { + case 2: /* on / off */ + switch (parse_argv(argv[1])) { + case 0: + icache_disable(); + break; + case 1: + icache_enable(); + break; + case 2: + invalidate_icache_all(); + break; + } + 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + switch (argc) { + case 2: /* on / off */ + switch (parse_argv(argv[1])) { + case 0: + dcache_disable(); + break; + case 1: + dcache_enable(); + break; + case 2: + flush_dcache_all(); + break; + } + 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/cmd/cbfs.c b/cmd/cbfs.c new file mode 100644 index 0000000..35d8a7a --- /dev/null +++ b/cmd/cbfs.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * CBFS commands + */ +#include +#include +#include + +int do_cbfs_init(cmd_tbl_t *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 = (int)simple_strtoul(argv[1], &ep, 16); + if (*ep) { + puts("\n** Invalid end of ROM **\n"); + return 1; + } + } + file_cbfs_init(end_of_rom); + if (file_cbfs_result != CBFS_SUCCESS) { + 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" +); + +int do_cbfs_fsload(cmd_tbl_t *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 [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 (file_cbfs_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); + + setenv_hex("filesize", size); + + return 0; +} + +U_BOOT_CMD( + cbfsload, 4, 0, do_cbfs_fsload, + "load binary file from a cbfs filesystem", + " [bytes]\n" + " - load binary file 'filename' from the cbfs to address 'addr'\n" +); + +int do_cbfs_ls(cmd_tbl_t *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) { + u32 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_STAGE: + type_name = "stage"; + break; + case CBFS_TYPE_PAYLOAD: + type_name = "payload"; + 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_COMPONENT_CMOS_DEFAULT: + type_name = "cmos default"; + break; + case CBFS_COMPONENT_CMOS_LAYOUT: + type_name = "cmos layout"; + break; + case -1UL: + 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" +); + +int do_cbfs_fsinfo(cmd_tbl_t *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/cmd/clk.c b/cmd/clk.c new file mode 100644 index 0000000..6d3d46a --- /dev/null +++ b/cmd/clk.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2013 Xilinx, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include + +int __weak soc_clk_dump(void) +{ + puts("Not implemented\n"); + return 1; +} + +static int do_clk_dump(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + return soc_clk_dump(); +} + +static cmd_tbl_t cmd_clk_sub[] = { + U_BOOT_CMD_MKENT(dump, 1, 1, do_clk_dump, "", ""), +}; + +static int do_clk(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + cmd_tbl_t *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/cmd/cmd_aes.c b/cmd/cmd_aes.c deleted file mode 100644 index 76da3ef..0000000 --- a/cmd/cmd_aes.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2014 Marek Vasut - * - * Command for en/de-crypting block of memory with AES-128-CBC cipher. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -/** - * 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(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - uint32_t key_addr, src_addr, dst_addr, len; - uint8_t *key_ptr, *src_ptr, *dst_ptr; - uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; - uint32_t aes_blocks; - int enc; - - 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; - - key_addr = simple_strtoul(argv[2], NULL, 16); - src_addr = simple_strtoul(argv[3], NULL, 16); - dst_addr = simple_strtoul(argv[4], NULL, 16); - len = simple_strtoul(argv[5], NULL, 16); - - key_ptr = (uint8_t *)key_addr; - src_ptr = (uint8_t *)src_addr; - dst_ptr = (uint8_t *)dst_addr; - - /* First we expand the key. */ - aes_expand_key(key_ptr, key_exp); - - /* Calculate the number of AES blocks to encrypt. */ - aes_blocks = DIV_ROUND_UP(len, AES_KEY_LENGTH); - - if (enc) - aes_cbc_encrypt_blocks(key_exp, src_ptr, dst_ptr, aes_blocks); - else - aes_cbc_decrypt_blocks(key_exp, src_ptr, dst_ptr, aes_blocks); - - return 0; -} - -/***************************************************/ -#ifdef CONFIG_SYS_LONGHELP -static char aes_help_text[] = - "enc key src dst len - Encrypt block of data $len bytes long\n" - " at address $src using a key at address\n" - " $key and store the result at address\n" - " $dst. The $len size must be multiple of\n" - " 16 bytes and $key must be 16 bytes long.\n" - "aes dec key src dst len - Decrypt block of data $len bytes long\n" - " at address $src using a key at address\n" - " $key and store the result at address\n" - " $dst. The $len size must be multiple of\n" - " 16 bytes and $key must be 16 bytes long."; -#endif - -U_BOOT_CMD( - aes, 6, 1, do_aes, - "AES 128 CBC encryption", - aes_help_text -); diff --git a/cmd/cmd_ambapp.c b/cmd/cmd_ambapp.c deleted file mode 100644 index 4b6d174..0000000 --- a/cmd/cmd_ambapp.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * (C) Copyright 2007 - * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * AMBA Plug&Play information list command - * - */ -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -typedef struct { - int device_id; - char *name; - char *desc; -} ambapp_device_name; - -typedef struct { - unsigned int vendor_id; - char *name; - char *desc; - ambapp_device_name *devices; -} ambapp_vendor_devnames; - -/** Vendor GAISLER devices */ -static ambapp_device_name GAISLER_devices[] = { - {GAISLER_LEON2DSU, "LEON2DSU", "Leon2 Debug Support Unit"}, - {GAISLER_LEON3, "LEON3", "Leon3 SPARC V8 Processor"}, - {GAISLER_LEON3DSU, "LEON3DSU", "Leon3 Debug Support Unit"}, - {GAISLER_ETHAHB, "ETHAHB", "OC ethernet AHB interface"}, - {GAISLER_APBMST, "APBMST", "AHB/APB Bridge"}, - {GAISLER_AHBUART, "AHBUART", "AHB Debug UART"}, - {GAISLER_SRCTRL, "SRCTRL", "Simple SRAM Controller"}, - {GAISLER_SDCTRL, "SDCTRL", "PC133 SDRAM Controller"}, - {GAISLER_SSRCTRL, "SSRCTRL", "Synchronous SRAM Controller"}, - {GAISLER_APBUART, "APBUART", "Generic UART"}, - {GAISLER_IRQMP, "IRQMP", "Multi-processor Interrupt Ctrl."}, - {GAISLER_AHBRAM, "AHBRAM", "Single-port AHB SRAM module"}, - {GAISLER_AHBDPRAM, "AHBDPRAM", "Dual-port AHB SRAM module"}, - {GAISLER_GPTIMER, "GPTIMER", "Modular Timer Unit"}, - {GAISLER_PCITRG, "PCITRG", "Simple 32-bit PCI Target"}, - {GAISLER_PCISBRG, "PCISBRG", "Simple 32-bit PCI Bridge"}, - {GAISLER_PCIFBRG, "PCIFBRG", "Fast 32-bit PCI Bridge"}, - {GAISLER_PCITRACE, "PCITRACE", "32-bit PCI Trace Buffer"}, - {GAISLER_DMACTRL, "DMACTRL", "AMBA DMA controller"}, - {GAISLER_AHBTRACE, "AHBTRACE", "AMBA Trace Buffer"}, - {GAISLER_DSUCTRL, "DSUCTRL", "DSU/ETH controller"}, - {GAISLER_CANAHB, "CANAHB", "OC CAN AHB interface"}, - {GAISLER_GPIO, "GPIO", "General Purpose I/O port"}, - {GAISLER_AHBROM, "AHBROM", "Generic AHB ROM"}, - {GAISLER_AHBJTAG, "AHBJTAG", "JTAG Debug Link"}, - {GAISLER_ETHMAC, "ETHMAC", "GR Ethernet MAC"}, - {GAISLER_SWNODE, "SWNODE", "SpaceWire Node Interface"}, - {GAISLER_SPW, "SPW", "SpaceWire Serial Link"}, - {GAISLER_AHB2AHB, "AHB2AHB", "AHB-to-AHB Bridge"}, - {GAISLER_USBDC, "USBDC", "GR USB 2.0 Device Controller"}, - {GAISLER_USB_DCL, "USB_DCL", "USB Debug Communication Link"}, - {GAISLER_DDRMP, "DDRMP", "Multi-port DDR controller"}, - {GAISLER_ATACTRL, "ATACTRL", "ATA controller"}, - {GAISLER_DDRSP, "DDRSP", "Single-port DDR266 controller"}, - {GAISLER_EHCI, "EHCI", "USB Enhanced Host Controller"}, - {GAISLER_UHCI, "UHCI", "USB Universal Host Controller"}, - {GAISLER_I2CMST, "I2CMST", "AMBA Wrapper for OC I2C-master"}, - {GAISLER_SPW2, "SPW2", "GRSPW2 SpaceWire Serial Link"}, - {GAISLER_AHBDMA, "AHBDMA", ""}, - {GAISLER_NUHOSP3, "NUHOSP3", "Nuhorizons Spartan3 IO I/F"}, - {GAISLER_CLKGATE, "CLKGATE", "Clock gating unit"}, - {GAISLER_SPICTRL, "SPICTRL", "SPI Controller"}, - {GAISLER_DDR2SP, "DDR2SP", "Single-port DDR2 controller"}, - {GAISLER_SLINK, "SLINK", "SLINK Master"}, - {GAISLER_GRTM, "GRTM", "CCSDS Telemetry Encoder"}, - {GAISLER_GRTC, "GRTC", "CCSDS Telecommand Decoder"}, - {GAISLER_GRPW, "GRPW", "PacketWire to AMBA AHB I/F"}, - {GAISLER_GRCTM, "GRCTM", "CCSDS Time Manager"}, - {GAISLER_GRHCAN, "GRHCAN", "ESA HurriCANe CAN with DMA"}, - {GAISLER_GRFIFO, "GRFIFO", "FIFO Controller"}, - {GAISLER_GRADCDAC, "GRADCDAC", "ADC / DAC Interface"}, - {GAISLER_GRPULSE, "GRPULSE", "General Purpose I/O with Pulses"}, - {GAISLER_GRTIMER, "GRTIMER", "Timer Unit with Latches"}, - {GAISLER_AHB2PP, "AHB2PP", "AMBA AHB to Packet Parallel I/F"}, - {GAISLER_GRVERSION, "GRVERSION", "Version and Revision Register"}, - {GAISLER_APB2PW, "APB2PW", "PacketWire Transmit Interface"}, - {GAISLER_PW2APB, "PW2APB", "PacketWire Receive Interface"}, - {GAISLER_GRCAN, "GRCAN", "CAN Controller with DMA"}, - {GAISLER_I2CSLV, "I2CSLV", "I2C Slave"}, - {GAISLER_U16550, "U16550", "Simple 16550 UART"}, - {GAISLER_AHBMST_EM, "AHBMST_EM", "AMBA Master Emulator"}, - {GAISLER_AHBSLV_EM, "AHBSLV_EM", "AMBA Slave Emulator"}, - {GAISLER_GRTESTMOD, "GRTESTMOD", "Test report module"}, - {GAISLER_ASCS, "ASCS", "ASCS Master"}, - {GAISLER_IPMVBCTRL, "IPMVBCTRL", "IPM-bus/MVBC memory controller"}, - {GAISLER_SPIMCTRL, "SPIMCTRL", "SPI Memory Controller"}, - {GAISLER_L4STAT, "L4STAT", "Leon4 Statistics Module"}, - {GAISLER_LEON4, "LEON4", "Leon4 SPARC V8 Processor"}, - {GAISLER_LEON4DSU, "LEON4DSU", "Leon4 Debug Support Unit"}, - {GAISLER_PWM, "PWM", "PWM generator"}, - {GAISLER_L2CACHE, "L2CACHE", "L2-Cache Controller"}, - {GAISLER_SDCTRL64, "SDCTRL64", "64-bit PC133 SDRAM Controller"}, - {GAISLER_GR1553B, "GR1553B", "MIL-STD-1553B Interface"}, - {GAISLER_1553TST, "1553TST", "MIL-STD-1553B Test Device"}, - {GAISLER_GRIOMMU, "GRIOMMU", "I/O Memory Management Unit"}, - {GAISLER_FTAHBRAM, "FTAHBRAM", "Generic FT AHB SRAM module"}, - {GAISLER_FTSRCTRL, "FTSRCTRL", "Simple FT SRAM Controller"}, - {GAISLER_AHBSTAT, "AHBSTAT", "AHB Status Register"}, - {GAISLER_LEON3FT, "LEON3FT", "Leon3-FT SPARC V8 Processor"}, - {GAISLER_FTMCTRL, "FTMCTRL", "Memory controller with EDAC"}, - {GAISLER_FTSDCTRL, "FTSDCTRL", "FT PC133 SDRAM Controller"}, - {GAISLER_FTSRCTRL8, "FTSRCTRL8", "FT 8-bit SRAM/16-bit IO Ctrl"}, - {GAISLER_MEMSCRUB, "MEMSCRUB", "AHB Memory Scrubber"}, - {GAISLER_FTSDCTRL64, "FTSDCTRL64", "64-bit FT SDRAM Controller"}, - {GAISLER_APBPS2, "APBPS2", "PS2 interface"}, - {GAISLER_VGACTRL, "VGACTRL", "VGA controller"}, - {GAISLER_LOGAN, "LOGAN", "On chip Logic Analyzer"}, - {GAISLER_SVGACTRL, "SVGACTRL", "SVGA frame buffer"}, - {GAISLER_T1AHB, "T1AHB", "Niagara T1 PCX/AHB bridge"}, - {GAISLER_MP7WRAP, "MP7WRAP", "CoreMP7 wrapper"}, - {GAISLER_GRSYSMON, "GRSYSMON", "AMBA wrapper for System Monitor"}, - {GAISLER_GRACECTRL, "GRACECTRL", "System ACE I/F Controller"}, - {GAISLER_ATAHBSLV, "ATAHBSLV", "AMBA Test Framework AHB Slave"}, - {GAISLER_ATAHBMST, "ATAHBMST", "AMBA Test Framework AHB Master"}, - {GAISLER_ATAPBSLV, "ATAPBSLV", "AMBA Test Framework APB Slave"}, - {GAISLER_B1553BC, "B1553BC", "AMBA Wrapper for Core1553BBC"}, - {GAISLER_B1553RT, "B1553RT", "AMBA Wrapper for Core1553BRT"}, - {GAISLER_B1553BRM, "B1553BRM", "AMBA Wrapper for Core1553BRM"}, - {GAISLER_AES, "AES", "Advanced Encryption Standard"}, - {GAISLER_ECC, "ECC", "Elliptic Curve Cryptography"}, - {GAISLER_PCIF, "PCIF", "AMBA Wrapper for CorePCIF"}, - {GAISLER_CLKMOD, "CLKMOD", "CPU Clock Switching Ctrl module"}, - {GAISLER_HAPSTRAK, "HAPSTRAK", "HAPS HapsTrak I/O Port"}, - {GAISLER_TEST_1X2, "TEST_1X2", "HAPS TEST_1x2 interface"}, - {GAISLER_WILD2AHB, "WILD2AHB", "WildCard CardBus interface"}, - {GAISLER_BIO1, "BIO1", "Basic I/O board BIO1"}, - {GAISLER_AESDMA, "AESDMA", "AES 256 DMA"}, - {GAISLER_SATCAN, "SATCAN", "SatCAN controller"}, - {GAISLER_CANMUX, "CANMUX", "CAN Bus multiplexer"}, - {GAISLER_GRTMRX, "GRTMRX", "CCSDS Telemetry Receiver"}, - {GAISLER_GRTCTX, "GRTCTX", "CCSDS Telecommand Transmitter"}, - {GAISLER_GRTMDESC, "GRTMDESC", "CCSDS Telemetry Descriptor"}, - {GAISLER_GRTMVC, "GRTMVC", "CCSDS Telemetry VC Generator"}, - {GAISLER_GEFFE, "GEFFE", "Geffe Generator"}, - {GAISLER_GPREG, "GPREG", "General Purpose Register"}, - {GAISLER_GRTMPAHB, "GRTMPAHB", "CCSDS Telemetry VC AHB Input"}, - {GAISLER_SPWCUC, "SPWCUC", "CCSDS CUC / SpaceWire I/F"}, - {GAISLER_SPW2_DMA, "SPW2_DMA", "GRSPW Router DMA interface"}, - {GAISLER_SPWROUTER, "SPWROUTER", "GRSPW Router"}, - {0, NULL, NULL} -}; - - -/** Vendor PENDER devices */ -static ambapp_device_name PENDER_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor ESA devices */ -static ambapp_device_name ESA_devices[] = { - {ESA_LEON2, "LEON2", "Leon2 SPARC V8 Processor"}, - {ESA_LEON2APB, "LEON2APB", "Leon2 Peripheral Bus"}, - {ESA_IRQ, "IRQ", "Leon2 Interrupt Controller"}, - {ESA_TIMER, "TIMER", "Leon2 Timer"}, - {ESA_UART, "UART", "Leon2 UART"}, - {ESA_CFG, "CFG", "Leon2 Configuration Register"}, - {ESA_IO, "IO", "Leon2 Input/Output"}, - {ESA_MCTRL, "MCTRL", "Leon2 Memory Controller"}, - {ESA_PCIARB, "PCIARB", "PCI Arbiter"}, - {ESA_HURRICANE, "HURRICANE", "HurriCANe/HurryAMBA CAN Ctrl"}, - {ESA_SPW_RMAP, "SPW_RMAP", "UoD/Saab SpaceWire/RMAP link"}, - {ESA_AHBUART, "AHBUART", "Leon2 AHB Debug UART"}, - {ESA_SPWA, "SPWA", "ESA/ASTRIUM SpaceWire link"}, - {ESA_BOSCHCAN, "BOSCHCAN", "SSC/BOSCH CAN Ctrl"}, - {ESA_IRQ2, "IRQ2", "Leon2 Secondary Irq Controller"}, - {ESA_AHBSTAT, "AHBSTAT", "Leon2 AHB Status Register"}, - {ESA_WPROT, "WPROT", "Leon2 Write Protection"}, - {ESA_WPROT2, "WPROT2", "Leon2 Extended Write Protection"}, - {ESA_PDEC3AMBA, "PDEC3AMBA", "ESA CCSDS PDEC3AMBA TC Decoder"}, - {ESA_PTME3AMBA, "PTME3AMBA", "ESA CCSDS PTME3AMBA TM Encoder"}, - {0, NULL, NULL} -}; - - -/** Vendor ASTRIUM devices */ -static ambapp_device_name ASTRIUM_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor OPENCHIP devices */ -static ambapp_device_name OPENCHIP_devices[] = { - {OPENCHIP_APBGPIO, "APBGPIO", "APB General Purpose IO"}, - {OPENCHIP_APBI2C, "APBI2C", "APB I2C Interface"}, - {OPENCHIP_APBSPI, "APBSPI", "APB SPI Interface"}, - {OPENCHIP_APBCHARLCD, "APBCHARLCD", "APB Character LCD"}, - {OPENCHIP_APBPWM, "APBPWM", "APB PWM"}, - {OPENCHIP_APBPS2, "APBPS2", "APB PS/2 Interface"}, - {OPENCHIP_APBMMCSD, "APBMMCSD", "APB MMC/SD Card Interface"}, - {OPENCHIP_APBNAND, "APBNAND", "APB NAND(SmartMedia) Interface"}, - {OPENCHIP_APBLPC, "APBLPC", "APB LPC Interface"}, - {OPENCHIP_APBCF, "APBCF", "APB CompactFlash (IDE)"}, - {OPENCHIP_APBSYSACE, "APBSYSACE", "APB SystemACE Interface"}, - {OPENCHIP_APB1WIRE, "APB1WIRE", "APB 1-Wire Interface"}, - {OPENCHIP_APBJTAG, "APBJTAG", "APB JTAG TAP Master"}, - {OPENCHIP_APBSUI, "APBSUI", "APB Simple User Interface"}, - {0, NULL, NULL} -}; - - -/** Vendor OPENCORES devices */ -static ambapp_device_name OPENCORES_devices[] = { - {OPENCORES_PCIBR, "PCIBR", "PCI Bridge"}, - {OPENCORES_ETHMAC, "ETHMAC", "Ethernet MAC"}, - {0, NULL} -}; - - -/** Vendor CONTRIB devices */ -static ambapp_device_name CONTRIB_devices[] = { - {CONTRIB_CORE1, "CORE1", "Contributed core 1"}, - {CONTRIB_CORE2, "CORE2", "Contributed core 2"}, - {0, NULL, NULL} -}; - - -/** Vendor EONIC devices */ -static ambapp_device_name EONIC_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor RADIONOR devices */ -static ambapp_device_name RADIONOR_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor GLEICHMANN devices */ -static ambapp_device_name GLEICHMANN_devices[] = { - {GLEICHMANN_CUSTOM, "CUSTOM", "Custom device"}, - {GLEICHMANN_GEOLCD01, "GEOLCD01", "GEOLCD01 graphics system"}, - {GLEICHMANN_DAC, "DAC", "Sigma delta DAC"}, - {GLEICHMANN_HPI, "HPI", "AHB-to-HPI bridge"}, - {GLEICHMANN_SPI, "SPI", "SPI master"}, - {GLEICHMANN_HIFC, "HIFC", "Human interface controller"}, - {GLEICHMANN_ADCDAC, "ADCDAC", "Sigma delta ADC/DAC"}, - {GLEICHMANN_SPIOC, "SPIOC", ""}, - {GLEICHMANN_AC97, "AC97", ""}, - {0, NULL, NULL} -}; - - -/** Vendor MENTA devices */ -static ambapp_device_name MENTA_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor SUN devices */ -static ambapp_device_name SUN_devices[] = { - {SUN_T1, "T1", "Niagara T1 SPARC V9 Processor"}, - {SUN_S1, "S1", "Niagara S1 SPARC V9 Processor"}, - {0, NULL, NULL} -}; - - -/** Vendor MOVIDIA devices */ -static ambapp_device_name MOVIDIA_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor ORBITA devices */ -static ambapp_device_name ORBITA_devices[] = { - {ORBITA_1553B, "1553B", "MIL-STD-1553B Controller"}, - {ORBITA_429, "429", "429 Interface"}, - {ORBITA_SPI, "SPI", "SPI Interface"}, - {ORBITA_I2C, "I2C", "I2C Interface"}, - {ORBITA_SMARTCARD, "SMARTCARD", "Smart Card Reader"}, - {ORBITA_SDCARD, "SDCARD", "SD Card Reader"}, - {ORBITA_UART16550, "UART16550", "16550 UART"}, - {ORBITA_CRYPTO, "CRYPTO", "Crypto Engine"}, - {ORBITA_SYSIF, "SYSIF", "System Interface"}, - {ORBITA_PIO, "PIO", "Programmable IO module"}, - {ORBITA_RTC, "RTC", "Real-Time Clock"}, - {ORBITA_COLORLCD, "COLORLCD", "Color LCD Controller"}, - {ORBITA_PCI, "PCI", "PCI Module"}, - {ORBITA_DSP, "DSP", "DPS Co-Processor"}, - {ORBITA_USBHOST, "USBHOST", "USB Host"}, - {ORBITA_USBDEV, "USBDEV", "USB Device"}, - {0, NULL, NULL} -}; - - -/** Vendor SYNOPSYS devices */ -static ambapp_device_name SYNOPSYS_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor NASA devices */ -static ambapp_device_name NASA_devices[] = { - {NASA_EP32, "EP32", "EP32 Forth processor"}, - {0, NULL, NULL} -}; - - -/** Vendor CAL devices */ -static ambapp_device_name CAL_devices[] = { - {CAL_DDRCTRL, "DDRCTRL", ""}, - {0, NULL, NULL} -}; - - -/** Vendor EMBEDDIT devices */ -static ambapp_device_name EMBEDDIT_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor CETON devices */ -static ambapp_device_name CETON_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor S3 devices */ -static ambapp_device_name S3_devices[] = { - {0, NULL, NULL} -}; - - -/** Vendor ACTEL devices */ -static ambapp_device_name ACTEL_devices[] = { - {ACTEL_COREMP7, "COREMP7", "CoreMP7 Processor"}, - {0, NULL, NULL} -}; - - -/** Vendor APPLECORE devices */ -static ambapp_device_name APPLECORE_devices[] = { - {APPLECORE_UTLEON3, "UTLEON3", "AppleCore uT-LEON3 Processor"}, - {APPLECORE_UTLEON3DSU, "UTLEON3DSU", "AppleCore uT-LEON3 DSU"}, - {0, NULL, NULL} -}; - - -/** Vendors and their devices */ -static ambapp_vendor_devnames vendors[] = { - {VENDOR_GAISLER, "GAISLER", "Gaisler Research", GAISLER_devices}, - {VENDOR_PENDER, "PENDER", "", PENDER_devices}, - {VENDOR_ESA, "ESA", "European Space Agency", ESA_devices}, - {VENDOR_ASTRIUM, "ASTRIUM", "", ASTRIUM_devices}, - {VENDOR_OPENCHIP, "OPENCHIP", "OpenChip", OPENCHIP_devices}, - {VENDOR_OPENCORES, "OPENCORES", "OpenCores", OPENCORES_devices}, - {VENDOR_CONTRIB, "CONTRIB", "Various contributions", CONTRIB_devices}, - {VENDOR_EONIC, "EONIC", "Eonic BV", EONIC_devices}, - {VENDOR_RADIONOR, "RADIONOR", "Radionor Communications", RADIONOR_devices}, - {VENDOR_GLEICHMANN, "GLEICHMANN", "Gleichmann Electronics", GLEICHMANN_devices}, - {VENDOR_MENTA, "MENTA", "Menta", MENTA_devices}, - {VENDOR_SUN, "SUN", "Sun Microsystems", SUN_devices}, - {VENDOR_MOVIDIA, "MOVIDIA", "", MOVIDIA_devices}, - {VENDOR_ORBITA, "ORBITA", "Orbita", ORBITA_devices}, - {VENDOR_SYNOPSYS, "SYNOPSYS", "Synopsys Inc.", SYNOPSYS_devices}, - {VENDOR_NASA, "NASA", "NASA", NASA_devices}, - {VENDOR_S3, "S3", "S3 Group", S3_devices}, - {VENDOR_CAL, "CAL", "", CAL_devices}, - {VENDOR_EMBEDDIT, "EMBEDDIT", "Embedd.it", EMBEDDIT_devices}, - {VENDOR_CETON, "CETON", "Ceton Corporation", CETON_devices}, - {VENDOR_ACTEL, "ACTEL", "Actel Corporation", ACTEL_devices}, - {VENDOR_APPLECORE, "APPLECORE", "AppleCore", APPLECORE_devices}, - {0, NULL, NULL, NULL} -}; - -static ambapp_device_name *ambapp_get_dev(ambapp_device_name *devs, int id) -{ - if (!devs) - return NULL; - - while (devs->device_id > 0) { - if (devs->device_id == id) - return devs; - devs++; - } - return NULL; -} - -char *ambapp_device_id2str(int vendor, int id) -{ - ambapp_vendor_devnames *ven = &vendors[0]; - ambapp_device_name *dev; - - while (ven->vendor_id > 0) { - if (ven->vendor_id == vendor) { - dev = ambapp_get_dev(ven->devices, id); - if (!dev) - return NULL; - return dev->name; - } - ven++; - } - return NULL; -} - -char *ambapp_device_id2desc(int vendor, int id) -{ - ambapp_vendor_devnames *ven = &vendors[0]; - ambapp_device_name *dev; - - while (ven->vendor_id > 0) { - if (ven->vendor_id == vendor) { - dev = ambapp_get_dev(ven->devices, id); - if (!dev) - return NULL; - return dev->desc; - } - ven++; - } - return NULL; -} - -char *ambapp_vendor_id2str(int vendor) -{ - ambapp_vendor_devnames *ven = &vendors[0]; - - while (ven->vendor_id > 0) { - if (ven->vendor_id == vendor) { - return ven->name; - } - ven++; - } - return NULL; -} - -static char *unknown = "unknown"; - -char *ambapp_type_names[4] = { - /* 0 */ "UNUSED", - /* 1 */ "apb", - /* 2 */ "ahbmem", - /* 3 */ "ahbio" -}; - -/* Print one APB device */ -void ambapp_print_apb(ambapp_apbdev *dev, int index) -{ - char *dev_str, *ven_str; - unsigned int freq; - - ven_str = ambapp_vendor_id2str(dev->vendor); - if (!ven_str) { - ven_str = unknown; - dev_str = unknown; - } else { - dev_str = ambapp_device_id2str(dev->vendor, dev->device); - if (!dev_str) - dev_str = unknown; - } - - /* Get Frequency of Core */ - freq = ambapp_bus_freq(&ambapp_plb, dev->ahb_bus_index); - - printf("0x%02x:0x%02x:0x%02x: %s %s (%dkHz)\n" - " apb: 0x%08x - 0x%08x\n" - " irq: %-2d (ver: %-2d)\n", - index, dev->vendor, dev->device, ven_str, dev_str, freq / 1000, - dev->address, dev->address + (dev->mask-1), - dev->irq, dev->ver); -} - -void ambapp_print_ahb(ambapp_ahbdev *dev, int index) -{ - char *dev_str, *ven_str, *type_str; - int i; - unsigned int freq; - - ven_str = ambapp_vendor_id2str(dev->vendor); - if (!ven_str) { - ven_str = unknown; - dev_str = unknown; - } else { - dev_str = ambapp_device_id2str(dev->vendor, dev->device); - if (!dev_str) - dev_str = unknown; - } - - /* Get Frequency of Core */ - freq = ambapp_bus_freq(&ambapp_plb, dev->ahb_bus_index); - - printf("0x%02x:0x%02x:0x%02x: %s %s (%dkHz)\n", - index, dev->vendor, dev->device, ven_str, dev_str, freq / 1000); - - for (i = 0; i < 4; i++) { - if (dev->type[i] == 0) - continue; - type_str = ambapp_type_names[dev->type[i]]; - printf(" %-7s: 0x%08x - 0x%08x\n", type_str, dev->address[i], - dev->address[i] + (dev->mask[i]-1)); - } - - printf(" irq: %-2d (ver: %d)\n", dev->irq, dev->ver); -} - -int do_ambapp_print(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - int index; - ambapp_apbdev apbdev; - ambapp_ahbdev ahbdev; - - /* Print AHB Masters */ - puts("\n--------- AHB Masters ---------\n"); - index = 0; - while (ambapp_ahbmst_find(&ambapp_plb, 0, 0, index, &ahbdev) == 1) { - /* Found a AHB Master Device */ - ambapp_print_ahb(&ahbdev, index); - index++; - } - - /* Print AHB Slaves */ - puts("\n--------- AHB Slaves ---------\n"); - index = 0; - while (ambapp_ahbslv_find(&ambapp_plb, 0, 0, index, &ahbdev) == 1) { - /* Found a AHB Slave Device */ - ambapp_print_ahb(&ahbdev, index); - index++; - } - - /* Print APB Slaves */ - puts("\n--------- APB Slaves ---------\n"); - index = 0; - while (ambapp_apb_find(&ambapp_plb, 0, 0, index, &apbdev) == 1) { - /* Found a APB Slave Device */ - ambapp_print_apb(&apbdev, index); - index++; - } - - puts("\n"); - return 0; -} - -int ambapp_init_reloc(void) -{ - ambapp_vendor_devnames *vend = vendors; - ambapp_device_name *dev; - - while (vend->vendor_id && vend->name) { - vend->name = (char *)((unsigned int)vend->name + gd->reloc_off); - vend->desc = (char *)((unsigned int)vend->desc + gd->reloc_off); - vend->devices = (ambapp_device_name *) - ((unsigned int)vend->devices + gd->reloc_off); - dev = vend->devices; - vend++; - if (!dev) - continue; - while (dev->device_id && dev->name) { - dev->name = - (char *)((unsigned int)dev->name + gd->reloc_off); - dev->desc = - (char *)((unsigned int)dev->desc + gd->reloc_off); - dev++; - } - } - return 0; -} - -U_BOOT_CMD( - ambapp, 1, 1, do_ambapp_print, - "list AMBA Plug&Play information", - "ambapp\n" - " - lists AMBA (AHB & APB) Plug&Play devices present on the system" -); diff --git a/cmd/cmd_armflash.c b/cmd/cmd_armflash.c deleted file mode 100644 index b94d128..0000000 --- a/cmd/cmd_armflash.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * (C) Copyright 2015 - * Linus Walleij, Linaro - * - * Support for ARM Flash Partitions - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include - -#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(cmd_tbl_t *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 \n" - " - returns 1 if an image exists, else 0\n" - "load \n" - " - load an image to the location indicated in the header\n" - "load 0x
\n" - " - load an image to the location specified\n"); diff --git a/cmd/cmd_bdinfo.c b/cmd/cmd_bdinfo.c deleted file mode 100644 index deed6d8..0000000 --- a/cmd/cmd_bdinfo.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * (C) Copyright 2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Boot support - */ -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -__maybe_unused -static void print_num(const char *name, ulong value) -{ - printf("%-12s= 0x%08lX\n", name, value); -} - -__maybe_unused -static void print_eth(int idx) -{ - char name[10], *val; - if (idx) - sprintf(name, "eth%iaddr", idx); - else - strcpy(name, "ethaddr"); - val = getenv(name); - if (!val) - val = "(not set)"; - printf("%-12s= %s\n", name, val); -} - -#ifndef CONFIG_DM_ETH -__maybe_unused -static void print_eths(void) -{ - struct eth_device *dev; - int i = 0; - - do { - dev = eth_get_dev_by_index(i); - if (dev) { - printf("eth%dname = %s\n", i, dev->name); - print_eth(i); - i++; - } - } while (dev); - - printf("current eth = %s\n", eth_get_name()); - printf("ip_addr = %s\n", getenv("ipaddr")); -} -#endif - -__maybe_unused -static void print_lnum(const char *name, unsigned long long value) -{ - printf("%-12s= 0x%.8llX\n", name, value); -} - -__maybe_unused -static void print_mhz(const char *name, unsigned long hz) -{ - char buf[32]; - - printf("%-12s= %6s MHz\n", name, strmhz(buf, hz)); -} - -#if defined(CONFIG_PPC) -void __weak board_detail(void) -{ - /* Please define boot_detail() for your platform */ -} - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - -#ifdef DEBUG - print_num("bd address", (ulong)bd); -#endif - print_num("memstart", bd->bi_memstart); - print_lnum("memsize", bd->bi_memsize); - print_num("flashstart", bd->bi_flashstart); - print_num("flashsize", bd->bi_flashsize); - print_num("flashoffset", bd->bi_flashoffset); - print_num("sramstart", bd->bi_sramstart); - print_num("sramsize", bd->bi_sramsize); -#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || \ - defined(CONFIG_MPC8260) || defined(CONFIG_E500) - print_num("immr_base", bd->bi_immr_base); -#endif - print_num("bootflags", bd->bi_bootflags); -#if defined(CONFIG_405EP) || \ - defined(CONFIG_405GP) || \ - defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ - defined(CONFIG_XILINX_405) - print_mhz("procfreq", bd->bi_procfreq); - print_mhz("plb_busfreq", bd->bi_plb_busfreq); -#if defined(CONFIG_405EP) || defined(CONFIG_405GP) || \ - defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ - defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \ - defined(CONFIG_440SPE) || defined(CONFIG_XILINX_405) - print_mhz("pci_busfreq", bd->bi_pci_busfreq); -#endif -#else /* ! CONFIG_405GP, CONFIG_405EP, CONFIG_XILINX_405, CONFIG_440EP CONFIG_440GR */ -#if defined(CONFIG_CPM2) - print_mhz("vco", bd->bi_vco); - print_mhz("sccfreq", bd->bi_sccfreq); - print_mhz("brgfreq", bd->bi_brgfreq); -#endif - print_mhz("intfreq", bd->bi_intfreq); -#if defined(CONFIG_CPM2) - print_mhz("cpmfreq", bd->bi_cpmfreq); -#endif - print_mhz("busfreq", bd->bi_busfreq); -#endif /* CONFIG_405GP, CONFIG_405EP, CONFIG_XILINX_405, CONFIG_440EP CONFIG_440GR */ - -#ifdef CONFIG_ENABLE_36BIT_PHYS -#ifdef CONFIG_PHYS_64BIT - puts("addressing = 36-bit\n"); -#else - puts("addressing = 32-bit\n"); -#endif -#endif - - print_eth(0); -#if defined(CONFIG_HAS_ETH1) - print_eth(1); -#endif -#if defined(CONFIG_HAS_ETH2) - print_eth(2); -#endif -#if defined(CONFIG_HAS_ETH3) - print_eth(3); -#endif -#if defined(CONFIG_HAS_ETH4) - print_eth(4); -#endif -#if defined(CONFIG_HAS_ETH5) - print_eth(5); -#endif - - printf("IP addr = %s\n", getenv("ipaddr")); - printf("baudrate = %6u bps\n", gd->baudrate); - print_num("relocaddr", gd->relocaddr); - board_detail(); - return 0; -} - -#elif defined(CONFIG_NIOS2) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int i; - bd_t *bd = gd->bd; - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { - print_num("DRAM bank", i); - print_num("-> start", bd->bi_dram[i].start); - print_num("-> size", bd->bi_dram[i].size); - } - - print_num("flash start", (ulong)bd->bi_flashstart); - print_num("flash size", (ulong)bd->bi_flashsize); - print_num("flash offset", (ulong)bd->bi_flashoffset); - -#if defined(CONFIG_SYS_SRAM_BASE) - print_num ("sram start", (ulong)bd->bi_sramstart); - print_num ("sram size", (ulong)bd->bi_sramsize); -#endif - -#if defined(CONFIG_CMD_NET) - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); -#endif - - printf("baudrate = %u bps\n", gd->baudrate); - - return 0; -} - -#elif defined(CONFIG_MICROBLAZE) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - int i; - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { - print_num("DRAM bank", i); - print_num("-> start", bd->bi_dram[i].start); - print_num("-> size", bd->bi_dram[i].size); - } - - print_num("flash start ", (ulong)bd->bi_flashstart); - print_num("flash size ", (ulong)bd->bi_flashsize); - print_num("flash offset ", (ulong)bd->bi_flashoffset); -#if defined(CONFIG_SYS_SRAM_BASE) - print_num("sram start ", (ulong)bd->bi_sramstart); - print_num("sram size ", (ulong)bd->bi_sramsize); -#endif -#if defined(CONFIG_CMD_NET) - print_eths(); -#endif - printf("baudrate = %u bps\n", gd->baudrate); - print_num("relocaddr", gd->relocaddr); - print_num("reloc off", gd->reloc_off); - print_num("fdt_blob", (ulong)gd->fdt_blob); - print_num("new_fdt", (ulong)gd->new_fdt); - print_num("fdt_size", (ulong)gd->fdt_size); - - return 0; -} - -#elif defined(CONFIG_SPARC) - -int do_bdinfo(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - -#ifdef DEBUG - print_num("bd address ", (ulong) bd); -#endif - print_num("memstart ", bd->bi_memstart); - print_lnum("memsize ", bd->bi_memsize); - print_num("flashstart ", bd->bi_flashstart); - print_num("CONFIG_SYS_MONITOR_BASE ", CONFIG_SYS_MONITOR_BASE); - print_num("CONFIG_ENV_ADDR ", CONFIG_ENV_ADDR); - printf("CONFIG_SYS_RELOC_MONITOR_BASE = 0x%x (%d)\n", CONFIG_SYS_RELOC_MONITOR_BASE, - CONFIG_SYS_MONITOR_LEN); - printf("CONFIG_SYS_MALLOC_BASE = 0x%x (%d)\n", CONFIG_SYS_MALLOC_BASE, - CONFIG_SYS_MALLOC_LEN); - printf("CONFIG_SYS_INIT_SP_OFFSET = 0x%x (%d)\n", CONFIG_SYS_INIT_SP_OFFSET, - CONFIG_SYS_STACK_SIZE); - printf("CONFIG_SYS_PROM_OFFSET = 0x%x (%d)\n", CONFIG_SYS_PROM_OFFSET, - CONFIG_SYS_PROM_SIZE); - printf("CONFIG_SYS_GBL_DATA_OFFSET = 0x%x (%d)\n", CONFIG_SYS_GBL_DATA_OFFSET, - GENERATED_GBL_DATA_SIZE); - -#if defined(CONFIG_CMD_NET) - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); -#endif - printf("baudrate = %6u bps\n", gd->baudrate); - return 0; -} - -#elif defined(CONFIG_M68K) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - - print_num("memstart", (ulong)bd->bi_memstart); - print_lnum("memsize", (u64)bd->bi_memsize); - print_num("flashstart", (ulong)bd->bi_flashstart); - print_num("flashsize", (ulong)bd->bi_flashsize); - print_num("flashoffset", (ulong)bd->bi_flashoffset); -#if defined(CONFIG_SYS_INIT_RAM_ADDR) - print_num("sramstart", (ulong)bd->bi_sramstart); - print_num("sramsize", (ulong)bd->bi_sramsize); -#endif -#if defined(CONFIG_SYS_MBAR) - print_num("mbar", bd->bi_mbar_base); -#endif - print_mhz("cpufreq", bd->bi_intfreq); - print_mhz("busfreq", bd->bi_busfreq); -#ifdef CONFIG_PCI - print_mhz("pcifreq", bd->bi_pcifreq); -#endif -#ifdef CONFIG_EXTRA_CLOCK - print_mhz("flbfreq", bd->bi_flbfreq); - print_mhz("inpfreq", bd->bi_inpfreq); - print_mhz("vcofreq", bd->bi_vcofreq); -#endif -#if defined(CONFIG_CMD_NET) - print_eth(0); -#if defined(CONFIG_HAS_ETH1) - print_eth(1); -#endif -#if defined(CONFIG_HAS_ETH2) - print_eth(2); -#endif -#if defined(CONFIG_HAS_ETH3) - print_eth(3); -#endif - - printf("ip_addr = %s\n", getenv("ipaddr")); -#endif - printf("baudrate = %u bps\n", gd->baudrate); - - return 0; -} - -#elif defined(CONFIG_BLACKFIN) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - - printf("U-Boot = %s\n", bd->bi_r_version); - printf("CPU = %s\n", bd->bi_cpu); - printf("Board = %s\n", bd->bi_board_name); - print_mhz("VCO", bd->bi_vco); - print_mhz("CCLK", bd->bi_cclk); - print_mhz("SCLK", bd->bi_sclk); - - print_num("boot_params", (ulong)bd->bi_boot_params); - print_num("memstart", (ulong)bd->bi_memstart); - print_lnum("memsize", (u64)bd->bi_memsize); - print_num("flashstart", (ulong)bd->bi_flashstart); - print_num("flashsize", (ulong)bd->bi_flashsize); - print_num("flashoffset", (ulong)bd->bi_flashoffset); - - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); - printf("baudrate = %u bps\n", gd->baudrate); - - return 0; -} - -#elif defined(CONFIG_MIPS) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - - print_num("boot_params", (ulong)bd->bi_boot_params); - print_num("memstart", (ulong)bd->bi_memstart); - print_lnum("memsize", (u64)bd->bi_memsize); - print_num("flashstart", (ulong)bd->bi_flashstart); - print_num("flashsize", (ulong)bd->bi_flashsize); - print_num("flashoffset", (ulong)bd->bi_flashoffset); - - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); - printf("baudrate = %u bps\n", gd->baudrate); - - return 0; -} - -#elif defined(CONFIG_AVR32) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - - print_num("boot_params", (ulong)bd->bi_boot_params); - print_num("memstart", (ulong)bd->bi_dram[0].start); - print_lnum("memsize", (u64)bd->bi_dram[0].size); - print_num("flashstart", (ulong)bd->bi_flashstart); - print_num("flashsize", (ulong)bd->bi_flashsize); - print_num("flashoffset", (ulong)bd->bi_flashoffset); - - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); - printf("baudrate = %u bps\n", gd->baudrate); - - return 0; -} - -#elif defined(CONFIG_ARM) - -static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - int i; - bd_t *bd = gd->bd; - - print_num("arch_number", bd->bi_arch_number); - print_num("boot_params", (ulong)bd->bi_boot_params); - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { - print_num("DRAM bank", i); - print_num("-> start", bd->bi_dram[i].start); - print_num("-> size", bd->bi_dram[i].size); - } - -#ifdef CONFIG_SYS_MEM_RESERVE_SECURE - if (gd->secure_ram & MEM_RESERVE_SECURE_SECURED) { - print_num("Secure ram", - gd->secure_ram & MEM_RESERVE_SECURE_ADDR_MASK); - } -#endif -#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH) - print_eths(); -#endif - printf("baudrate = %u bps\n", gd->baudrate); -#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) - print_num("TLB addr", gd->arch.tlb_addr); -#endif - print_num("relocaddr", gd->relocaddr); - print_num("reloc off", gd->reloc_off); - print_num("irq_sp", gd->irq_sp); /* irq stack pointer */ - print_num("sp start ", gd->start_addr_sp); -#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) - print_num("FB base ", gd->fb_base); -#endif - /* - * TODO: Currently only support for davinci SOC's is added. - * Remove this check once all the board implement this. - */ -#ifdef CONFIG_CLOCKS - printf("ARM frequency = %ld MHz\n", gd->bd->bi_arm_freq); - printf("DSP frequency = %ld MHz\n", gd->bd->bi_dsp_freq); - printf("DDR frequency = %ld MHz\n", gd->bd->bi_ddr_freq); -#endif -#ifdef CONFIG_BOARD_TYPES - printf("Board Type = %ld\n", gd->board_type); -#endif - return 0; -} - -#elif defined(CONFIG_SH) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - print_num("mem start ", (ulong)bd->bi_memstart); - print_lnum("mem size ", (u64)bd->bi_memsize); - print_num("flash start ", (ulong)bd->bi_flashstart); - print_num("flash size ", (ulong)bd->bi_flashsize); - print_num("flash offset ", (ulong)bd->bi_flashoffset); - -#if defined(CONFIG_CMD_NET) - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); -#endif - printf("baudrate = %u bps\n", gd->baudrate); - return 0; -} - -#elif defined(CONFIG_X86) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int i; - bd_t *bd = gd->bd; - - print_num("boot_params", (ulong)bd->bi_boot_params); - print_num("bi_memstart", bd->bi_memstart); - print_num("bi_memsize", bd->bi_memsize); - print_num("bi_flashstart", bd->bi_flashstart); - print_num("bi_flashsize", bd->bi_flashsize); - print_num("bi_flashoffset", bd->bi_flashoffset); - print_num("bi_sramstart", bd->bi_sramstart); - print_num("bi_sramsize", bd->bi_sramsize); - print_num("bi_bootflags", bd->bi_bootflags); - print_mhz("cpufreq", bd->bi_intfreq); - print_mhz("busfreq", bd->bi_busfreq); - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { - print_num("DRAM bank", i); - print_num("-> start", bd->bi_dram[i].start); - print_num("-> size", bd->bi_dram[i].size); - } - -#if defined(CONFIG_CMD_NET) - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); - print_mhz("ethspeed", bd->bi_ethspeed); -#endif - printf("baudrate = %u bps\n", gd->baudrate); - - return 0; -} - -#elif defined(CONFIG_SANDBOX) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int i; - bd_t *bd = gd->bd; - - print_num("boot_params", (ulong)bd->bi_boot_params); - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { - print_num("DRAM bank", i); - print_num("-> start", bd->bi_dram[i].start); - print_num("-> size", bd->bi_dram[i].size); - } - -#if defined(CONFIG_CMD_NET) - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); -#endif -#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) - print_num("FB base ", gd->fb_base); -#endif - return 0; -} - -#elif defined(CONFIG_NDS32) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int i; - bd_t *bd = gd->bd; - - print_num("arch_number", bd->bi_arch_number); - print_num("boot_params", (ulong)bd->bi_boot_params); - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) { - print_num("DRAM bank", i); - print_num("-> start", bd->bi_dram[i].start); - print_num("-> size", bd->bi_dram[i].size); - } - -#if defined(CONFIG_CMD_NET) - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); -#endif - printf("baudrate = %u bps\n", gd->baudrate); - - return 0; -} - -#elif defined(CONFIG_OPENRISC) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - - print_num("mem start", (ulong)bd->bi_memstart); - print_lnum("mem size", (u64)bd->bi_memsize); - print_num("flash start", (ulong)bd->bi_flashstart); - print_num("flash size", (ulong)bd->bi_flashsize); - print_num("flash offset", (ulong)bd->bi_flashoffset); - -#if defined(CONFIG_CMD_NET) - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); -#endif - - printf("baudrate = %u bps\n", gd->baudrate); - - return 0; -} - -#elif defined(CONFIG_ARC) - -int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bd_t *bd = gd->bd; - - print_num("mem start", bd->bi_memstart); - print_lnum("mem size", bd->bi_memsize); - -#if defined(CONFIG_CMD_NET) - print_eth(0); - printf("ip_addr = %s\n", getenv("ipaddr")); -#endif - printf("baudrate = %d bps\n", gd->baudrate); - - return 0; -} - -#else - #error "a case for this architecture does not exist!" -#endif - -/* -------------------------------------------------------------------- */ - -U_BOOT_CMD( - bdinfo, 1, 1, do_bdinfo, - "print Board Info structure", - "" -); diff --git a/cmd/cmd_bedbug.c b/cmd/cmd_bedbug.c deleted file mode 100644 index 69afeaf..0000000 --- a/cmd/cmd_bedbug.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * BedBug Functions - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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. - * ====================================================================== */ - -void bedbug_init (void) -{ - /* -------------------------------------------------- */ - -#if defined(CONFIG_4xx) - void bedbug405_init (void); - - bedbug405_init (); -#elif defined(CONFIG_8xx) - void bedbug860_init (void); - - bedbug860_init (); -#endif - -#if defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260) - /* Processors that are 603e core based */ - void bedbug603e_init (void); - - bedbug603e_init (); -#endif - - return; -} /* bedbug_init */ - - - -/* ====================================================================== - * Entry point from the interpreter to the disassembler. Repeated calls - * will resume from the last disassembled address. - * ====================================================================== */ -int do_bedbug_dis (cmd_tbl_t * 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
[# 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 (cmd_tbl_t * 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
"); - -/* ====================================================================== - * Used to set a break point from the interpreter. Simply calls into the - * CPU-specific break point set routine. - * ====================================================================== */ - -int do_bedbug_break (cmd_tbl_t * 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
- Break at an address\n" - "break off - 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 ("\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 (cmd_tbl_t * 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 (cmd_tbl_t * 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 (cmd_tbl_t * 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 (cmd_tbl_t * 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->bd->bi_memstart + gd->bd->bi_memsize; - 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 (cmd_tbl_t * 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/cmd/cmd_blob.c b/cmd/cmd_blob.c deleted file mode 100644 index ac8b268..0000000 --- a/cmd/cmd_blob.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Command for encapsulating/decapsulating blob of memory. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -/** - * 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(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - uint32_t 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 (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/cmd/cmd_bmp.c b/cmd/cmd_bmp.c deleted file mode 100644 index fd5b7db..0000000 --- a/cmd/cmd_bmp.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * (C) Copyright 2002 - * Detlev Zundel, DENX Software Engineering, dzu@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * BMP handling routines - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 *)((((unsigned int)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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - ulong addr; - - switch (argc) { - case 1: /* use load_addr as default address */ - addr = 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(cmd_tbl_t * 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 load_addr as default address */ - addr = load_addr; - break; - case 2: /* use argument */ - addr = simple_strtoul(argv[1], NULL, 16); - break; - case 4: - addr = simple_strtoul(argv[1], NULL, 16); - x = simple_strtoul(argv[2], NULL, 10); - y = simple_strtoul(argv[3], NULL, 10); - break; - default: - return CMD_RET_USAGE; - } - - return (bmp_display(addr, x, y)); -} - -static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *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 - display image info\n" - "bmp display [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(UCLASS_VIDEO, &dev); - if (!ret) { - if (!dev) - ret = -ENODEV; - if (!ret) { - bool align = false; - -# ifdef CONFIG_SPLASH_SCREEN_ALIGN - align = true; -# endif /* CONFIG_SPLASH_SCREEN_ALIGN */ - ret = video_bmp_display(dev, addr, x, y, align); - } - } - return ret ? CMD_RET_FAILURE : 0; -#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; -} diff --git a/cmd/cmd_boot.c b/cmd/cmd_boot.c deleted file mode 100644 index 72f2cf3..0000000 --- a/cmd/cmd_boot.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * (C) Copyright 2000-2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Misc boot support - */ -#include -#include -#include - -#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(cmd_tbl_t *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, 1, 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/cmd/cmd_bootldr.c b/cmd/cmd_bootldr.c deleted file mode 100644 index bc5c1f9..0000000 --- a/cmd/cmd_bootldr.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * U-boot - bootldr.c - * - * Copyright (c) 2005-2008 Analog Devices Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include - -#include -#include - -/* Simple sanity check on the specified address to make sure it contains - * an LDR image of some sort. - */ -static bool ldr_valid_signature(uint8_t *data) -{ -#if defined(__ADSPBF561__) - - /* BF56x has a 4 byte global header */ - if (data[3] == (GFLAG_56X_SIGN_MAGIC << (GFLAG_56X_SIGN_SHIFT - 24))) - return true; - -#elif defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ - defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ - defined(__ADSPBF538__) || defined(__ADSPBF539__) - - /* all the BF53x should start at this address mask */ - uint32_t addr; - memmove(&addr, data, sizeof(addr)); - if ((addr & 0xFF0FFF0F) == 0xFF000000) - return true; -#else - - /* everything newer has a magic byte */ - uint32_t count; - memmove(&count, data + 8, sizeof(count)); - if (data[3] == 0xAD && count == 0) - return true; - -#endif - - return false; -} - -/* If the Blackfin is new enough, the Blackfin on-chip ROM supports loading - * LDRs from random memory addresses. So whenever possible, use that. In - * the older cases (BF53x/BF561), parse the LDR format ourselves. - */ -static void ldr_load(uint8_t *base_addr) -{ -#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ - /*defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) ||*/\ - defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) - - uint32_t addr; - uint32_t count; - uint16_t flags; - - /* the bf56x has a 4 byte global header ... but it is useless to - * us when booting an LDR from a memory address, so skip it - */ -# ifdef __ADSPBF561__ - base_addr += 4; -# endif - - memmove(&flags, base_addr + 8, sizeof(flags)); - bfin_write_EVT1(flags & BFLAG_53X_RESVECT ? 0xFFA00000 : 0xFFA08000); - - do { - /* block header may not be aligned */ - memmove(&addr, base_addr, sizeof(addr)); - memmove(&count, base_addr+4, sizeof(count)); - memmove(&flags, base_addr+8, sizeof(flags)); - base_addr += sizeof(addr) + sizeof(count) + sizeof(flags); - - printf("loading to 0x%08x (%#x bytes) flags: 0x%04x\n", - addr, count, flags); - - if (!(flags & BFLAG_53X_IGNORE)) { - if (flags & BFLAG_53X_ZEROFILL) - memset((void *)addr, 0x00, count); - else - memcpy((void *)addr, base_addr, count); - - if (flags & BFLAG_53X_INIT) { - void (*init)(void) = (void *)addr; - init(); - } - } - - if (!(flags & BFLAG_53X_ZEROFILL)) - base_addr += count; - } while (!(flags & BFLAG_53X_FINAL)); - -#endif -} - -/* For BF537, we use the _BOOTROM_BOOT_DXE_FLASH funky ROM function. - * For all other BF53x/BF56x, we just call the entry point. - * For everything else (newer), we use _BOOTROM_MEMBOOT ROM function. - */ -static void ldr_exec(void *addr) -{ -#if defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) - - /* restore EVT1 to reset value as this is what the bootrom uses as - * the default entry point when booting the final block of LDRs - */ - bfin_write_EVT1(L1_INST_SRAM); - __asm__("call (%0);" : : "a"(_BOOTROM_MEMBOOT), "q7"(addr) : "RETS", "memory"); - -#elif defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ - defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) - - void (*ldr_entry)(void) = (void *)bfin_read_EVT1(); - ldr_entry(); - -#else - - int32_t (*BOOTROM_MEM)(void *, int32_t, int32_t, void *) = (void *)_BOOTROM_MEMBOOT; - BOOTROM_MEM(addr, 0, 0, NULL); - -#endif -} - -/* - * the bootldr command loads an address, checks to see if there - * is a Boot stream that the on-chip BOOTROM can understand, - * and loads it via the BOOTROM Callback. It is possible - * to also add booting from SPI, or TWI, but this function does - * not currently support that. - */ -int do_bootldr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - void *addr; - - /* Get the address */ - if (argc < 2) - addr = (void *)load_addr; - else - addr = (void *)simple_strtoul(argv[1], NULL, 16); - - /* Check if it is a LDR file */ - if (ldr_valid_signature(addr)) { - printf("## Booting ldr image at 0x%p ...\n", addr); - ldr_load(addr); - - icache_disable(); - dcache_disable(); - - ldr_exec(addr); - } else - printf("## No ldr image at address 0x%p\n", addr); - - return 0; -} - -U_BOOT_CMD( - bootldr, 2, 0, do_bootldr, - "boot ldr image from memory", - "[addr]\n" - "" -); diff --git a/cmd/cmd_bootm.c b/cmd/cmd_bootm.c deleted file mode 100644 index 48738ac..0000000 --- a/cmd/cmd_bootm.c +++ /dev/null @@ -1,775 +0,0 @@ -/* - * (C) Copyright 2000-2009 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Boot support - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#if defined(CONFIG_CMD_IMI) -static int image_info(unsigned long addr); -#endif - -#if defined(CONFIG_CMD_IMLS) -#include -#include -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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); -#endif - -bootm_headers_t images; /* pointers to os/initrd/fdt images */ - -/* we overload the cmd field with our state machine info instead of a - * function pointer */ -static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - int ret = 0; - long state; - cmd_tbl_t *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(cmd_tbl_t *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 | -#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(cmd_tbl_t *cmdtp, const char *cmd) -{ - const char *ep = getenv("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", 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 extened to include component or configuration unit name:\n" - "\taddr: - direct component image specification\n" - "\taddr# - 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_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - return run_command(getenv("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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int arg; - ulong addr; - int rcode = 0; - - if (argc < 2) { - return image_info(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 *)addr; - - printf("\n## Checking Image at %08lx ...\n", addr); - - switch (genimg_get_format(hdr)) { -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - case IMAGE_FORMAT_LEGACY: - puts(" Legacy image found\n"); - if (!image_check_magic(hdr)) { - puts(" Bad Magic Number\n"); - return 1; - } - - if (!image_check_hcrc(hdr)) { - puts(" Bad Header Checksum\n"); - return 1; - } - - image_print_contents(hdr); - - puts(" Verifying Checksum ... "); - if (!image_check_dcrc(hdr)) { - puts(" Bad Data CRC\n"); - return 1; - } - puts("OK\n"); - return 0; -#endif -#if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - puts(" FIT image found\n"); - - if (!fit_check_format(hdr)) { - puts("Bad FIT image format!\n"); - return 1; - } - - fit_print_contents(hdr); - - if (!fit_all_image_verify(hdr)) { - puts("Bad hash in FIT image!\n"); - return 1; - } - - return 0; -#endif - default: - puts("Unknown image format!\n"); - break; - } - - 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_IMAGE_FORMAT_LEGACY) - 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)) - 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(nand_info_t *nand, 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(nand, off, &len, - 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(nand_info_t *nand, 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(nand, off, &len, - imgdata); - if (ret < 0 && ret != -EUCLEAN) { - free(imgdata); - return ret; - } - - if (!fit_check_format(imgdata)) { - 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) -{ - nand_info_t *nand; - 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++) { - nand = &nand_info[nand_dev]; - if (!nand->name || !nand->size) - continue; - - for (off = 0; off < nand->size; off += nand->erasesize) { - const image_header_t *header; - int ret; - - if (nand_block_isbad(nand, off)) - continue; - - len = sizeof(buffer); - - ret = nand_read(nand, 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_IMAGE_FORMAT_LEGACY) - case IMAGE_FORMAT_LEGACY: - header = (const image_header_t *)buffer; - - len = image_get_image_size(header); - nand_imls_legacyimage(nand, nand_dev, off, len); - break; -#endif -#if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - len = fit_get_size(buffer); - nand_imls_fitimage(nand, nand_dev, off, len); - break; -#endif - } - } - } - - return 0; -} -#endif - -#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) -static int do_imls(cmd_tbl_t *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 - -#ifdef CONFIG_CMD_BOOTZ - -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(cmd_tbl_t *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 = load_addr; - debug("* kernel: default image load address = 0x%08lx\n", - 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)) - return 1; - - return 0; -} - -int do_bootz(cmd_tbl_t *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, - 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 -); -#endif /* CONFIG_CMD_BOOTZ */ - -#ifdef CONFIG_CMD_BOOTI -/* See Documentation/arm64/booting.txt in the Linux kernel */ -struct Image_header { - uint32_t code0; /* Executable code */ - uint32_t code1; /* Executable code */ - uint64_t text_offset; /* Image load offset, LE */ - uint64_t image_size; /* Effective Image size, LE */ - uint64_t res1; /* reserved */ - uint64_t res2; /* reserved */ - uint64_t res3; /* reserved */ - uint64_t res4; /* reserved */ - uint32_t magic; /* Magic number */ - uint32_t res5; -}; - -#define LINUX_ARM64_IMAGE_MAGIC 0x644d5241 - -static int booti_setup(bootm_headers_t *images) -{ - struct Image_header *ih; - uint64_t dst; - - ih = (struct Image_header *)map_sysmem(images->ep, 0); - - if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) { - puts("Bad Linux ARM64 Image magic!\n"); - return 1; - } - - if (ih->image_size == 0) { - puts("Image lacks image_size field, assuming 16MiB\n"); - ih->image_size = (16 << 20); - } - - /* - * If we are not at the correct run-time location, set the new - * correct location and then move the image there. - */ - dst = gd->bd->bi_dram[0].start + le32_to_cpu(ih->text_offset); - if (images->ep != dst) { - void *src; - - debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst); - - src = (void *)images->ep; - images->ep = dst; - memmove((void *)dst, src, le32_to_cpu(ih->image_size)); - } - - return 0; -} - -/* - * Image booting support - */ -static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[], bootm_headers_t *images) -{ - int ret; - struct Image_header *ih; - - ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START, - images, 1); - - /* Setup Linux kernel Image entry point */ - if (!argc) { - images->ep = load_addr; - debug("* kernel: default image load address = 0x%08lx\n", - load_addr); - } else { - images->ep = simple_strtoul(argv[0], NULL, 16); - debug("* kernel: cmdline image address = 0x%08lx\n", - images->ep); - } - - ret = booti_setup(images); - if (ret != 0) - return 1; - - ih = (struct Image_header *)map_sysmem(images->ep, 0); - - lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->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)) - return 1; - - return 0; -} - -int do_booti(cmd_tbl_t *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; - ret = do_bootm_states(cmdtp, flag, argc, argv, - 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 Image 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) - "\tSince booting a Linux kernelrequires 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.\n" -#endif - ""; -#endif - -U_BOOT_CMD( - booti, CONFIG_SYS_MAXARGS, 1, do_booti, - "boot arm64 Linux Image image from memory", booti_help_text -); -#endif /* CONFIG_CMD_BOOTI */ diff --git a/cmd/cmd_bootmenu.c b/cmd/cmd_bootmenu.c deleted file mode 100644 index 5879065..0000000 --- a/cmd/cmd_bootmenu.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * (C) Copyright 2011-2013 Pali Rohár - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include - -/* 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, -}; - -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 getenv(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 = getc(); - - switch (c) { - case '\e': - *esc = 1; - *key = KEY_NONE; - break; - case '\r': - *key = KEY_SELECT; - 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; - - while (!tstc()) { - WATCHDOG_RESET(); - mdelay(10); - } - - c = getc(); - - 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 { - *esc = 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; -} - -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; - 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; - struct bootmenu_entry *entry; - - menu = malloc(sizeof(struct bootmenu_data)); - if (!menu) - return NULL; - - menu->delay = delay; - menu->active = 0; - menu->first = NULL; - - 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; - return menu; - -cleanup: - bootmenu_destroy(menu); - return NULL; -} - -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, 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 -} - -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"); - puts(ANSI_CLEAR_LINE_TO_END); - printf(ANSI_CURSOR_POSITION, menu->count + 7, 1); - puts(ANSI_CLEAR_LINE); -} - -#ifdef CONFIG_MENU_SHOW -int menu_show(int bootdelay) -{ - bootmenu_show(bootdelay); - return -1; /* -1 - abort boot and run monitor code */ -} -#endif - -int do_bootmenu(cmd_tbl_t *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 = getenv("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/cmd/cmd_bootstage.c b/cmd/cmd_bootstage.c deleted file mode 100644 index 788ab16..0000000 --- a/cmd/cmd_bootstage.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2012, Google Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -static int do_bootstage_report(cmd_tbl_t *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(cmd_tbl_t *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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - cmd_tbl_t *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 [ []] - Stash data into memory\n" - "unstash [ []] - Unstash data from memory" -); diff --git a/cmd/cmd_cache.c b/cmd/cmd_cache.c deleted file mode 100644 index 37ab345..0000000 --- a/cmd/cmd_cache.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Cache support: switch on or off, get status - */ -#include -#include -#include - -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"); -} - -static int do_icache(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - switch (argc) { - case 2: /* on / off */ - switch (parse_argv(argv[1])) { - case 0: - icache_disable(); - break; - case 1: - icache_enable(); - break; - case 2: - invalidate_icache_all(); - break; - } - 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - switch (argc) { - case 2: /* on / off */ - switch (parse_argv(argv[1])) { - case 0: - dcache_disable(); - break; - case 1: - dcache_enable(); - break; - case 2: - flush_dcache_all(); - break; - } - 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/cmd/cmd_cbfs.c b/cmd/cmd_cbfs.c deleted file mode 100644 index 35d8a7a..0000000 --- a/cmd/cmd_cbfs.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * CBFS commands - */ -#include -#include -#include - -int do_cbfs_init(cmd_tbl_t *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 = (int)simple_strtoul(argv[1], &ep, 16); - if (*ep) { - puts("\n** Invalid end of ROM **\n"); - return 1; - } - } - file_cbfs_init(end_of_rom); - if (file_cbfs_result != CBFS_SUCCESS) { - 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" -); - -int do_cbfs_fsload(cmd_tbl_t *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 [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 (file_cbfs_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); - - setenv_hex("filesize", size); - - return 0; -} - -U_BOOT_CMD( - cbfsload, 4, 0, do_cbfs_fsload, - "load binary file from a cbfs filesystem", - " [bytes]\n" - " - load binary file 'filename' from the cbfs to address 'addr'\n" -); - -int do_cbfs_ls(cmd_tbl_t *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) { - u32 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_STAGE: - type_name = "stage"; - break; - case CBFS_TYPE_PAYLOAD: - type_name = "payload"; - 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_COMPONENT_CMOS_DEFAULT: - type_name = "cmos default"; - break; - case CBFS_COMPONENT_CMOS_LAYOUT: - type_name = "cmos layout"; - break; - case -1UL: - 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" -); - -int do_cbfs_fsinfo(cmd_tbl_t *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/cmd/cmd_clk.c b/cmd/cmd_clk.c deleted file mode 100644 index 6d3d46a..0000000 --- a/cmd/cmd_clk.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 Xilinx, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include - -int __weak soc_clk_dump(void) -{ - puts("Not implemented\n"); - return 1; -} - -static int do_clk_dump(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - return soc_clk_dump(); -} - -static cmd_tbl_t cmd_clk_sub[] = { - U_BOOT_CMD_MKENT(dump, 1, 1, do_clk_dump, "", ""), -}; - -static int do_clk(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - cmd_tbl_t *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/cmd/cmd_console.c b/cmd/cmd_console.c deleted file mode 100644 index 9a356ec..0000000 --- a/cmd/cmd_console.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Boot support - */ -#include -#include -#include - -extern void _do_coninfo (void); -static int do_coninfo(cmd_tbl_t *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/cmd/cmd_cplbinfo.c b/cmd/cmd_cplbinfo.c deleted file mode 100644 index ab5b3b5..0000000 --- a/cmd/cmd_cplbinfo.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * cmd_cplbinfo.c - dump the instruction/data cplb tables - * - * Copyright (c) 2007-2008 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include - -/* - * Translate the PAGE_SIZE bits into a human string - */ -static const char *cplb_page_size(uint32_t data) -{ - static const char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" }; - return page_size_string_table[(data & PAGE_SIZE_MASK) >> PAGE_SIZE_SHIFT]; -} - -/* - * show a hardware cplb table - */ -static void show_cplb_table(uint32_t *addr, uint32_t *data) -{ - int i; - printf(" Address Data Size Valid Locked\n"); - for (i = 1; i <= 16; ++i) { - printf(" %2i 0x%p 0x%05X %s %c %c\n", - i, (void *)*addr, *data, - cplb_page_size(*data), - (*data & CPLB_VALID ? 'Y' : 'N'), - (*data & CPLB_LOCK ? 'Y' : 'N')); - ++addr; - ++data; - } -} - -/* - * display current instruction and data cplb tables - */ -int do_cplbinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - printf("%s CPLB table [%08x]:\n", "Instruction", *(uint32_t *)DMEM_CONTROL); - show_cplb_table((uint32_t *)ICPLB_ADDR0, (uint32_t *)ICPLB_DATA0); - - printf("%s CPLB table [%08x]:\n", "Data", *(uint32_t *)IMEM_CONTROL); - show_cplb_table((uint32_t *)DCPLB_ADDR0, (uint32_t *)DCPLB_DATA0); - - return 0; -} - -U_BOOT_CMD( - cplbinfo, 1, 0, do_cplbinfo, - "display current CPLB tables", - "" -); diff --git a/cmd/cmd_cpu.c b/cmd/cmd_cpu.c deleted file mode 100644 index b4af64f..0000000 --- a/cmd/cmd_cpu.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2015 Google, Inc - * Written by Simon Glass - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -static const char *cpu_feature_name[CPU_FEAT_COUNT] = { - "L1 cache", - "MMU", -}; - -static int print_cpu_list(bool detail) -{ - struct udevice *dev; - struct uclass *uc; - char buf[100]; - int ret; - - ret = uclass_get(UCLASS_CPU, &uc); - if (ret) { - printf("Cannot find CPU uclass\n"); - return ret; - } - uclass_foreach_dev(dev, uc) { - struct cpu_platdata *plat = dev_get_parent_platdata(dev); - struct cpu_info info; - bool first; - int i; - - ret = cpu_get_desc(dev, buf, sizeof(buf)); - printf("%3d: %-10s %s\n", dev->seq, dev->name, - ret ? "" : buf); - if (!detail) - continue; - ret = cpu_get_info(dev, &info); - if (ret) { - printf("\t(no detail available"); - if (ret != -ENOSYS) - printf(": err=%d\n", ret); - printf(")\n"); - continue; - } - printf("\tID = %d, freq = ", plat->cpu_id); - print_freq(info.cpu_freq, ""); - first = true; - 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"); - } - - return 0; -} - -static int do_cpu_list(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - if (print_cpu_list(false)) - return CMD_RET_FAILURE; - - return 0; -} - -static int do_cpu_detail(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - if (print_cpu_list(true)) - return CMD_RET_FAILURE; - - return 0; -} - -static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - cmd_tbl_t *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/cmd/cmd_cramfs.c b/cmd/cmd_cramfs.c deleted file mode 100644 index 1d31326..0000000 --- a/cmd/cmd_cramfs.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0+ - * - * based on: cmd_jffs2.c - * - * Add support for a CRAMFS located in RAM - */ - - -/* - * CRAMFS support - */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* 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 - -#ifdef CONFIG_CRAMFS_CMDLINE -#include - -#ifdef CONFIG_SYS_NO_FLASH -# define OFFSET_ADJUSTMENT 0 -#else -# define OFFSET_ADJUSTMENT (flash_info[id.num].start[0]) -#endif - -#ifndef CONFIG_CMD_JFFS2 -#include -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_CMD_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *filename; - int size; - ulong offset = load_addr; - - struct part_info part; - struct mtd_device dev; - struct mtdids id; - - ulong addr; - addr = simple_strtoul(getenv("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 = addr - OFFSET_ADJUSTMENT; - - /* pre-set Boot file name */ - if ((filename = getenv("bootfile")) == NULL) { - filename = "uImage"; - } - - if (argc == 2) { - filename = argv[1]; - } - if (argc == 3) { - offset = simple_strtoul(argv[1], NULL, 0); - load_addr = offset; - filename = argv[2]; - } - - size = 0; - if (cramfs_check(&part)) - size = cramfs_load ((char *) offset, &part, filename); - - if (size > 0) { - printf("### CRAMFS load complete: %d bytes loaded to 0x%lx\n", - size, offset); - setenv_hex("filesize", size); - } else { - printf("### CRAMFS LOAD ERROR<%x> for %s!\n", size, filename); - } - - 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(cmd_tbl_t *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(getenv("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 = addr - OFFSET_ADJUSTMENT; - - if (argc == 2) - filename = argv[1]; - - ret = 0; - if (cramfs_check(&part)) - ret = cramfs_ls (&part, filename); - - 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" -); - -#endif /* #ifdef CONFIG_CRAMFS_CMDLINE */ - -/***************************************************/ diff --git a/cmd/cmd_dataflash_mmc_mux.c b/cmd/cmd_dataflash_mmc_mux.c deleted file mode 100644 index 3832248..0000000 --- a/cmd/cmd_dataflash_mmc_mux.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -static int mmc_nspi (const char *); - -int do_dataflash_mmc_mux (cmd_tbl_t *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/cmd/cmd_date.c b/cmd/cmd_date.c deleted file mode 100644 index 8714699..0000000 --- a/cmd/cmd_date.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * (C) Copyright 2001 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * RTC, Date & Time support: get and set date & time - */ -#include -#include -#include -#include -#include - -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(cmd_tbl_t *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++ = '\0'; - if ((len - (ptr - datestr)) != 2) - return (-1); - - len = strlen (datestr); - - 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, ¢ury) || - 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/cmd/cmd_dcr.c b/cmd/cmd_dcr.c deleted file mode 100644 index cc77250..0000000 --- a/cmd/cmd_dcr.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * (C) Copyright 2001 - * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * AMCC 4XX DCR Functions - */ - -#include -#include -#include -#include -#include - -unsigned long get_dcr (unsigned short); -unsigned long set_dcr (unsigned short, unsigned long); - -/* ======================================================================= - * Interpreter command to retrieve an AMCC PPC 4xx Device Control Register - * ======================================================================= - */ -int do_getdcr ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] ) -{ - unsigned short dcrn; /* Device Control Register Num */ - unsigned long value; /* DCR's value */ - - unsigned long get_dcr (unsigned short); - - /* Validate arguments */ - if (argc < 2) - return CMD_RET_USAGE; - - /* Get a DCR */ - dcrn = (unsigned short) simple_strtoul (argv[1], NULL, 16); - value = get_dcr (dcrn); - - printf ("%04x: %08lx\n", dcrn, value); - - return 0; -} - - -/* ====================================================================== - * Interpreter command to set an AMCC PPC 4xx Device Control Register - * ====================================================================== -*/ -int do_setdcr (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - unsigned short dcrn; /* Device Control Register Num */ - unsigned long value; - - /* DCR's value */ - int nbytes; - - /* Validate arguments */ - if (argc < 2) - return CMD_RET_USAGE; - - /* Set a DCR */ - dcrn = (unsigned short) simple_strtoul (argv[1], NULL, 16); - do { - value = get_dcr (dcrn); - printf ("%04x: %08lx", dcrn, value); - nbytes = cli_readline(" ? "); - if (nbytes == 0) { - /* - * pressed as only input, don't modify current - * location and exit command. - */ - nbytes = 1; - return 0; - } else { - unsigned long i; - char *endp; - - i = simple_strtoul (console_buffer, &endp, 16); - nbytes = endp - console_buffer; - if (nbytes) - set_dcr (dcrn, i); - } - } while (nbytes); - - return 0; -} - -/* ======================================================================= - * Interpreter command to retrieve an register value through AMCC PPC 4xx - * Device Control Register inderect addressing. - * ======================================================================= - */ -int do_getidcr (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unsigned short adr_dcrn; /* Device Control Register Num for Address */ - unsigned short dat_dcrn; /* Device Control Register Num for Data */ - unsigned short offset; /* Register's offset */ - unsigned long value; /* Register's value */ - char *ptr = NULL; - char buf[80]; - - /* Validate arguments */ - if (argc < 3) - return CMD_RET_USAGE; - - /* Find out whether ther is '.' (dot) symbol in the first parameter. */ - strncpy (buf, argv[1], sizeof(buf)-1); - buf[sizeof(buf)-1] = 0; /* will guarantee zero-end string */ - ptr = strchr (buf, '.'); - - if (ptr != NULL) { - /* First parameter has format adr_dcrn.dat_dcrn */ - *ptr++ = 0; /* erase '.', create zero-end string */ - adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16); - dat_dcrn = (unsigned short) simple_strtoul (ptr, NULL, 16); - } else { - /* - * First parameter has format adr_dcrn; dat_dcrn will be - * calculated as adr_dcrn+1. - */ - adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16); - dat_dcrn = adr_dcrn+1; - } - - /* Register's offset */ - offset = (unsigned short) simple_strtoul (argv[2], NULL, 16); - - /* Disable interrupts */ - disable_interrupts (); - /* Set offset */ - set_dcr (adr_dcrn, offset); - /* get data */ - value = get_dcr (dat_dcrn); - /* Enable interrupts */ - enable_interrupts (); - - printf ("%04x.%04x-%04x Read %08lx\n", adr_dcrn, dat_dcrn, offset, value); - - return 0; -} - -/* ======================================================================= - * Interpreter command to update an register value through AMCC PPC 4xx - * Device Control Register inderect addressing. - * ======================================================================= - */ -int do_setidcr (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - unsigned short adr_dcrn; /* Device Control Register Num for Address */ - unsigned short dat_dcrn; /* Device Control Register Num for Data */ - unsigned short offset; /* Register's offset */ - unsigned long value; /* Register's value */ - char *ptr = NULL; - char buf[80]; - - /* Validate arguments */ - if (argc < 4) - return CMD_RET_USAGE; - - /* Find out whether ther is '.' (dot) symbol in the first parameter. */ - strncpy (buf, argv[1], sizeof(buf)-1); - buf[sizeof(buf)-1] = 0; /* will guarantee zero-end string */ - ptr = strchr (buf, '.'); - - if (ptr != NULL) { - /* First parameter has format adr_dcrn.dat_dcrn */ - *ptr++ = 0; /* erase '.', create zero-end string */ - adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16); - dat_dcrn = (unsigned short) simple_strtoul (ptr, NULL, 16); - } else { - /* - * First parameter has format adr_dcrn; dat_dcrn will be - * calculated as adr_dcrn+1. - */ - adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16); - dat_dcrn = adr_dcrn+1; - } - - /* Register's offset */ - offset = (unsigned short) simple_strtoul (argv[2], NULL, 16); - /* New value */ - value = (unsigned long) simple_strtoul (argv[3], NULL, 16); - - /* Disable interrupts */ - disable_interrupts (); - /* Set offset */ - set_dcr (adr_dcrn, offset); - /* set data */ - set_dcr (dat_dcrn, value); - /* Enable interrupts */ - enable_interrupts (); - - printf ("%04x.%04x-%04x Write %08lx\n", adr_dcrn, dat_dcrn, offset, value); - - return 0; -} - -/***************************************************/ - -U_BOOT_CMD( - getdcr, 2, 1, do_getdcr, - "Get an AMCC PPC 4xx DCR's value", - "dcrn - return a DCR's value." -); -U_BOOT_CMD( - setdcr, 2, 1, do_setdcr, - "Set an AMCC PPC 4xx DCR's value", - "dcrn - set a DCR's value." -); - -U_BOOT_CMD( - getidcr, 3, 1, do_getidcr, - "Get a register value via indirect DCR addressing", - "adr_dcrn[.dat_dcrn] offset - write offset to adr_dcrn, read value from dat_dcrn." -); - -U_BOOT_CMD( - setidcr, 4, 1, do_setidcr, - "Set a register value via indirect DCR addressing", - "adr_dcrn[.dat_dcrn] offset value - write offset to adr_dcrn, write value to dat_dcrn." -); diff --git a/cmd/cmd_demo.c b/cmd/cmd_demo.c deleted file mode 100644 index 209dc4a..0000000 --- a/cmd/cmd_demo.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2013 Google, Inc - * - * (C) Copyright 2012 - * Pavel Herrmann - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -struct udevice *demo_dev; - -static int do_demo_hello(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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, platdata %08x\n", - i++, map_to_sysmem(dev), - map_to_sysmem(dev->driver->ops), - map_to_sysmem(dev_get_platdata(dev))); - } - - return cmd_process_error(cmdtp, ret); -} - -static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *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 [] Say hello\n" - "demo light [] Set or get the lights\n" - "demo status Get demo device status\n" - "demo list List available demo devices" -); diff --git a/cmd/cmd_dfu.c b/cmd/cmd_dfu.c deleted file mode 100644 index 6d95ce9..0000000 --- a/cmd/cmd_dfu.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * cmd_dfu.c -- dfu command - * - * Copyright (C) 2015 - * Lukasz Majewski - * - * Copyright (C) 2012 Samsung Electronics - * authors: Andrzej Pietrasiewicz - * Lukasz Majewski - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include - -static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - bool dfu_reset = false; - - if (argc < 4) - return CMD_RET_USAGE; - - char *usb_controller = argv[1]; - char *interface = argv[2]; - char *devstring = argv[3]; - - int ret, i = 0; -#ifdef CONFIG_DFU_TFTP - unsigned long addr = 0; - if (!strcmp(argv[1], "tftp")) { - if (argc == 5) - addr = simple_strtoul(argv[4], NULL, 0); - - return update_tftp(addr, interface, devstring); - } -#endif - - ret = dfu_init_env_entities(interface, devstring); - if (ret) - goto done; - - ret = CMD_RET_SUCCESS; - if (argc > 4 && strcmp(argv[4], "list") == 0) { - dfu_show_entities(); - goto done; - } - - int controller_index = simple_strtoul(usb_controller, NULL, 0); - board_usb_init(controller_index, USB_INIT_DEVICE); - g_dnl_clear_detach(); - g_dnl_register("usb_dnl_dfu"); - while (1) { - if (g_dnl_detach()) { - /* - * Check if USB bus reset is performed after detach, - * which indicates that -R switch has been passed to - * dfu-util. In this case reboot the device - */ - if (dfu_usb_get_reset()) { - dfu_reset = true; - goto exit; - } - - /* - * This extra number of usb_gadget_handle_interrupts() - * calls is necessary to assure correct transmission - * completion with dfu-util - */ - if (++i == 10000) - goto exit; - } - - if (ctrlc()) - goto exit; - - WATCHDOG_RESET(); - usb_gadget_handle_interrupts(controller_index); - } -exit: - g_dnl_unregister(); - board_usb_cleanup(controller_index, USB_INIT_DEVICE); -done: - dfu_free_entities(); - - if (dfu_reset) - run_command("reset", 0); - - g_dnl_clear_detach(); - - return ret; -} - -U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, - "Device Firmware Upgrade", - " [list]\n" - " - device firmware upgrade via \n" - " on device , attached to interface\n" - " \n" - " [list] - list available alt settings\n" -#ifdef CONFIG_DFU_TFTP - "dfu tftp []\n" - " - device firmware upgrade via TFTP\n" - " on device , attached to interface\n" - " \n" - " [] - address where FIT image has been stored\n" -#endif -); diff --git a/cmd/cmd_diag.c b/cmd/cmd_diag.c deleted file mode 100644 index 14ae04f..0000000 --- a/cmd/cmd_diag.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * (C) Copyright 2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Diagnostics support - */ -#include -#include -#include - -int do_diag (cmd_tbl_t * 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 [ [ ...]]'" - " to get more info.\n"); - puts ("Use 'diag run [ [ ...]]'" - " 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/cmd/cmd_disk.c b/cmd/cmd_disk.c deleted file mode 100644 index 3025225..0000000 --- a/cmd/cmd_disk.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * (C) Copyright 2000-2011 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include - -#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \ - defined(CONFIG_USB_STORAGE) -int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, - char *const argv[]) -{ - int dev, part; - ulong addr = CONFIG_SYS_LOAD_ADDR; - ulong cnt; - disk_partition_t info; -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - image_header_t *hdr; -#endif - block_dev_desc_t *dev_desc; - -#if defined(CONFIG_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 = get_device_and_partition(intf, (argc == 3) ? argv[2] : NULL, - &dev_desc, &info, 1); - if (part < 0) { - bootstage_error(BOOTSTAGE_ID_IDE_TYPE); - return 1; - } - - dev = dev_desc->dev; - 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 (dev_desc->block_read(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_IMAGE_FORMAT_LEGACY) - 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 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_IDE_FORMAT); - puts("** Unknown image type\n"); - return 1; - } - - cnt += info.blksz - 1; - cnt /= info.blksz; - cnt -= 1; - - if (dev_desc->block_read(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 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)) { - bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ); - puts("** Bad FIT image format\n"); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK); - fit_print_contents(fit_hdr); - } -#endif - - flush_cache(addr, (cnt+1)*info.blksz); - - /* Loading ok, update default load address */ - load_addr = addr; - - return bootm_maybe_autostart(cmdtp, argv[0]); -} -#endif diff --git a/cmd/cmd_display.c b/cmd/cmd_display.c deleted file mode 100644 index bc1b1eb..0000000 --- a/cmd/cmd_display.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * (C) Copyright 2005 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#undef DEBUG_DISP - -int do_display (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int i; - - /* Clear display */ - display_set(DISPLAY_CLEAR | DISPLAY_HOME); - - if (argc < 2) - return (0); - - for (i = 1; i < argc; i++) { - char *p = argv[i]; - - if (i > 1) { /* Insert a space between strings */ - display_putc(' '); - } - - while ((*p)) { -#ifdef DEBUG_DISP - putc(*p); -#endif - display_putc(*p++); - } - } - -#ifdef DEBUG_DISP - putc('\n'); -#endif - - return (0); -} - -/***************************************************/ - -U_BOOT_CMD( - display, CONFIG_SYS_MAXARGS, 1, do_display, - "display string on dot matrix display", - "[]\n" - " - with argument: display on dot matrix display\n" - " - without arguments: clear dot matrix display" -); diff --git a/cmd/cmd_dtt.c b/cmd/cmd_dtt.c deleted file mode 100644 index f2e750f..0000000 --- a/cmd/cmd_dtt.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * (C) Copyright 2001 - * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#include -#include -#include - -#if defined CONFIG_DTT_SENSORS -static unsigned long sensor_initialized; - -static void _initialize_dtt(void) -{ - int i; - unsigned char sensors[] = CONFIG_DTT_SENSORS; - - for (i = 0; i < sizeof(sensors); i++) { - if ((sensor_initialized & (1 << i)) == 0) { - if (dtt_init_one(sensors[i]) != 0) { - printf("DTT%d: Failed init!\n", i); - continue; - } - sensor_initialized |= (1 << i); - } - } -} - -void dtt_init(void) -{ - int old_bus; - - /* switch to correct I2C bus */ - old_bus = I2C_GET_BUS(); - I2C_SET_BUS(CONFIG_SYS_DTT_BUS_NUM); - - _initialize_dtt(); - - /* switch back to original I2C bus */ - I2C_SET_BUS(old_bus); -} -#endif - -int dtt_i2c(void) -{ -#if defined CONFIG_DTT_SENSORS - int i; - unsigned char sensors[] = CONFIG_DTT_SENSORS; - int old_bus; - - /* Force a compilation error, if there are more then 32 sensors */ - BUILD_BUG_ON(sizeof(sensors) > 32); - /* switch to correct I2C bus */ -#ifdef CONFIG_SYS_I2C - old_bus = i2c_get_bus_num(); - i2c_set_bus_num(CONFIG_SYS_DTT_BUS_NUM); -#else - old_bus = I2C_GET_BUS(); - I2C_SET_BUS(CONFIG_SYS_DTT_BUS_NUM); -#endif - - _initialize_dtt(); - - /* - * Loop through sensors, read - * temperature, and output it. - */ - for (i = 0; i < sizeof(sensors); i++) - printf("DTT%d: %i C\n", i + 1, dtt_get_temp(sensors[i])); - - /* switch back to original I2C bus */ -#ifdef CONFIG_SYS_I2C - i2c_set_bus_num(old_bus); -#else - I2C_SET_BUS(old_bus); -#endif -#endif - - return 0; -} - -int dtt_tmu(void) -{ -#if defined CONFIG_TMU_CMD_DTT - int cur_temp; - - /* Sense and return latest thermal info */ - if (tmu_monitor(&cur_temp) == TMU_STATUS_INIT) { - puts("TMU is in unknown state, temperature is invalid\n"); - return -1; - } - printf("Current temperature: %u degrees Celsius\n", cur_temp); -#endif - return 0; -} - -int do_dtt(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - int err = 0; - - err |= dtt_i2c(); - err |= dtt_tmu(); - - return err; -} /* do_dtt() */ - -/***************************************************/ - -U_BOOT_CMD( - dtt, 1, 1, do_dtt, - "Read temperature from Digital Thermometer and Thermostat", - "" -); diff --git a/cmd/cmd_echo.c b/cmd/cmd_echo.c deleted file mode 100644 index 3dc3a63..0000000 --- a/cmd/cmd_echo.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2000-2009 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -static int do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int i; - int putnl = 1; - - for (i = 1; i < argc; i++) { - char *p = argv[i]; - char *nls; /* new-line suppression */ - - if (i > 1) - putc(' '); - - nls = strstr(p, "\\c"); - if (nls) { - char *prenls = p; - - putnl = 0; - /* - * be paranoid and guess that someone might - * say \c more than once - */ - while (nls) { - *nls = '\0'; - puts(prenls); - *nls = '\\'; - prenls = nls + 2; - nls = strstr(prenls, "\\c"); - } - puts(prenls); - } else { - puts(p); - } - } - - if (putnl) - putc('\n'); - - return 0; -} - -U_BOOT_CMD( - echo, CONFIG_SYS_MAXARGS, 1, do_echo, - "echo args to console", - "[args..]\n" - " - echo args to console; \\c suppresses newline" -); diff --git a/cmd/cmd_eeprom.c b/cmd/cmd_eeprom.c deleted file mode 100644 index 571240a..0000000 --- a/cmd/cmd_eeprom.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * (C) Copyright 2000, 2001 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * 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 -#include -#include -#include - -#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 - -#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 - -__weak int eeprom_write_enable(unsigned dev_addr, int state) -{ - return 0; -} - -void eeprom_init(int bus) -{ - /* SPI EEPROM */ -#if defined(CONFIG_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) - spi_init_f(); -#endif - - /* I2C EEPROM */ -#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C_SOFT) -#if defined(CONFIG_SYS_I2C) - if (bus >= 0) - i2c_set_bus_num(bus); -#endif - 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 ccessed 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; - - /* SPI */ -#if defined(CONFIG_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) - if (read) - spi_read(addr, alen, buffer, len); - else - spi_write(addr, alen, buffer, len); -#else /* I2C */ - -#if defined(CONFIG_SYS_I2C_EEPROM_BUS) - i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS); -#endif - - if (read) - ret = i2c_read(addr[0], offset, alen - 1, buffer, len); - else - ret = i2c_write(addr[0], offset, alen - 1, buffer, len); - - if (ret) - ret = 1; -#endif - 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]; - - 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 do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - const char *const fmt = - "\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... "; - char * const *args = &argv[2]; - int rcode; - ulong dev_addr, addr, off, cnt; - int bus_addr; - - switch (argc) { -#ifdef CONFIG_SYS_DEF_EEPROM_ADDR - case 5: - bus_addr = -1; - dev_addr = CONFIG_SYS_DEF_EEPROM_ADDR; - break; -#endif - case 6: - bus_addr = -1; - dev_addr = simple_strtoul(*args++, NULL, 16); - break; - case 7: - bus_addr = simple_strtoul(*args++, NULL, 16); - dev_addr = simple_strtoul(*args++, NULL, 16); - break; - default: - return CMD_RET_USAGE; - } - - addr = simple_strtoul(*args++, NULL, 16); - off = simple_strtoul(*args++, NULL, 16); - cnt = simple_strtoul(*args++, NULL, 16); - - eeprom_init(bus_addr); - - if (strcmp(argv[1], "read") == 0) { - printf(fmt, dev_addr, argv[1], addr, off, cnt); - - rcode = eeprom_read(dev_addr, off, (uchar *)addr, cnt); - - puts("done\n"); - return rcode; - } else if (strcmp(argv[1], "write") == 0) { - printf(fmt, dev_addr, argv[1], addr, off, cnt); - - rcode = eeprom_write(dev_addr, off, (uchar *)addr, cnt); - - puts("done\n"); - return rcode; - } - - return CMD_RET_USAGE; -} - -U_BOOT_CMD( - eeprom, 7, 1, do_eeprom, - "EEPROM sub-system", - "read addr off cnt\n" - "eeprom write addr off cnt\n" - " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'" -) diff --git a/cmd/cmd_efi.c b/cmd/cmd_efi.c deleted file mode 100644 index c76296e..0000000 --- a/cmd/cmd_efi.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * (C) Copyright 2015 Google, Inc - * Written by Simon Glass - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -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 { - int shift; - const char *name; -} mem_attr[] = { - { EFI_MEMORY_UC_SHIFT, "uncached" }, - { EFI_MEMORY_WC_SHIFT, "write-coalescing" }, - { EFI_MEMORY_WT_SHIFT, "write-through" }, - { EFI_MEMORY_WB_SHIFT, "write-back" }, - { EFI_MEMORY_UCE_SHIFT, "uncached & exported" }, - { EFI_MEMORY_WP_SHIFT, "write-protect" }, - { EFI_MEMORY_RP_SHIFT, "read-protect" }, - { EFI_MEMORY_XP_SHIFT, "execute-protect" }, - { EFI_MEMORY_RUNTIME_SHIFT, "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; -} - -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 = base + count; - for (desc = base; desc < end; desc = efi_get_next_mem_desc(map, desc)) { - bool merge = true; - int type = desc->type; - - 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_TABLE_END; - - 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_TABLE_END; - 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", "", - addr, "", desc->physical_start - addr); - } - size = desc->num_pages << EFI_PAGE_SHIFT; - - name = desc->type < ARRAY_SIZE(type_name) ? - type_name[desc->type] : ""; - 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 & (1ULL << mem_attr[j].shift)) { - 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(cmd_tbl_t *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 cmd_tbl_t efi_commands[] = { - U_BOOT_CMD_MKENT(mem, 1, 1, do_efi_mem, "", ""), -}; - -static int do_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *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/cmd/cmd_elf.c b/cmd/cmd_elf.c deleted file mode 100644 index 5190cc6..0000000 --- a/cmd/cmd_elf.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include -#include -#include -#ifdef CONFIG_X86 -#include -#include -#endif - -/* - * A very simple elf loader, assumes the image is valid, returns the - * entry point address. - */ -static unsigned long load_elf_image_phdr(unsigned long addr) -{ - Elf32_Ehdr *ehdr; /* Elf header structure pointer */ - Elf32_Phdr *phdr; /* Program header structure pointer */ - int i; - - ehdr = (Elf32_Ehdr *)addr; - phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); - - /* Load each program header */ - for (i = 0; i < ehdr->e_phnum; ++i) { - void *dst = (void *)(uintptr_t)phdr->p_paddr; - void *src = (void *)addr + phdr->p_offset; - debug("Loading phdr %i to 0x%p (%i bytes)\n", - i, dst, phdr->p_filesz); - if (phdr->p_filesz) - memcpy(dst, src, phdr->p_filesz); - if (phdr->p_filesz != phdr->p_memsz) - memset(dst + phdr->p_filesz, 0x00, - phdr->p_memsz - phdr->p_filesz); - flush_cache((unsigned long)dst, phdr->p_filesz); - ++phdr; - } - - return ehdr->e_entry; -} - -static unsigned long load_elf_image_shdr(unsigned long addr) -{ - Elf32_Ehdr *ehdr; /* Elf header structure pointer */ - Elf32_Shdr *shdr; /* Section header structure pointer */ - unsigned char *strtab = 0; /* String table pointer */ - unsigned char *image; /* Binary image pointer */ - int i; /* Loop counter */ - - ehdr = (Elf32_Ehdr *)addr; - - /* Find the section header string table for output info */ - shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + - (ehdr->e_shstrndx * sizeof(Elf32_Shdr))); - - if (shdr->sh_type == SHT_STRTAB) - strtab = (unsigned char *)(addr + shdr->sh_offset); - - /* Load each appropriate section */ - for (i = 0; i < ehdr->e_shnum; ++i) { - shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + - (i * sizeof(Elf32_Shdr))); - - if (!(shdr->sh_flags & SHF_ALLOC) || - shdr->sh_addr == 0 || shdr->sh_size == 0) { - continue; - } - - if (strtab) { - debug("%sing %s @ 0x%08lx (%ld bytes)\n", - (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", - &strtab[shdr->sh_name], - (unsigned long)shdr->sh_addr, - (long)shdr->sh_size); - } - - if (shdr->sh_type == SHT_NOBITS) { - memset((void *)(uintptr_t)shdr->sh_addr, 0, - shdr->sh_size); - } else { - image = (unsigned char *)addr + shdr->sh_offset; - memcpy((void *)(uintptr_t)shdr->sh_addr, - (const void *)image, shdr->sh_size); - } - flush_cache(shdr->sh_addr, shdr->sh_size); - } - - return ehdr->e_entry; -} - -/* 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; - - /* - * QNX images require the data cache is disabled. - * Data cache is already flushed, so just turn it off. - */ - int dcache = dcache_status(); - if (dcache) - dcache_disable(); - - /* - * pass address parameter as argv[0] (aka command name), - * and all remaining args - */ - ret = entry(argc, argv); - - if (dcache) - dcache_enable(); - - return ret; -} - -/* - * Determine if a valid ELF image exists at the given memory location. - * First look at the ELF header magic field, then make sure that it is - * executable. - */ -int valid_elf_image(unsigned long addr) -{ - Elf32_Ehdr *ehdr; /* Elf header structure pointer */ - - ehdr = (Elf32_Ehdr *)addr; - - if (!IS_ELF(*ehdr)) { - printf("## No elf image at address 0x%08lx\n", addr); - return 0; - } - - if (ehdr->e_type != ET_EXEC) { - printf("## Not a 32-bit elf image at address 0x%08lx\n", addr); - return 0; - } - - return 1; -} - -/* Interpreter command to boot an arbitrary ELF image from memory */ -int do_bootelf(cmd_tbl_t *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, *saddr; - const char *ep = getenv("autostart"); - - int rcode = 0; - - sload = saddr = NULL; - if (argc == 3) { - sload = argv[1]; - saddr = argv[2]; - } else if (argc == 2) { - if (argv[1][0] == '-') - sload = argv[1]; - else - saddr = argv[1]; - } - - if (saddr) - addr = simple_strtoul(saddr, NULL, 16); - else - addr = 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 - 1, argv + 1); - 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unsigned long addr; /* Address of image */ - unsigned long bootaddr; /* 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 - struct e820info *info; - struct e820entry *data; -#endif - - /* - * Check the loadaddr variable. - * If we don't know where the image is then we're done. - */ - if (argc < 2) - addr = 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_WALNUT) - tmp = (char *)CONFIG_SYS_NVRAM_BASE_ADDR + 0x500; - eth_getenv_enetaddr("ethaddr", (uchar *)build_buf); - memcpy(tmp, &build_buf[3], 3); -#elif defined(CONFIG_SYS_VXWORKS_MAC_PTR) - tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR; - eth_getenv_enetaddr("ethaddr", (uchar *)build_buf); - memcpy(tmp, build_buf, 6); -#else - puts("## Ethernet MAC address not copied to NV RAM\n"); -#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 = getenv("bootaddr"); - if (!tmp) { - printf("## VxWorks bootline address not specified\n"); - } else { - 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 = getenv("bootargs"); - if (bootline) { - memcpy((void *)bootaddr, bootline, - max(strlen(bootline), (size_t)255)); - flush_cache(bootaddr, max(strlen(bootline), - (size_t)255)); - } else { - tmp = getenv("bootdev"); - if (tmp) { - strcpy(build_buf, tmp); - ptr = strlen(tmp); - } else - printf("## VxWorks boot device not specified\n"); - - tmp = getenv("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 = getenv("ipaddr"); - if (tmp) { - ptr += sprintf(build_buf + ptr, "e=%s", tmp); - tmp = getenv("netmask"); - if (tmp) { - u32 mask = getenv_ip("netmask").s_addr; - ptr += sprintf(build_buf + ptr, - ":%08x ", ntohl(mask)); - } else { - ptr += sprintf(build_buf + ptr, " "); - } - } - - tmp = getenv("serverip"); - if (tmp) - ptr += sprintf(build_buf + ptr, "h=%s ", tmp); - - tmp = getenv("gatewayip"); - if (tmp) - ptr += sprintf(build_buf + ptr, "g=%s ", tmp); - - tmp = getenv("hostname"); - if (tmp) - ptr += sprintf(build_buf + ptr, "tn=%s ", tmp); - - tmp = getenv("othbootargs"); - if (tmp) { - strcpy(build_buf + ptr, tmp); - ptr += strlen(tmp); - } - - memcpy((void *)bootaddr, build_buf, - max(strlen(build_buf), (size_t)255)); - flush_cache(bootaddr, max(strlen(build_buf), - (size_t)255)); - } - - printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, - (char *)bootaddr); - } - -#ifdef CONFIG_X86 - /* - * Since E820 information is critical to the kernel, if we don't - * specify these in the environments, use a default one. - */ - tmp = getenv("e820data"); - if (tmp) - data = (struct e820entry *)simple_strtoul(tmp, NULL, 16); - else - data = (struct e820entry *)VXWORKS_E820_DATA_ADDR; - tmp = getenv("e820info"); - if (tmp) - info = (struct e820info *)simple_strtoul(tmp, NULL, 16); - else - info = (struct e820info *)VXWORKS_E820_INFO_ADDR; - - memset(info, 0, sizeof(struct e820info)); - info->sign = E820_SIGNATURE; - info->entries = install_e820_map(E820MAX, data); - info->addr = (info->entries - 1) * sizeof(struct e820entry) + - VXWORKS_E820_DATA_ADDR; -#endif - - /* - * 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_shdr(addr); - else - puts("## Not an ELF image, assuming binary\n"); - - printf("## Starting vxWorks at 0x%08lx ...\n", addr); - - dcache_disable(); -#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, 3, 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/cmd/cmd_ethsw.c b/cmd/cmd_ethsw.c deleted file mode 100644 index 8e452e9..0000000 --- a/cmd/cmd_ethsw.c +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * Copyright 2015 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Ethernet Switch commands - */ - -#include -#include -#include -#include -#include - -static const char *ethsw_name; - -#define ETHSW_PORT_STATS_HELP "ethsw [port ] 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 ] 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 ] [vlan ] fdb " \ -"{ [help] | show | flush | { add | del } } " \ -"- Add/delete a mac entry in FDB; use show to see FDB entries; " \ -"if vlan 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 ] " \ -"pvid { [help] | show | } " \ -"- 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 ] vlan " \ -"{ [help] | show | add | del } " \ -"- 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 ] untagged " \ -"{ [help] | show | all | none | pvid } " \ -" - set egress tagging mod 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 ] 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 ] 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; -} - -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 = ðsw_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 = ðsw_learn_help_key_func, - }, { - .cmd_keyword = { - ethsw_id_learning, - ethsw_id_help, - ethsw_id_key_end, - }, - .cmd_func_offset = -1, - .keyword_function = ðsw_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 = ðsw_fdb_help_key_func, - }, { - .cmd_keyword = { - ethsw_id_fdb, - ethsw_id_help, - ethsw_id_key_end, - }, - .cmd_func_offset = -1, - .keyword_function = ðsw_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 = ðsw_pvid_help_key_func, - }, { - .cmd_keyword = { - ethsw_id_pvid, - ethsw_id_help, - ethsw_id_key_end, - }, - .cmd_func_offset = -1, - .keyword_function = ðsw_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 = ðsw_vlan_help_key_func, - }, { - .cmd_keyword = { - ethsw_id_vlan, - ethsw_id_help, - ethsw_id_key_end, - }, - .cmd_func_offset = -1, - .keyword_function = ðsw_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 = ðsw_port_untag_help_key_func, - }, { - .cmd_keyword = { - ethsw_id_untagged, - ethsw_id_help, - ethsw_id_key_end, - }, - .cmd_func_offset = -1, - .keyword_function = ðsw_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 = ðsw_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 = ðsw_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 = ðsw_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 = ðsw_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 = ðsw_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 = ðsw_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, - }, -}; - -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); - -/* - * 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, - }, -}; - -/* - * 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; - } - - eth_parse_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; -} - -/* 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(ethsw_cmd_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 = ðsw_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->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(cmd_tbl_t *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 ] { enable | disable | show } " \ -"- enable/disable a port; show shows 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" -); diff --git a/cmd/cmd_exit.c b/cmd/cmd_exit.c deleted file mode 100644 index c789233..0000000 --- a/cmd/cmd_exit.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2000-2009 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -static int do_exit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int r; - - r = 0; - if (argc > 1) - r = simple_strtoul(argv[1], NULL, 10); - - return -r - 2; -} - -U_BOOT_CMD( - exit, 2, 1, do_exit, - "exit script", - "" -); diff --git a/cmd/cmd_ext2.c b/cmd/cmd_ext2.c deleted file mode 100644 index 6657ef5..0000000 --- a/cmd/cmd_ext2.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * (C) Copyright 2011 - 2012 Samsung Electronics - * EXT4 filesystem implementation in Uboot by - * Uma Shankar - * Manjunatha C Achar - - * (C) Copyright 2004 - * esd gmbh - * Reinhard Arlt - * - * made from cmd_reiserfs by - * - * (C) Copyright 2003 - 2004 - * Sysgo Real-Time Solutions, AG - * Pavel Bartusek - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Ext2fs support - */ -#include - -static int do_ext2ls(cmd_tbl_t *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(cmd_tbl_t *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 /)", - " [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", - " [ [addr [filename [bytes [pos]]]]]\n" - " - load binary file 'filename' from 'dev' on 'interface'\n" - " to address 'addr' from ext2 filesystem." -) diff --git a/cmd/cmd_ext4.c b/cmd/cmd_ext4.c deleted file mode 100644 index 19423d1..0000000 --- a/cmd/cmd_ext4.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * (C) Copyright 2011 - 2012 Samsung Electronics - * EXT4 filesystem implementation in Uboot by - * Uma Shankar - * Manjunatha C Achar - * - * Ext4fs support - * made from existing cmd_ext2.c file of Uboot - * - * (C) Copyright 2004 - * esd gmbh - * Reinhard Arlt - * - * made from cmd_reiserfs by - * - * (C) Copyright 2003 - 2004 - * Sysgo Real-Time Solutions, AG - * Pavel Bartusek - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) -#include -#endif - -int do_ext4_size(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - return do_size(cmdtp, flag, argc, argv, FS_TYPE_EXT); -} - -int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - return do_load(cmdtp, flag, argc, argv, FS_TYPE_EXT); -} - -int do_ext4_ls(cmd_tbl_t *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(cmd_tbl_t *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", - " \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", - " \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 /)", - " [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", - " [ [addr [filename [bytes [pos]]]]]\n" - " - load binary file 'filename' from 'dev' on 'interface'\n" - " to address 'addr' from ext4 filesystem"); diff --git a/cmd/cmd_fastboot.c b/cmd/cmd_fastboot.c deleted file mode 100644 index 488822a..0000000 --- a/cmd/cmd_fastboot.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2008 - 2009 Windriver, - * Author: Tom Rix - * - * (C) Copyright 2014 Linaro, Ltd. - * Rob Herring - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include - -static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - int controller_index; - char *usb_controller; - int ret; - - if (argc < 2) - return CMD_RET_USAGE; - - usb_controller = argv[1]; - controller_index = simple_strtoul(usb_controller, NULL, 0); - - ret = board_usb_init(controller_index, USB_INIT_DEVICE); - if (ret) { - error("USB init failed: %d", 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; - usb_gadget_handle_interrupts(controller_index); - } - - ret = CMD_RET_SUCCESS; - -exit: - g_dnl_unregister(); - g_dnl_clear_detach(); - board_usb_cleanup(controller_index, USB_INIT_DEVICE); - - return ret; -} - -U_BOOT_CMD( - fastboot, 2, 1, do_fastboot, - "use USB Fastboot protocol", - "\n" - " - run as a fastboot usb device" -); diff --git a/cmd/cmd_fat.c b/cmd/cmd_fat.c deleted file mode 100644 index aae993d..0000000 --- a/cmd/cmd_fat.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * (C) Copyright 2002 - * Richard Jones, rjones@nexus-tech.net - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Boot support - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int do_fat_size(cmd_tbl_t *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", - " \n" - " - Find file 'filename' from 'dev' on 'interface'\n" - " and determine its size." -); - -int do_fat_fsload (cmd_tbl_t *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", - " [ [ [ [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(cmd_tbl_t *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 /)", - " [] [directory]\n" - " - list files from 'dev' on 'interface' in a 'directory'" -); - -static int do_fat_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - int dev, part; - block_dev_desc_t *dev_desc; - disk_partition_t info; - - if (argc < 2) { - printf("usage: fatinfo []\n"); - return 0; - } - - part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); - if (part < 0) - return 1; - - dev = dev_desc->dev; - 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", - " []\n" - " - print information about filesystem from 'dev' on 'interface'" -); - -#ifdef CONFIG_FAT_WRITE -static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - loff_t size; - int ret; - unsigned long addr; - unsigned long count; - block_dev_desc_t *dev_desc = NULL; - disk_partition_t info; - int dev = 0; - int part = 1; - void *buf; - - if (argc < 5) - return cmd_usage(cmdtp); - - part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); - if (part < 0) - return 1; - - dev = dev_desc->dev; - - if (fat_set_blk_dev(dev_desc, &info) != 0) { - printf("\n** Unable to use %s %d:%d for fatwrite **\n", - argv[1], dev, part); - return 1; - } - addr = simple_strtoul(argv[3], NULL, 16); - count = simple_strtoul(argv[5], NULL, 16); - - buf = map_sysmem(addr, count); - ret = file_fat_write(argv[4], buf, 0, count, &size); - unmap_sysmem(buf); - if (ret < 0) { - printf("\n** Unable to write \"%s\" from %s %d:%d **\n", - argv[4], argv[1], dev, part); - return 1; - } - - printf("%llu bytes written\n", size); - - return 0; -} - -U_BOOT_CMD( - fatwrite, 6, 0, do_fat_fswrite, - "write file into a dos filesystem", - " \n" - " - write file 'filename' from the address 'addr' in RAM\n" - " to 'dev' on 'interface'" -); -#endif diff --git a/cmd/cmd_fdc.c b/cmd/cmd_fdc.c deleted file mode 100644 index 5766b56..0000000 --- a/cmd/cmd_fdc.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * (C) Copyright 2001 - * Denis Peter, MPL AG, d.peter@mpl.ch. - * - * SPDX-License-Identifier: GPL-2.0+ - */ -/* - * Floppy Disk support - */ - -#include -#include -#include -#include - - -#undef FDC_DEBUG - -#ifdef FDC_DEBUG -#define PRINTF(fmt,args...) printf (fmt ,##args) -#else -#define PRINTF(fmt,args...) -#endif - -/*#if defined(CONFIG_CMD_DATE) */ -/*#include */ -/*#endif */ - -typedef struct { - int flags; /* connected drives ect */ - unsigned long blnr; /* Logical block nr */ - uchar drive; /* drive no */ - uchar cmdlen; /* cmd length */ - uchar cmd[16]; /* cmd desc */ - uchar dma; /* if > 0 dma enabled */ - uchar result[11]; /* status information */ - uchar resultlen; /* lenght of result */ -} FDC_COMMAND_STRUCT; - -/* flags: only the lower 8bit used: - * bit 0 if set drive 0 is present - * bit 1 if set drive 1 is present - * bit 2 if set drive 2 is present - * bit 3 if set drive 3 is present - * bit 4 if set disk in drive 0 is inserted - * bit 5 if set disk in drive 1 is inserted - * bit 6 if set disk in drive 2 is inserted - * bit 7 if set disk in drive 4 is inserted - */ - -/* cmd indexes */ -#define COMMAND 0 -#define DRIVE 1 -#define CONFIG0 1 -#define SPEC_HUTSRT 1 -#define TRACK 2 -#define CONFIG1 2 -#define SPEC_HLT 2 -#define HEAD 3 -#define CONFIG2 3 -#define SECTOR 4 -#define SECTOR_SIZE 5 -#define LAST_TRACK 6 -#define GAP 7 -#define DTL 8 -/* result indexes */ -#define STATUS_0 0 -#define STATUS_PCN 1 -#define STATUS_1 1 -#define STATUS_2 2 -#define STATUS_TRACK 3 -#define STATUS_HEAD 4 -#define STATUS_SECT 5 -#define STATUS_SECT_SIZE 6 - - -/* Register addresses */ -#define FDC_BASE 0x3F0 -#define FDC_SRA FDC_BASE + 0 /* Status Register A */ -#define FDC_SRB FDC_BASE + 1 /* Status Register B */ -#define FDC_DOR FDC_BASE + 2 /* Digital Output Register */ -#define FDC_TDR FDC_BASE + 3 /* Tape Drive Register */ -#define FDC_DSR FDC_BASE + 4 /* Data rate Register */ -#define FDC_MSR FDC_BASE + 4 /* Main Status Register */ -#define FDC_FIFO FDC_BASE + 5 /* FIFO */ -#define FDC_DIR FDC_BASE + 6 /* Digital Input Register */ -#define FDC_CCR FDC_BASE + 7 /* Configuration Control */ -/* Commands */ -#define FDC_CMD_SENSE_INT 0x08 -#define FDC_CMD_CONFIGURE 0x13 -#define FDC_CMD_SPECIFY 0x03 -#define FDC_CMD_RECALIBRATE 0x07 -#define FDC_CMD_READ 0x06 -#define FDC_CMD_READ_TRACK 0x02 -#define FDC_CMD_READ_ID 0x0A -#define FDC_CMD_DUMP_REG 0x0E -#define FDC_CMD_SEEK 0x0F - -#define FDC_CMD_SENSE_INT_LEN 0x01 -#define FDC_CMD_CONFIGURE_LEN 0x04 -#define FDC_CMD_SPECIFY_LEN 0x03 -#define FDC_CMD_RECALIBRATE_LEN 0x02 -#define FDC_CMD_READ_LEN 0x09 -#define FDC_CMD_READ_TRACK_LEN 0x09 -#define FDC_CMD_READ_ID_LEN 0x02 -#define FDC_CMD_DUMP_REG_LEN 0x01 -#define FDC_CMD_SEEK_LEN 0x03 - -#define FDC_FIFO_THR 0x0C -#define FDC_FIFO_DIS 0x00 -#define FDC_IMPLIED_SEEK 0x01 -#define FDC_POLL_DIS 0x00 -#define FDC_PRE_TRK 0x00 -#define FDC_CONFIGURE FDC_FIFO_THR | (FDC_POLL_DIS<<4) | (FDC_FIFO_DIS<<5) | (FDC_IMPLIED_SEEK << 6) -#define FDC_MFM_MODE 0x01 /* MFM enable */ -#define FDC_SKIP_MODE 0x00 /* skip enable */ - -#define FDC_TIME_OUT 100000 /* time out */ -#define FDC_RW_RETRIES 3 /* read write retries */ -#define FDC_CAL_RETRIES 3 /* calibration and seek retries */ - - -/* Disk structure */ -typedef struct { - unsigned int size; /* nr of sectors total */ - unsigned int sect; /* sectors per track */ - unsigned int head; /* nr of heads */ - unsigned int track; /* nr of tracks */ - unsigned int stretch; /* !=0 means double track steps */ - unsigned char gap; /* gap1 size */ - unsigned char rate; /* data rate. |= 0x40 for perpendicular */ - unsigned char spec1; /* stepping rate, head unload time */ - unsigned char fmt_gap;/* gap2 size */ - unsigned char hlt; /* head load time */ - unsigned char sect_code;/* Sector Size code */ - const char * name; /* used only for predefined formats */ -} FD_GEO_STRUCT; - - -/* supported Floppy types (currently only one) */ -const static FD_GEO_STRUCT floppy_type[2] = { - { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,16,2,"H1440" }, /* 7 1.44MB 3.5" */ - { 0, 0,0, 0,0,0x00,0x00,0x00,0x00, 0,0,NULL }, /* end of table */ -}; - -static FDC_COMMAND_STRUCT cmd; /* global command struct */ - -/* If the boot drive number is undefined, we assume it's drive 0 */ -#ifndef CONFIG_SYS_FDC_DRIVE_NUMBER -#define CONFIG_SYS_FDC_DRIVE_NUMBER 0 -#endif - -/* Hardware access */ -#ifndef CONFIG_SYS_ISA_IO_STRIDE -#define CONFIG_SYS_ISA_IO_STRIDE 1 -#endif - -#ifndef CONFIG_SYS_ISA_IO_OFFSET -#define CONFIG_SYS_ISA_IO_OFFSET 0 -#endif - -/* Supporting Functions */ -/* reads a Register of the FDC */ -unsigned char read_fdc_reg(unsigned int addr) -{ - volatile unsigned char *val = - (volatile unsigned char *)(CONFIG_SYS_ISA_IO_BASE_ADDRESS + - (addr * CONFIG_SYS_ISA_IO_STRIDE) + - CONFIG_SYS_ISA_IO_OFFSET); - - return val [0]; -} - -/* writes a Register of the FDC */ -void write_fdc_reg(unsigned int addr, unsigned char val) -{ - volatile unsigned char *tmp = - (volatile unsigned char *)(CONFIG_SYS_ISA_IO_BASE_ADDRESS + - (addr * CONFIG_SYS_ISA_IO_STRIDE) + - CONFIG_SYS_ISA_IO_OFFSET); - tmp[0]=val; -} - -/* waits for an interrupt (polling) */ -int wait_for_fdc_int(void) -{ - unsigned long timeout; - timeout = FDC_TIME_OUT; - while((read_fdc_reg(FDC_SRA)&0x80)==0) { - timeout--; - udelay(10); - if(timeout==0) /* timeout occured */ - return false; - } - return true; -} - -/* reads a byte from the FIFO of the FDC and checks direction and RQM bit - of the MSR. returns -1 if timeout, or byte if ok */ -int read_fdc_byte(void) -{ - unsigned long timeout; - timeout = FDC_TIME_OUT; - while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) { - /* direction out and ready */ - udelay(10); - timeout--; - if(timeout==0) /* timeout occured */ - return -1; - } - return read_fdc_reg(FDC_FIFO); -} - -/* if the direction of the FIFO is wrong, this routine is used to - empty the FIFO. Should _not_ be used */ -int fdc_need_more_output(void) -{ - unsigned char c; - while((read_fdc_reg(FDC_MSR)&0xC0)==0xC0) { - c=(unsigned char)read_fdc_byte(); - printf("Error: more output: %x\n",c); - } - return true; -} - - -/* writes a byte to the FIFO of the FDC and checks direction and RQM bit - of the MSR */ -int write_fdc_byte(unsigned char val) -{ - unsigned long timeout; - timeout = FDC_TIME_OUT; - while((read_fdc_reg(FDC_MSR)&0xC0)!=0x80) { - /* direction in and ready for byte */ - timeout--; - udelay(10); - fdc_need_more_output(); - if(timeout==0) /* timeout occured */ - return false; - } - write_fdc_reg(FDC_FIFO,val); - return true; -} - -/* sets up all FDC commands and issues it to the FDC. If - the command causes direct results (no Execution Phase) - the result is be read as well. */ - -int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG) -{ - int i; - unsigned long head,track,sect,timeout; - track = pCMD->blnr / (pFG->sect * pFG->head); /* track nr */ - sect = pCMD->blnr % (pFG->sect * pFG->head); /* remaining blocks */ - head = sect / pFG->sect; /* head nr */ - sect = sect % pFG->sect; /* remaining blocks */ - sect++; /* sectors are 1 based */ - PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n", - pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr); - - if(head|=0) { /* max heads = 2 */ - pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */ - pCMD->cmd[HEAD]=(unsigned char) head; /* head register */ - } - else { - pCMD->cmd[DRIVE]=pCMD->drive; /* head 0 */ - pCMD->cmd[HEAD]=(unsigned char) head; /* head register */ - } - pCMD->cmd[TRACK]=(unsigned char) track; /* track */ - switch (pCMD->cmd[COMMAND]) { - case FDC_CMD_READ: - pCMD->cmd[SECTOR]=(unsigned char) sect; /* sector */ - pCMD->cmd[SECTOR_SIZE]=pFG->sect_code; /* sector size code */ - pCMD->cmd[LAST_TRACK]=pFG->sect; /* End of track */ - pCMD->cmd[GAP]=pFG->gap; /* gap */ - pCMD->cmd[DTL]=0xFF; /* DTL */ - pCMD->cmdlen=FDC_CMD_READ_LEN; - pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */ - pCMD->cmd[COMMAND]|=(FDC_SKIP_MODE<<5); /* set Skip bit */ - pCMD->resultlen=0; /* result only after execution */ - break; - case FDC_CMD_SEEK: - pCMD->cmdlen=FDC_CMD_SEEK_LEN; - pCMD->resultlen=0; /* no result */ - break; - case FDC_CMD_CONFIGURE: - pCMD->cmd[CONFIG0]=0; - pCMD->cmd[CONFIG1]=FDC_CONFIGURE; /* FIFO Threshold, Poll, Enable FIFO */ - pCMD->cmd[CONFIG2]=FDC_PRE_TRK; /* Precompensation Track */ - pCMD->cmdlen=FDC_CMD_CONFIGURE_LEN; - pCMD->resultlen=0; /* no result */ - break; - case FDC_CMD_SPECIFY: - pCMD->cmd[SPEC_HUTSRT]=pFG->spec1; - pCMD->cmd[SPEC_HLT]=(pFG->hlt)<<1; /* head load time */ - if(pCMD->dma==0) - pCMD->cmd[SPEC_HLT]|=0x1; /* no dma */ - pCMD->cmdlen=FDC_CMD_SPECIFY_LEN; - pCMD->resultlen=0; /* no result */ - break; - case FDC_CMD_DUMP_REG: - pCMD->cmdlen=FDC_CMD_DUMP_REG_LEN; - pCMD->resultlen=10; /* 10 byte result */ - break; - case FDC_CMD_READ_ID: - pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */ - pCMD->cmdlen=FDC_CMD_READ_ID_LEN; - pCMD->resultlen=7; /* 7 byte result */ - break; - case FDC_CMD_RECALIBRATE: - pCMD->cmd[DRIVE]&=0x03; /* don't set the head bit */ - pCMD->cmdlen=FDC_CMD_RECALIBRATE_LEN; - pCMD->resultlen=0; /* no result */ - break; - break; - case FDC_CMD_SENSE_INT: - pCMD->cmdlen=FDC_CMD_SENSE_INT_LEN; - pCMD->resultlen=2; - break; - } - for(i=0;icmdlen;i++) { - /* PRINTF("write cmd%d = 0x%02X\n",i,pCMD->cmd[i]); */ - if (write_fdc_byte(pCMD->cmd[i]) == false) { - PRINTF("Error: timeout while issue cmd%d\n",i); - return false; - } - } - timeout=FDC_TIME_OUT; - for(i=0;iresultlen;i++) { - while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) { - timeout--; - if(timeout==0) { - PRINTF(" timeout while reading result%d MSR=0x%02X\n",i,read_fdc_reg(FDC_MSR)); - return false; - } - } - pCMD->result[i]=(unsigned char)read_fdc_byte(); - } - return true; -} - -/* selects the drive assigned in the cmd structur and - switches on the Motor */ -void select_fdc_drive(FDC_COMMAND_STRUCT *pCMD) -{ - unsigned char val; - - val=(1<<(4+pCMD->drive))|pCMD->drive|0xC; /* set reset, dma gate and motor bits */ - if((read_fdc_reg(FDC_DOR)&val)!=val) { - write_fdc_reg(FDC_DOR,val); - for(val=0;val<255;val++) - udelay(500); /* wait some time to start motor */ - } -} - -/* switches off the Motor of the specified drive */ -void stop_fdc_drive(FDC_COMMAND_STRUCT *pCMD) -{ - unsigned char val; - - val=(1<<(4+pCMD->drive))|pCMD->drive; /* sets motor bits */ - write_fdc_reg(FDC_DOR,(read_fdc_reg(FDC_DOR)&~val)); -} - -/* issues a recalibrate command, waits for interrupt and - * issues a sense_interrupt */ -int fdc_recalibrate(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG) -{ - pCMD->cmd[COMMAND]=FDC_CMD_RECALIBRATE; - if (fdc_issue_cmd(pCMD, pFG) == false) - return false; - while (wait_for_fdc_int() != true); - - pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT; - return(fdc_issue_cmd(pCMD,pFG)); -} - -/* issues a recalibrate command, waits for interrupt and - * issues a sense_interrupt */ -int fdc_seek(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG) -{ - pCMD->cmd[COMMAND]=FDC_CMD_SEEK; - if (fdc_issue_cmd(pCMD, pFG) == false) - return false; - while (wait_for_fdc_int() != true); - - pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT; - return(fdc_issue_cmd(pCMD,pFG)); -} - -/* terminates current command, by not servicing the FIFO - * waits for interrupt and fills in the result bytes */ -int fdc_terminate(FDC_COMMAND_STRUCT *pCMD) -{ - int i; - for(i=0;i<100;i++) - udelay(500); /* wait 500usec for fifo overrun */ - while((read_fdc_reg(FDC_SRA)&0x80)==0x00); /* wait as long as no int has occured */ - for(i=0;i<7;i++) { - pCMD->result[i]=(unsigned char)read_fdc_byte(); - } - return true; -} - -/* reads data from FDC, seek commands are issued automatic */ -int fdc_read_data(unsigned char *buffer, unsigned long blocks,FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG) -{ - /* first seek to start address */ - unsigned long len,readblk,i,timeout,ii,offset; - unsigned char c,retriesrw,retriescal; - unsigned char *bufferw; /* working buffer */ - int sect_size; - int flags; - - flags=disable_interrupts(); /* switch off all Interrupts */ - select_fdc_drive(pCMD); /* switch on drive */ - sect_size=0x080<sect_code; - retriesrw=0; - retriescal=0; - offset=0; - if (fdc_seek(pCMD, pFG) == false) { - stop_fdc_drive(pCMD); - if (flags) - enable_interrupts(); - return false; - } - if((pCMD->result[STATUS_0]&0x20)!=0x20) { - printf("Seek error Status: %02X\n",pCMD->result[STATUS_0]); - stop_fdc_drive(pCMD); - if (flags) - enable_interrupts(); - return false; - } - /* now determine the next seek point */ - /* lastblk=pCMD->blnr + blocks; */ - /* readblk=(pFG->head*pFG->sect)-(pCMD->blnr%(pFG->head*pFG->sect)); */ - readblk=pFG->sect-(pCMD->blnr%pFG->sect); - PRINTF("1st nr of block possible read %ld start %ld\n",readblk,pCMD->blnr); - if(readblk>blocks) /* is end within 1st track */ - readblk=blocks; /* yes, correct it */ - PRINTF("we read %ld blocks start %ld\n",readblk,pCMD->blnr); - bufferw = &buffer[0]; /* setup working buffer */ - do { -retryrw: - len=sect_size * readblk; - pCMD->cmd[COMMAND]=FDC_CMD_READ; - if (fdc_issue_cmd(pCMD, pFG) == false) { - stop_fdc_drive(pCMD); - if (flags) - enable_interrupts(); - return false; - } - for (i=0;i6) { - for(ii=0;ii<7;ii++) { - pCMD->result[ii]=bufferw[(i-7+ii)]; - } /* for */ - } - if(retriesrw++>FDC_RW_RETRIES) { - if (retriescal++>FDC_CAL_RETRIES) { - stop_fdc_drive(pCMD); - if (flags) - enable_interrupts(); - return false; - } - else { - PRINTF(" trying to recalibrate Try %d\n",retriescal); - if (fdc_recalibrate(pCMD, pFG) == false) { - stop_fdc_drive(pCMD); - if (flags) - enable_interrupts(); - return false; - } - retriesrw=0; - goto retrycal; - } /* else >FDC_CAL_RETRIES */ - } - else { - PRINTF("Read retry %d\n",retriesrw); - goto retryrw; - } /* else >FDC_RW_RETRIES */ - }/* if output */ - timeout--; - } while (true); - } /* for len */ - /* the last sector of a track or all data has been read, - * we need to get the results */ - fdc_terminate(pCMD); - offset+=(sect_size*readblk); /* set up buffer pointer */ - bufferw = &buffer[offset]; - pCMD->blnr+=readblk; /* update current block nr */ - blocks-=readblk; /* update blocks */ - if(blocks==0) - break; /* we are finish */ - /* setup new read blocks */ - /* readblk=pFG->head*pFG->sect; */ - readblk=pFG->sect; - if(readblk>blocks) - readblk=blocks; -retrycal: - /* a seek is necessary */ - if (fdc_seek(pCMD, pFG) == false) { - stop_fdc_drive(pCMD); - if (flags) - enable_interrupts(); - return false; - } - if((pCMD->result[STATUS_0]&0x20)!=0x20) { - PRINTF("Seek error Status: %02X\n",pCMD->result[STATUS_0]); - stop_fdc_drive(pCMD); - return false; - } - } while (true); /* start over */ - stop_fdc_drive(pCMD); /* switch off drive */ - if (flags) - enable_interrupts(); - return true; -} - -/* Scan all drives and check if drive is present and disk is inserted */ -int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG) -{ - int i,drives,state; - /* OK procedure of data book is satisfied. - * trying to get some information over the drives */ - state=0; /* no drives, no disks */ - for(drives=0;drives<4;drives++) { - pCMD->drive=drives; - select_fdc_drive(pCMD); - pCMD->blnr=0; /* set to the 1st block */ - if (fdc_recalibrate(pCMD, pFG) == false) - continue; - if((pCMD->result[STATUS_0]&0x10)==0x10) - continue; - /* ok drive connected check for disk */ - state|=(1<blnr=pFG->size; /* set to the last block */ - if (fdc_seek(pCMD, pFG) == false) - continue; - pCMD->blnr=0; /* set to the 1st block */ - if (fdc_recalibrate(pCMD, pFG) == false) - continue; - pCMD->cmd[COMMAND]=FDC_CMD_READ_ID; - if (fdc_issue_cmd(pCMD, pFG) == false) - continue; - state|=(0x10<name : ""); - } - pCMD->flags=state; - return true; -} - - -/************************************************************************** -* int fdc_setup -* setup the fdc according the datasheet -* assuming in PS2 Mode -*/ -int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG) -{ - int i; - -#ifdef CONFIG_SYS_FDC_HW_INIT - fdc_hw_init (); -#endif - /* first, we reset the FDC via the DOR */ - write_fdc_reg(FDC_DOR,0x00); - for(i=0; i<255; i++) /* then we wait some time */ - udelay(500); - /* then, we clear the reset in the DOR */ - pCMD->drive=drive; - select_fdc_drive(pCMD); - /* initialize the CCR */ - write_fdc_reg(FDC_CCR,pFG->rate); - /* then initialize the DSR */ - write_fdc_reg(FDC_DSR,pFG->rate); - if (wait_for_fdc_int() == false) { - PRINTF("Time Out after writing CCR\n"); - return false; - } - /* now issue sense Interrupt and status command - * assuming only one drive present (drive 0) */ - pCMD->dma=0; /* we don't use any dma at all */ - for(i=0;i<4;i++) { - /* issue sense interrupt for all 4 possible drives */ - pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT; - if (fdc_issue_cmd(pCMD, pFG) == false) { - PRINTF("Sense Interrupt for drive %d failed\n",i); - } - } - /* issue the configure command */ - pCMD->drive=drive; - select_fdc_drive(pCMD); - pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE; - if (fdc_issue_cmd(pCMD, pFG) == false) { - PRINTF(" configure timeout\n"); - stop_fdc_drive(pCMD); - return false; - } - /* issue specify command */ - pCMD->cmd[COMMAND]=FDC_CMD_SPECIFY; - if (fdc_issue_cmd(pCMD, pFG) == false) { - PRINTF(" specify timeout\n"); - stop_fdc_drive(pCMD); - return false; - - } - /* then, we clear the reset in the DOR */ - /* fdc_check_drive(pCMD,pFG); */ - /* write_fdc_reg(FDC_DOR,0x04); */ - - return true; -} - -/**************************************************************************** - * main routine do_fdcboot - */ -int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type; - FDC_COMMAND_STRUCT *pCMD = &cmd; - unsigned long addr,imsize; -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - image_header_t *hdr; /* used for fdc boot */ -#endif - unsigned char boot_drive; - int i,nrofblk; -#if defined(CONFIG_FIT) - const void *fit_hdr = NULL; -#endif - - switch (argc) { - case 1: - addr = CONFIG_SYS_LOAD_ADDR; - boot_drive=CONFIG_SYS_FDC_DRIVE_NUMBER; - break; - case 2: - addr = simple_strtoul(argv[1], NULL, 16); - boot_drive=CONFIG_SYS_FDC_DRIVE_NUMBER; - break; - case 3: - addr = simple_strtoul(argv[1], NULL, 16); - boot_drive=simple_strtoul(argv[2], NULL, 10); - break; - default: - return CMD_RET_USAGE; - } - /* setup FDC and scan for drives */ - if (fdc_setup(boot_drive, pCMD, pFG) == false) { - printf("\n** Error in setup FDC **\n"); - return 1; - } - if (fdc_check_drive(pCMD, pFG) == false) { - printf("\n** Error in check_drives **\n"); - return 1; - } - if((pCMD->flags&(1<flags&(0x10<drive=boot_drive; - /* read first block */ - pCMD->blnr=0; - if (fdc_read_data((unsigned char *)addr, 1, pCMD, pFG) == false) { - printf("\nRead error:"); - for(i=0;i<7;i++) - printf("result%d: 0x%02X\n",i,pCMD->result[i]); - return 1; - } - - switch (genimg_get_format ((void *)addr)) { -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - case IMAGE_FORMAT_LEGACY: - hdr = (image_header_t *)addr; - image_print_contents (hdr); - - imsize = 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"); - - imsize = fit_get_size (fit_hdr); - break; -#endif - default: - puts ("** Unknown image type\n"); - return 1; - } - - nrofblk=imsize/512; - if((imsize%512)>0) - nrofblk++; - printf("Loading %ld Bytes (%d blocks) at 0x%08lx..\n",imsize,nrofblk,addr); - pCMD->blnr=0; - if (fdc_read_data((unsigned char *)addr, nrofblk, pCMD, pFG) == false) { - /* read image block */ - printf("\nRead error:"); - for(i=0;i<7;i++) - printf("result%d: 0x%02X\n",i,pCMD->result[i]); - return 1; - } - printf("OK %ld Bytes loaded.\n",imsize); - - flush_cache (addr, imsize); - -#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)) { - puts ("** Bad FIT image format\n"); - return 1; - } - fit_print_contents (fit_hdr); - } -#endif - - /* Loading ok, update default load address */ - load_addr = addr; - - return bootm_maybe_autostart(cmdtp, argv[0]); -} - -U_BOOT_CMD( - fdcboot, 3, 1, do_fdcboot, - "boot from floppy device", - "loadAddr drive" -); diff --git a/cmd/cmd_fdt.c b/cmd/cmd_fdt.c deleted file mode 100644 index 4c18962..0000000 --- a/cmd/cmd_fdt.c +++ /dev/null @@ -1,1065 +0,0 @@ -/* - * (C) Copyright 2007 - * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com - * Based on code written by: - * Pantelis Antoniou and - * Matthew McClintock - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_LEVEL 32 /* how deeply nested we will go */ -#define SCRATCHPAD 1024 /* bytes of scratchpad memory */ -#ifndef CONFIG_CMD_FDT_MAX_DUMP -#define CONFIG_CMD_FDT_MAX_DUMP 64 -#endif - -/* - * Global data (for the gd->bd) - */ -DECLARE_GLOBAL_DATA_PTR; - -static int fdt_valid(struct fdt_header **blobp); -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; - setenv_hex("fdtaddr", addr); -} - -/* - * Get a value from the fdt and format it to be set in the environment - */ -static int fdt_value_setenv(const void *nodep, int len, const char *var) -{ - if (is_printable_string(nodep, len)) - setenv(var, (void *)nodep); - else if (len == 4) { - char buf[11]; - - sprintf(buf, "0x%08X", *(uint32_t *)nodep); - setenv(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)); - setenv(var, buf); - } else { - printf("error: unprintable value\n"); - return 1; - } - return 0; -} - -/* - * Flattened Device Tree command, see the help for parameter definitions. - */ -static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - if (argc < 2) - return CMD_RET_USAGE; - - /* - * Set the address of the fdt - */ - if (argv[1][0] == 'a') { - 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) : - getenv_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
\" 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; - } - working_fdt = newaddr; - - /* - * 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 (argv[1][0] == 's') { - char *pathp; /* path */ - char *prop; /* property */ - int nodeoffset; /* node offset from libfdt */ - static char data[SCRATCHPAD]; /* storage for the property */ - 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]; - if (argc == 4) { - len = 0; - } else { - ret = fdt_parse_prop(&argv[4], argc - 4, data, &len); - if (ret != 0) - return ret; - } - - 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; - } - - 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 *nodeName = fdt_get_name( - working_fdt, nextNodeOffset, NULL); - - setenv(var, (char *)nodeName); - 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 */ - setenv_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 */ - setenv(var, ""); - return 0; - } else if (len > 0) { - if (subcmd[0] == 'v') { - int ret; - - ret = fdt_value_setenv(nodep, len, var); - if (ret != 0) - return ret; - } else if (subcmd[0] == 'a') { - /* Get address */ - char buf[11]; - - sprintf(buf, "0x%p", nodep); - setenv(var, buf); - } else if (subcmd[0] == 's') { - /* Get size */ - char buf[11]; - - sprintf(buf, "0x%08X", len); - setenv(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') { - 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; - } - } -#endif -#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 - /* 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 - - } - /* resize the fdt */ - else if (strncmp(argv[1], "re", 2) == 0) { - fdt_shrink_to_minimum(working_fdt); - } - else { - /* Unrecognized command */ - return CMD_RET_USAGE; - } - - return 0; -} - -/****************************************************************************/ - -/** - * fdt_valid() - Check if an FDT is valid. If not, change it to NULL - * - * @blobp: Pointer to FDT pointer - * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL) - */ -static int fdt_valid(struct fdt_header **blobp) -{ - const void *blob = *blobp; - int err; - - if (blob == NULL) { - printf ("The address of the fdt is invalid (NULL).\n"); - return 0; - } - - err = fdt_check_header(blob); - if (err == 0) - return 1; /* valid */ - - if (err < 0) { - printf("libfdt fdt_check_header(): %s", fdt_strerror(err)); - /* - * Be more informative on bad version. - */ - if (err == -FDT_ERR_BADVERSION) { - if (fdt_version(blob) < - FDT_FIRST_SUPPORTED_VERSION) { - printf (" - too old, fdt %d < %d", - fdt_version(blob), - FDT_FIRST_SUPPORTED_VERSION); - } - if (fdt_last_comp_version(blob) > - FDT_LAST_SUPPORTED_VERSION) { - printf (" - too new, fdt %d > %d", - fdt_version(blob), - FDT_LAST_SUPPORTED_VERSION); - } - } - printf("\n"); - *blobp = NULL; - return 0; - } - return 1; -} - -/****************************************************************************/ - -/* - * 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); - *(__be32 *)data = __cpu_to_be32(tmp); - 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; - - /* no data, don't print */ - if (len == 0) - return; - - /* - * 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 > CONFIG_CMD_FDT_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 > CONFIG_CMD_FDT_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 (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] [] - Set the [control] fdt location to \n" -#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 - Copy the fdt to and make it active\n" - "fdt resize - Resize fdt to size + padding to 4k addr\n" - "fdt print [] - Recursive print starting at \n" - "fdt list [] - Print one level starting at \n" - "fdt get value - Get and store in \n" - "fdt get name - Get name of node and store in \n" - "fdt get addr - Get start address of and store in \n" - "fdt get size [] - Get size of [] or num nodes and store in \n" - "fdt set [] - Set [to ]\n" - "fdt mknode - Create a new node after \n" - "fdt rm [] - Delete the node or \n" - "fdt header - Display header info\n" - "fdt bootcpu - Set boot cpuid\n" - "fdt memory - Add/Update memory node\n" - "fdt rsvmem print - Show current mem reserves\n" - "fdt rsvmem add - Add a mem reserve\n" - "fdt rsvmem delete - Delete a mem reserves\n" - "fdt chosen [ ] - Add/update the /chosen branch in the tree\n" - " / - initrd start/end addr\n" -#if defined(CONFIG_FIT_SIGNATURE) - "fdt checksign [] - check FIT signature\n" - " - addr of key blob\n" - " default gd->fdt_blob\n" -#endif - "NOTE: Dereference aliases by omiting 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/cmd/cmd_fitupd.c b/cmd/cmd_fitupd.c deleted file mode 100644 index 78b8747..0000000 --- a/cmd/cmd_fitupd.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * (C) Copyright 2011 - * Andreas Pretzsch, carpe noctem engineering, apr@cn-eng.de - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#if !defined(CONFIG_UPDATE_TFTP) -#error "CONFIG_UPDATE_TFTP required" -#endif - -static int do_fitupd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - ulong addr = 0UL; - - if (argc > 2) - return CMD_RET_USAGE; - - if (argc == 2) - addr = simple_strtoul(argv[1], NULL, 16); - - return update_tftp(addr, NULL, NULL); -} - -U_BOOT_CMD(fitupd, 2, 0, do_fitupd, - "update from FIT image", - "[addr]\n" - "\t- run update from FIT image at addr\n" - "\t or from tftp 'updatefile'" -); diff --git a/cmd/cmd_flash.c b/cmd/cmd_flash.c deleted file mode 100644 index 85d18bb..0000000 --- a/cmd/cmd_flash.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * FLASH support - */ -#include -#include - -#ifdef CONFIG_HAS_DATAFLASH -#include -#endif - -#if defined(CONFIG_CMD_MTDPARTS) -#include - -/* 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 - -#ifndef CONFIG_SYS_NO_FLASH -#include -#include -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. start end - operate on <'start', 'end') - * 2. 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_SYS_NO_FLASH */ - -static int do_flinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ -#ifndef CONFIG_SYS_NO_FLASH - ulong bank; -#endif - -#ifdef CONFIG_HAS_DATAFLASH - dataflash_print_info(); -#endif - -#ifndef CONFIG_SYS_NO_FLASH - if (argc == 1) { /* print info for all FLASH banks */ - for (bank=0; 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_SYS_NO_FLASH */ - return 0; -} - -static int do_flerase(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ -#ifndef CONFIG_SYS_NO_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, §_first, §_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 - 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_SYS_NO_FLASH */ -} - -#ifndef CONFIG_SYS_NO_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_SYS_NO_FLASH */ - -static int do_protect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int rcode = 0; -#ifndef CONFIG_SYS_NO_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_SYS_NO_FLASH */ -#ifdef CONFIG_HAS_DATAFLASH - int status; -#endif -#if !defined(CONFIG_SYS_NO_FLASH) || defined(CONFIG_HAS_DATAFLASH) - int p; - ulong addr_first, addr_last; -#endif - - if (argc < 3) - return CMD_RET_USAGE; - -#if !defined(CONFIG_SYS_NO_FLASH) || defined(CONFIG_HAS_DATAFLASH) - 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_HAS_DATAFLASH - if ((strcmp(argv[2], "all") != 0) && (strcmp(argv[2], "bank") != 0)) { - addr_first = simple_strtoul(argv[2], NULL, 16); - addr_last = simple_strtoul(argv[3], NULL, 16); - - if (addr_dataflash(addr_first) && addr_dataflash(addr_last)) { - status = dataflash_real_protect(p,addr_first,addr_last); - if (status < 0){ - puts ("Bad DataFlash sector specification\n"); - return 1; - } - printf("%sProtect %d DataFlash Sectors\n", - p ? "" : "Un-", status); - return 0; - } - } -#endif - -#ifndef CONFIG_SYS_NO_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; isector_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, §_first, §_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 */ - 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; isector_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_SYS_NO_FLASH */ - return rcode; -} - -#ifndef CONFIG_SYS_NO_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_SYS_NO_FLASH */ - - -/**************************************************/ -#if defined(CONFIG_CMD_MTDPARTS) -# define TMP_ERASE "erase \n - erase partition\n" -# define TMP_PROT_ON "protect on \n - protect partition\n" -# define TMP_PROT_OFF "protect off \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/cmd/cmd_fpga.c b/cmd/cmd_fpga.c deleted file mode 100644 index 7f99aab..0000000 --- a/cmd/cmd_fpga.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * (C) Copyright 2000, 2001 - * Rich Ireland, Enterasys Networks, rireland@enterasys.com. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * FPGA support - */ -#include -#include -#include -#include -#include - -/* Local functions */ -static int fpga_get_op(char *opstr); - -/* Local defines */ -#define FPGA_NONE -1 -#define FPGA_INFO 0 -#define FPGA_LOAD 1 -#define FPGA_LOADB 2 -#define FPGA_DUMP 3 -#define FPGA_LOADMK 4 -#define FPGA_LOADP 5 -#define FPGA_LOADBP 6 -#define FPGA_LOADFS 7 - -/* ------------------------------------------------------------------------- */ -/* command form: - * fpga - * where op is 'load', 'dump', or 'info' - * If there is no device number field, the fpga environment variable is used. - * If there is no data addr field, the fpgadata environment variable is used. - * The info command requires no data address field. - */ -int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - int op, dev = FPGA_INVALID_DEVICE; - size_t data_size = 0; - void *fpga_data = NULL; - char *devstr = getenv("fpga"); - char *datastr = getenv("fpgadata"); - int rc = FPGA_FAIL; - int wrong_parms = 0; -#if defined(CONFIG_FIT) - const char *fit_uname = NULL; - ulong fit_addr; -#endif -#if defined(CONFIG_CMD_FPGA_LOADFS) - fpga_fs_info fpga_fsinfo; - fpga_fsinfo.fstype = FS_TYPE_ANY; -#endif - - if (devstr) - dev = (int) simple_strtoul(devstr, NULL, 16); - if (datastr) - fpga_data = (void *)simple_strtoul(datastr, NULL, 16); - - switch (argc) { -#if defined(CONFIG_CMD_FPGA_LOADFS) - case 9: - fpga_fsinfo.blocksize = (unsigned int) - simple_strtoul(argv[5], NULL, 16); - fpga_fsinfo.interface = argv[6]; - fpga_fsinfo.dev_part = argv[7]; - fpga_fsinfo.filename = argv[8]; -#endif - case 5: /* fpga */ - data_size = simple_strtoul(argv[4], NULL, 16); - - case 4: /* fpga */ -#if defined(CONFIG_FIT) - if (fit_parse_subimage(argv[3], (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(argv[3], NULL, 16); - debug("* fpga: cmdline image address = 0x%08lx\n", - (ulong)fpga_data); - } - debug("%s: fpga_data = 0x%x\n", __func__, (uint)fpga_data); - - case 3: /* fpga */ - dev = (int)simple_strtoul(argv[2], NULL, 16); - debug("%s: device = %d\n", __func__, dev); - /* FIXME - this is a really weak test */ - if ((argc == 3) && (dev > fpga_count())) { - /* must be buffer ptr */ - debug("%s: Assuming buffer pointer in arg 3\n", - __func__); - -#if defined(CONFIG_FIT) - if (fit_parse_subimage(argv[2], (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 *)dev; - debug("* fpga: cmdline image addr = 0x%08lx\n", - (ulong)fpga_data); - } - - debug("%s: fpga_data = 0x%x\n", - __func__, (uint)fpga_data); - dev = FPGA_INVALID_DEVICE; /* reset device num */ - } - - case 2: /* fpga */ - op = (int)fpga_get_op(argv[1]); - break; - - default: - debug("%s: Too many or too few args (%d)\n", __func__, argc); - op = FPGA_NONE; /* force usage display */ - break; - } - - if (dev == FPGA_INVALID_DEVICE) { - puts("FPGA device not specified\n"); - op = FPGA_NONE; - } - - switch (op) { - case FPGA_NONE: - case FPGA_INFO: - break; -#if defined(CONFIG_CMD_FPGA_LOADFS) - case FPGA_LOADFS: - /* Blocksize can be zero */ - if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part || - !fpga_fsinfo.filename) - wrong_parms = 1; -#endif - case FPGA_LOAD: - case FPGA_LOADP: - case FPGA_LOADB: - case FPGA_LOADBP: - case FPGA_DUMP: - if (!fpga_data || !data_size) - wrong_parms = 1; - break; -#if defined(CONFIG_CMD_FPGA_LOADMK) - case FPGA_LOADMK: - if (!fpga_data) - wrong_parms = 1; - break; -#endif - } - - if (wrong_parms) { - puts("Wrong parameters for FPGA request\n"); - op = FPGA_NONE; - } - - switch (op) { - case FPGA_NONE: - return CMD_RET_USAGE; - - case FPGA_INFO: - rc = fpga_info(dev); - break; - - case FPGA_LOAD: - rc = fpga_load(dev, fpga_data, data_size, BIT_FULL); - break; - -#if defined(CONFIG_CMD_FPGA_LOADP) - case FPGA_LOADP: - rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL); - break; -#endif - - case FPGA_LOADB: - rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL); - break; - -#if defined(CONFIG_CMD_FPGA_LOADBP) - case FPGA_LOADBP: - rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL); - break; -#endif - -#if defined(CONFIG_CMD_FPGA_LOADFS) - case FPGA_LOADFS: - rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo); - break; -#endif - -#if defined(CONFIG_CMD_FPGA_LOADMK) - case FPGA_LOADMK: - switch (genimg_get_format(fpga_data)) { -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - case IMAGE_FORMAT_LEGACY: - { - image_header_t *hdr = - (image_header_t *)fpga_data; - ulong data; - uint8_t comp; - - comp = image_get_comp(hdr); - if (comp == IH_COMP_GZIP) { -#if defined(CONFIG_GZIP) - ulong image_buf = image_get_data(hdr); - data = image_get_load(hdr); - ulong image_size = ~0UL; - - if (gunzip((void *)data, ~0UL, - (void *)image_buf, - &image_size) != 0) { - puts("GUNZIP: error\n"); - return 1; - } - 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); - } - rc = fpga_load(dev, (void *)data, data_size, - BIT_FULL); - } - break; -#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 == NULL) { - puts("No FIT subimage unit name\n"); - return 1; - } - - if (!fit_check_format(fit_hdr)) { - puts("Bad FIT image format\n"); - return 1; - } - - /* 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 1; - } - - /* verify integrity */ - if (!fit_image_verify(fit_hdr, noffset)) { - puts ("Bad Data Hash\n"); - return 1; - } - - /* get fpga subimage data address and length */ - if (fit_image_get_data(fit_hdr, noffset, - &fit_data, &data_size)) { - puts("Fpga subimage data not found\n"); - return 1; - } - - rc = fpga_load(dev, fit_data, data_size, - BIT_FULL); - } - break; -#endif - default: - puts("** Unknown image type\n"); - rc = FPGA_FAIL; - break; - } - break; -#endif - - case FPGA_DUMP: - rc = fpga_dump(dev, fpga_data, data_size); - break; - - default: - printf("Unknown operation\n"); - return CMD_RET_USAGE; - } - return rc; -} - -/* - * Map op to supported operations. We don't use a table since we - * would just have to relocate it from flash anyway. - */ -static int fpga_get_op(char *opstr) -{ - int op = FPGA_NONE; - - if (!strcmp("info", opstr)) - op = FPGA_INFO; - else if (!strcmp("loadb", opstr)) - op = FPGA_LOADB; - else if (!strcmp("load", opstr)) - op = FPGA_LOAD; -#if defined(CONFIG_CMD_FPGA_LOADP) - else if (!strcmp("loadp", opstr)) - op = FPGA_LOADP; -#endif -#if defined(CONFIG_CMD_FPGA_LOADBP) - else if (!strcmp("loadbp", opstr)) - op = FPGA_LOADBP; -#endif -#if defined(CONFIG_CMD_FPGA_LOADFS) - else if (!strcmp("loadfs", opstr)) - op = FPGA_LOADFS; -#endif -#if defined(CONFIG_CMD_FPGA_LOADMK) - else if (!strcmp("loadmk", opstr)) - op = FPGA_LOADMK; -#endif - else if (!strcmp("dump", opstr)) - op = FPGA_DUMP; - - if (op == FPGA_NONE) - printf("Unknown fpga operation \"%s\"\n", opstr); - - return op; -} - -#if defined(CONFIG_CMD_FPGA_LOADFS) -U_BOOT_CMD(fpga, 9, 1, do_fpga, -#else -U_BOOT_CMD(fpga, 6, 1, do_fpga, -#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] \n" - " [] \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:" -#endif -#endif -); diff --git a/cmd/cmd_fpgad.c b/cmd/cmd_fpgad.c deleted file mode 100644 index 5370c3e..0000000 --- a/cmd/cmd_fpgad.c +++ /dev/null @@ -1,101 +0,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. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#include - -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(cmd_tbl_t *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/cmd/cmd_fs.c b/cmd/cmd_fs.c deleted file mode 100644 index 8f8f1b2..0000000 --- a/cmd/cmd_fs.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. - * - * Inspired by cmd_ext_common.c, cmd_fat.c. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include - -static int do_size_wrapper(cmd_tbl_t *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", - " \n" - " - Find file 'filename' from 'dev' on 'interface'\n" - " and determine its size." -); - -static int do_load_wrapper(cmd_tbl_t *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", - " [ [ [ [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(cmd_tbl_t *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", - " 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(cmd_tbl_t *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 /)", - " [ [directory]]\n" - " - List files in directory 'directory' of partition 'part' on\n" - " device type 'interface' instance 'dev'." -) - -static int do_fstype_wrapper(cmd_tbl_t *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", - " :\n" - "- print filesystem type\n" - "fstype : \n" - "- set environment variable to filesystem type\n" -); diff --git a/cmd/cmd_fs_uuid.c b/cmd/cmd_fs_uuid.c deleted file mode 100644 index 613f3a4..0000000 --- a/cmd/cmd_fs_uuid.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * cmd_fs_uuid.c -- fsuuid command - * - * Copyright (C) 2014, Bachmann electronic GmbH - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -static int do_fs_uuid_wrapper(cmd_tbl_t *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", - " :\n" - " - print filesystem UUID\n" - "fsuuid : \n" - " - set environment variable to filesystem UUID\n" -); diff --git a/cmd/cmd_fuse.c b/cmd/cmd_fuse.c deleted file mode 100644 index 5998f9b..0000000 --- a/cmd/cmd_fuse.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * (C) Copyright 2009-2013 ADVANSEE - * Benoît Thébaudeau - * - * Based on the mpc512x iim code: - * Copyright 2008 Silicon Turnkey Express, Inc. - * Martha Marx - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -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? \n"); - - if (confirm_yesno()) - return 1; - - puts("Fuse programming aborted\n"); - return 0; -} - -static int do_fuse(cmd_tbl_t *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 [] - read 1 or 'cnt' fuse words,\n" - " starting at 'word'\n" - "fuse sense [] - sense 1 or 'cnt' fuse words,\n" - " starting at 'word'\n" - "fuse prog [-y] [...] - program 1 or\n" - " several fuse words, starting at 'word' (PERMANENT)\n" - "fuse override [...] - override 1 or\n" - " several fuse words, starting at 'word'" -); diff --git a/cmd/cmd_gettime.c b/cmd/cmd_gettime.c deleted file mode 100644 index c48baad..0000000 --- a/cmd/cmd_gettime.c +++ /dev/null @@ -1,40 +0,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. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Get Timer overflows after 2^32 / CONFIG_SYS_HZ (32Khz) = 131072 sec - */ -#include -#include - -static int do_gettime(cmd_tbl_t *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/cmd/cmd_gpio.c b/cmd/cmd_gpio.c deleted file mode 100644 index 2b78b16..0000000 --- a/cmd/cmd_gpio.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Control GPIO pins on the fly - * - * Copyright (c) 2008-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include - -__weak int name_to_gpio(const char *name) -{ - return simple_strtoul(name, NULL, 10); -} - -enum gpio_cmd { - GPIO_INPUT, - GPIO_SET, - GPIO_CLEAR, - GPIO_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) -{ - char buf[80]; - int ret; - - ret = gpio_get_function(dev, offset, NULL); - if (ret < 0) - goto err; - if (!(*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 || - !strncmp(gpio_name, bank_name, banklen)) { - const char *p = NULL; - int offset; - - p = gpio_name + banklen; - if (gpio_name && *p) { - offset = simple_strtoul(p, NULL, 10); - gpio_get_description(dev, bank_name, offset, - &flags); - } else { - for (offset = 0; offset < num_bits; offset++) { - gpio_get_description(dev, bank_name, - offset, &flags); - } - } - } - /* Add a newline between bank names */ - if (!(flags & FLAG_SHOW_BANK)) - flags |= FLAG_SHOW_NEWLINE; - } - - return ret; -} -#endif - -static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unsigned int gpio; - enum gpio_cmd sub_cmd; - ulong 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", 1)) { - /* 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 = GPIO_INPUT; break; - case 's': sub_cmd = GPIO_SET; break; - case 'c': sub_cmd = GPIO_CLEAR; break; - case 't': sub_cmd = GPIO_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 == GPIO_INPUT) { - gpio_direction_input(gpio); - value = gpio_get_value(gpio); - } else { - switch (sub_cmd) { - case GPIO_SET: value = 1; break; - case GPIO_CLEAR: value = 0; break; - case GPIO_TOGGLE: value = !gpio_get_value(gpio); break; - default: goto show_usage; - } - gpio_direction_output(gpio, value); - } - printf("gpio: pin %s (gpio %i) value is %lu\n", - str_gpio, gpio, value); - - if (ret != -EBUSY) - gpio_free(gpio); - - return value; -} - -U_BOOT_CMD(gpio, 4, 0, do_gpio, - "query and control gpio pins", - " \n" - " - input/set/clear/toggle the specified pin\n" - "gpio status [-a] [ | ] - show [all/claimed] GPIOs"); diff --git a/cmd/cmd_gpt.c b/cmd/cmd_gpt.c deleted file mode 100644 index d94d553..0000000 --- a/cmd/cmd_gpt.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * cmd_gpt.c -- GPT (GUID Partition Table) handling command - * - * Copyright (C) 2015 - * Lukasz Majewski - * - * Copyright (C) 2012 Samsung Electronics - * author: Lukasz Majewski - * author: Piotr Wilczek - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_PARTITION_UUIDS -#error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled -#endif - -/** - * 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 = getenv(s); - if (e == NULL) { -#ifdef CONFIG_RANDOM_UUID - debug("%s unset. ", str); - gen_rand_uuid_str(uuid_str, UUID_STR_FORMAT_STD); - setenv(s, uuid_str); - - e = getenv(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; -} - -/** - * 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(block_dev_desc_t *dev_desc, - const char *str_part, - char **str_disk_guid, - disk_partition_t **partitions, - u8 *parts_count) -{ - char *tok, *str, *s; - int i; - char *val, *p; - int p_count; - disk_partition_t *parts; - int errno = 0; - uint64_t size_ll, start_ll; - - 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); - - /* 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); - 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 (strlen(s) == 0) - return -3; - - 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(disk_partition_t), p_count); - - /* 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 (strlen(p) >= sizeof(parts[i].uuid)) { - printf("Wrong uuid format for partition %d\n", i); - errno = -4; - goto err; - } - strcpy((char *)parts[i].uuid, p); - 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 (strlen(p) >= sizeof(parts[i].type_guid)) { - printf("Wrong type guid format for partition %d\n", - i); - errno = -4; - goto err; - } - strcpy((char *)parts[i].type_guid, p); - 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 (strlen(p) >= sizeof(parts[i].name)) { - errno = -4; - goto err; - } - strcpy((char *)parts[i].name, p); - free(val); - - /* size */ - val = extract_val(tok, "size"); - if (!val) { /* 'size' is mandatory */ - errno = -4; - goto err; - } - if (extract_env(val, &p)) - p = val; - 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); - } - - /* bootable */ - if (found_key(tok, "bootable")) - parts[i].bootable = 1; - } - - *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(block_dev_desc_t *blk_dev_desc, const char *str_part) -{ - int ret; - char *str_disk_guid; - u8 part_count = 0; - disk_partition_t *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(block_dev_desc_t *blk_dev_desc, const char *str_part) -{ - ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, - blk_dev_desc->blksz); - disk_partition_t *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; -} - -/** - * 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int ret = CMD_RET_SUCCESS; - int dev = 0; - char *ep; - block_dev_desc_t *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 = 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 { - 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", - " \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" - " gpt verify mmc 0 $partitions\n" -); diff --git a/cmd/cmd_hash.c b/cmd/cmd_hash.c deleted file mode 100644 index 704d21e..0000000 --- a/cmd/cmd_hash.c +++ /dev/null @@ -1,56 +0,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. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -static int do_hash(cmd_tbl_t *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/cmd/cmd_help.c b/cmd/cmd_help.c deleted file mode 100644 index 6ff494d..0000000 --- a/cmd/cmd_help.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2000-2009 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -static int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *start = ll_entry_start(cmd_tbl_t, cmd); - const int len = ll_entry_count(cmd_tbl_t, cmd); - return _do_help(start, len, cmdtp, flag, argc, argv); -} - -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'" -); - -/* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */ -ll_entry_declare(cmd_tbl_t, question_mark, cmd) = { - "?", CONFIG_SYS_MAXARGS, 1, do_help, - "alias for 'help'", -#ifdef CONFIG_SYS_LONGHELP - "" -#endif /* CONFIG_SYS_LONGHELP */ -}; diff --git a/cmd/cmd_host.c b/cmd/cmd_host.c deleted file mode 100644 index ba1460e..0000000 --- a/cmd/cmd_host.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2012, Google Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -static int host_curr_device = -1; - -static int do_host_load(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - return do_load(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); -} - -static int do_host_ls(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); -} - -static int do_host_save(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); -} - -static int do_host_bind(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - if (argc < 2 || argc > 3) - return CMD_RET_USAGE; - char *ep; - char *dev_str = argv[1]; - char *file = argc >= 3 ? argv[2] : NULL; - int dev = simple_strtoul(dev_str, &ep, 16); - if (*ep) { - printf("** Bad device specification %s **\n", dev_str); - return CMD_RET_USAGE; - } - return host_dev_bind(dev, file); -} - -static int do_host_info(cmd_tbl_t *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++) { - block_dev_desc_t *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 = blk_dev->priv; - printf("%12lu %s\n", (unsigned long)blk_dev->lba, - host_dev->filename); - } - return 0; -} - -static int do_host_dev(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - int dev; - char *ep; - block_dev_desc_t *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 cmd_tbl_t 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(bind, 3, 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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - cmd_tbl_t *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( - sb, 8, 1, do_host, - "Deprecated: use 'host' command instead.", "" -); - -U_BOOT_CMD( - host, 8, 1, do_host, - "Miscellaneous host commands", - "load hostfs - [ ] - " - "load a file from host\n" - "host ls hostfs - - list files on host\n" - "host save hostfs - [] - " - "save a file to host\n" - "host bind [] - bind \"host\" device to file\n" - "host info [] - show device binding & info\n" - "host 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/cmd/cmd_i2c.c b/cmd/cmd_i2c.c deleted file mode 100644 index b3bb644..0000000 --- a/cmd/cmd_i2c.c +++ /dev/null @@ -1,2030 +0,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. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * 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: A0 00 A1 ... - * i2c md 50 100 10 display 16 bytes starting at 0x100 - * On the bus: A2 00 A3 ... - * i2c md 50 210 10 display 16 bytes starting at 0x210 - * On the bus: A4 10 A5 ... - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -/* 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. - */ -#ifdef CONFIG_DM_I2C -#define DEFAULT_ADDR_LEN (-1) -#else -#define DEFAULT_ADDR_LEN 1 -#endif - -#ifdef CONFIG_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) -{ - 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 overriden 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) && !defined(CONFIG_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 ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - uint chip; - uint devaddr, length; - int alen; - u_char *memaddr; - int ret; -#ifdef CONFIG_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); - -#ifdef CONFIG_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - uint chip; - uint devaddr, length; - int alen; - u_char *memaddr; - int ret; -#ifdef CONFIG_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); - -#ifdef CONFIG_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_platdata(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. - */ -#ifdef CONFIG_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 separate - * write transactions of one byte each - */ - while (length-- > 0) { -#ifdef CONFIG_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; -} - -#ifdef CONFIG_DM_I2C -static int do_i2c_flags(cmd_tbl_t *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(cmd_tbl_t *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 ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - uint chip; - uint addr, length; - int alen; - int j, nbytes, linebytes; - int ret; -#ifdef CONFIG_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); - } - -#ifdef CONFIG_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; - -#ifdef CONFIG_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 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 ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - uint chip; - ulong addr; - int alen; - uchar byte; - int count; - int ret; -#ifdef CONFIG_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; - -#ifdef CONFIG_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) { -#ifdef CONFIG_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 (cmd_tbl_t *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; -#ifdef CONFIG_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; - -#ifdef CONFIG_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) { -#ifdef CONFIG_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(cmd_tbl_t *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; -#ifdef CONFIG_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; - } - -#ifdef CONFIG_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); -#ifdef CONFIG_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) { - /* - * 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(); -#ifdef CONFIG_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 (cmd_tbl_t *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; -#ifdef CONFIG_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 -#ifdef CONFIG_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - uint chip; - int alen; - uint addr; - uint length; - u_char bytes[16]; - int delay; - int ret; -#ifdef CONFIG_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; -#ifdef CONFIG_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) { -#ifdef CONFIG_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 (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - enum { unknown, EDO, SDRAM, DDR2 } type; - - uint chip; - u_char data[128]; - u_char cksum; - int j; - - 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 (i2c_read (chip, 0, 1, data, sizeof (data)) != 0) { - 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 8: - type = DDR2; - puts ("DDR2\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(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - uint chip; - struct edid1_info edid; - int ret; -#ifdef CONFIG_DM_I2C - struct udevice *dev; -#endif - - if (argc < 2) { - cmd_usage(cmdtp); - return 1; - } - - chip = simple_strtoul(argv[1], NULL, 16); -#ifdef CONFIG_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 */ - -#ifdef CONFIG_DM_I2C -static void show_bus(struct udevice *bus) -{ - struct udevice *dev; - - printf("Bus %d:\t%s", bus->req_seq, bus->name); - if (device_active(bus)) - printf(" (active %d)", bus->seq); - printf("\n"); - for (device_find_first_child(bus, &dev); - dev; - device_find_next_child(&dev)) { - struct dm_i2c_chip *chip = dev_get_parent_platdata(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) || defined(CONFIG_DM_I2C) -static int do_i2c_show_bus(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - if (argc == 1) { - /* show all busses */ -#ifdef CONFIG_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); -#ifdef CONFIG_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) || \ - defined(CONFIG_DM_I2C) -static int do_i2c_bus_num(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - int ret = 0; - int bus_no; - - if (argc == 1) { - /* querying current setting */ -#ifdef CONFIG_DM_I2C - struct udevice *bus; - - if (!i2c_get_cur_bus(&bus)) - bus_no = bus->seq; - 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); -#ifdef CONFIG_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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - int speed, ret=0; - -#ifdef CONFIG_DM_I2C - struct udevice *bus; - - if (i2c_get_cur_bus(&bus)) - return 1; -#endif - if (argc == 1) { -#ifdef CONFIG_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); -#ifdef CONFIG_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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ -#if defined(CONFIG_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 cmd_tbl_t cmd_i2c_sub[] = { -#if defined(CONFIG_SYS_I2C) || defined(CONFIG_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) || defined(CONFIG_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, "", ""), -#ifdef CONFIG_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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *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) || defined(CONFIG_DM_I2C) - "bus [muxtype:muxaddr:muxchannel] - show I2C bus info\n" -#endif - "crc32 chip address[.0, .1, .2] count - compute CRC32 checksum\n" -#if defined(CONFIG_SYS_I2C) || \ - defined(CONFIG_I2C_MULTI_BUS) || defined(CONFIG_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" -#ifdef CONFIG_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/cmd/cmd_ide.c b/cmd/cmd_ide.c deleted file mode 100644 index f19a7ce..0000000 --- a/cmd/cmd_ide.c +++ /dev/null @@ -1,1457 +0,0 @@ -/* - * (C) Copyright 2000-2011 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * IDE support - */ - -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA) -# include -#endif - -#include -#include - -#ifdef CONFIG_STATUS_LED -# include -#endif - -#ifdef __PPC__ -# define EIEIO __asm__ volatile ("eieio") -# define SYNC __asm__ volatile ("sync") -#else -# define EIEIO /* nothing */ -# define SYNC /* nothing */ -#endif - -/* ------------------------------------------------------------------------- */ - -/* Current I/O Device */ -static int curr_device = -1; - -/* Current offset for IDE0 / IDE1 bus access */ -ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = { -#if defined(CONFIG_SYS_ATA_IDE0_OFFSET) - CONFIG_SYS_ATA_IDE0_OFFSET, -#endif -#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1) - CONFIG_SYS_ATA_IDE1_OFFSET, -#endif -}; - -static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; - -block_dev_desc_t ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; -/* ------------------------------------------------------------------------- */ - -#ifdef CONFIG_IDE_RESET -static void ide_reset (void); -#else -#define ide_reset() /* dummy */ -#endif - -static void ide_ident (block_dev_desc_t *dev_desc); -static uchar ide_wait (int dev, ulong t); - -#define IDE_TIME_OUT 2000 /* 2 sec timeout */ - -#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */ - -#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ - -static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); - -#ifndef CONFIG_SYS_ATA_PORT_ADDR -#define CONFIG_SYS_ATA_PORT_ADDR(port) (port) -#endif - -#ifdef CONFIG_ATAPI -static void atapi_inquiry(block_dev_desc_t *dev_desc); -static ulong atapi_read(block_dev_desc_t *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer); -#endif - - -/* ------------------------------------------------------------------------- */ - -int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - int rcode = 0; - - switch (argc) { - case 0: - case 1: - return CMD_RET_USAGE; - case 2: - if (strncmp(argv[1], "res", 3) == 0) { - puts("\nReset IDE" -#ifdef CONFIG_IDE_8xx_DIRECT - " on PCMCIA " PCMCIA_SLOT_MSG -#endif - ": "); - - ide_init(); - return 0; - } else if (strncmp(argv[1], "inf", 3) == 0) { - int i; - - putc('\n'); - - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - if (ide_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; /* list only known devices */ - printf("IDE device %d: ", i); - dev_print(&ide_dev_desc[i]); - } - return 0; - - } else if (strncmp(argv[1], "dev", 3) == 0) { - if ((curr_device < 0) - || (curr_device >= CONFIG_SYS_IDE_MAXDEVICE)) { - puts("\nno IDE devices available\n"); - return 1; - } - printf("\nIDE device %d: ", curr_device); - dev_print(&ide_dev_desc[curr_device]); - return 0; - } else if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; - - for (ok = 0, dev = 0; - dev < CONFIG_SYS_IDE_MAXDEVICE; - ++dev) { - if (ide_dev_desc[dev].part_type != - PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc('\n'); - print_part(&ide_dev_desc[dev]); - } - } - if (!ok) { - puts("\nno IDE devices available\n"); - rcode++; - } - return rcode; - } - return CMD_RET_USAGE; - case 3: - if (strncmp(argv[1], "dev", 3) == 0) { - int dev = (int) simple_strtoul(argv[2], NULL, 10); - - printf("\nIDE device %d: ", dev); - if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { - puts("unknown device\n"); - return 1; - } - dev_print(&ide_dev_desc[dev]); - /*ide_print (dev); */ - - if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - - curr_device = dev; - - puts("... is now current device\n"); - - return 0; - } else if (strncmp(argv[1], "part", 4) == 0) { - int dev = (int) simple_strtoul(argv[2], NULL, 10); - - if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - print_part(&ide_dev_desc[dev]); - } else { - printf("\nIDE device %d not available\n", - dev); - rcode = 1; - } - return rcode; - } - - return CMD_RET_USAGE; - default: - /* at least 4 args */ - - if (strcmp(argv[1], "read") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - block_dev_desc_t *dev_desc; - ulong n; - -#ifdef CONFIG_SYS_64BIT_LBA - lbaint_t blk = simple_strtoull(argv[3], NULL, 16); - - printf("\nIDE read: device %d block # %lld, count %ld ... ", - curr_device, blk, cnt); -#else - lbaint_t blk = simple_strtoul(argv[3], NULL, 16); - - printf("\nIDE read: device %d block # %ld, count %ld ... ", - curr_device, blk, cnt); -#endif - - dev_desc = &ide_dev_desc[curr_device]; - n = dev_desc->block_read(dev_desc, blk, cnt, - (ulong *)addr); - /* flush cache after read */ - flush_cache(addr, - cnt * ide_dev_desc[curr_device].blksz); - - printf("%ld blocks read: %s\n", - n, (n == cnt) ? "OK" : "ERROR"); - if (n == cnt) - return 0; - else - return 1; - } else if (strcmp(argv[1], "write") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - -#ifdef CONFIG_SYS_64BIT_LBA - lbaint_t blk = simple_strtoull(argv[3], NULL, 16); - - printf("\nIDE write: device %d block # %lld, count %ld ... ", - curr_device, blk, cnt); -#else - lbaint_t blk = simple_strtoul(argv[3], NULL, 16); - - printf("\nIDE write: device %d block # %ld, count %ld ... ", - curr_device, blk, cnt); -#endif - n = ide_write(&ide_dev_desc[curr_device], blk, cnt, - (ulong *)addr); - - printf("%ld blocks written: %s\n", - n, (n == cnt) ? "OK" : "ERROR"); - if (n == cnt) - return 0; - else - return 1; - } else { - return CMD_RET_USAGE; - } - - return rcode; - } -} - -int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - return common_diskboot(cmdtp, "ide", argc, argv); -} - -/* ------------------------------------------------------------------------- */ - -__weak void ide_led(uchar led, uchar status) -{ -#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ - static uchar led_buffer; /* Buffer for current LED status */ - - uchar *led_port = LED_PORT; - - if (status) /* switch LED on */ - led_buffer |= led; - else /* switch LED off */ - led_buffer &= ~led; - - *led_port = led_buffer; -#endif -} - -#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ -# define DEVICE_LED(x) 0 -# define LED_IDE1 1 -# define LED_IDE2 2 -#endif - -/* ------------------------------------------------------------------------- */ - -__weak void ide_outb(int dev, int port, unsigned char val) -{ - debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", - dev, port, val, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); - -#if defined(CONFIG_IDE_AHB) - if (port) { - /* write command */ - ide_write_register(dev, port, val); - } else { - /* write data */ - outb(val, (ATA_CURR_BASE(dev))); - } -#else - outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif -} - -__weak unsigned char ide_inb(int dev, int port) -{ - uchar val; - -#if defined(CONFIG_IDE_AHB) - val = ide_read_register(dev, port); -#else - val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif - - debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", - dev, port, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); - return val; -} - -void ide_init(void) -{ - unsigned char c; - int i, bus; - -#ifdef CONFIG_IDE_8xx_PCCARD - extern int ide_devices_found; /* Initialized in check_ide_device() */ -#endif /* CONFIG_IDE_8xx_PCCARD */ - -#ifdef CONFIG_IDE_PREINIT - WATCHDOG_RESET(); - - if (ide_preinit()) { - puts("ide_preinit failed\n"); - return; - } -#endif /* CONFIG_IDE_PREINIT */ - - WATCHDOG_RESET(); - - /* - * Reset the IDE just to be sure. - * Light LED's to show - */ - ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ - - /* ATAPI Drives seems to need a proper IDE Reset */ - ide_reset(); - -#ifdef CONFIG_IDE_INIT_POSTRESET - WATCHDOG_RESET(); - - if (ide_init_postreset()) { - puts("ide_preinit_postreset failed\n"); - return; - } -#endif /* CONFIG_IDE_INIT_POSTRESET */ - - /* - * Wait for IDE to get ready. - * According to spec, this can take up to 31 seconds! - */ - for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { - int dev = - bus * (CONFIG_SYS_IDE_MAXDEVICE / - CONFIG_SYS_IDE_MAXBUS); - -#ifdef CONFIG_IDE_8xx_PCCARD - /* Skip non-ide devices from probing */ - if ((ide_devices_found & (1 << bus)) == 0) { - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - continue; - } -#endif - printf("Bus %d: ", bus); - - ide_bus_ok[bus] = 0; - - /* Select device - */ - udelay(100000); /* 100 ms */ - ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); - udelay(100000); /* 100 ms */ - i = 0; - do { - udelay(10000); /* 10 ms */ - - c = ide_inb(dev, ATA_STATUS); - i++; - if (i > (ATA_RESET_TIME * 100)) { - puts("** Timeout **\n"); - /* LED's off */ - ide_led((LED_IDE1 | LED_IDE2), 0); - return; - } - if ((i >= 100) && ((i % 100) == 0)) - putc('.'); - - } while (c & ATA_STAT_BUSY); - - if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { - puts("not available "); - debug("Status = 0x%02X ", c); -#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ - } else if ((c & ATA_STAT_READY) == 0) { - puts("not available "); - debug("Status = 0x%02X ", c); -#endif - } else { - puts("OK "); - ide_bus_ok[bus] = 1; - } - WATCHDOG_RESET(); - } - - putc('\n'); - - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - ide_dev_desc[i].if_type = IF_TYPE_IDE; - ide_dev_desc[i].dev = i; - ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - ide_dev_desc[i].blksz = 0; - ide_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); - ide_dev_desc[i].lba = 0; - ide_dev_desc[i].block_read = ide_read; - ide_dev_desc[i].block_write = ide_write; - if (!ide_bus_ok[IDE_BUS(i)]) - continue; - ide_led(led, 1); /* LED on */ - ide_ident(&ide_dev_desc[i]); - ide_led(led, 0); /* LED off */ - dev_print(&ide_dev_desc[i]); - - if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { - /* initialize partition type */ - init_part(&ide_dev_desc[i]); - if (curr_device < 0) - curr_device = i; - } - } - WATCHDOG_RESET(); -} - -/* ------------------------------------------------------------------------- */ - -#ifdef CONFIG_PARTITIONS -block_dev_desc_t *ide_get_dev(int dev) -{ - return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; -} -#endif - -/* ------------------------------------------------------------------------- */ - -/* We only need to swap data if we are running on a big endian cpu. */ -#if defined(__LITTLE_ENDIAN) -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - ide_input_data(dev, sect_buf, words); -} -#else -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - volatile ushort *pbuf = - (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - ushort *dbuf = (ushort *) sect_buf; - - debug("in input swap data base for read is %lx\n", - (unsigned long) pbuf); - - while (words--) { -#ifdef __MIPS__ - *dbuf++ = swab16p((u16 *) pbuf); - *dbuf++ = swab16p((u16 *) pbuf); -#else - *dbuf++ = ld_le16(pbuf); - *dbuf++ = ld_le16(pbuf); -#endif /* !MIPS */ - } -} -#endif /* __LITTLE_ENDIAN */ - - -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - while (words--) { - EIEIO; - *pbuf = *dbuf++; - EIEIO; - *pbuf = *dbuf++; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_write_data(dev, sect_buf, words); -#else - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} -#endif /* CONFIG_IDE_SWAP_IO */ - -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - - debug("in input data base for read is %lx\n", (unsigned long) pbuf); - - while (words--) { - EIEIO; - *dbuf++ = *pbuf; - EIEIO; - *dbuf++ = *pbuf; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_read_data(dev, sect_buf, words); -#else - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} - -#endif /* CONFIG_IDE_SWAP_IO */ - -/* ------------------------------------------------------------------------- - */ -static void ide_ident(block_dev_desc_t *dev_desc) -{ - unsigned char c; - hd_driveid_t iop; - -#ifdef CONFIG_ATAPI - int retries = 0; -#endif - int device; - - device = dev_desc->dev; - printf(" Device %d: ", device); - - ide_led(DEVICE_LED(device), 1); /* LED on */ - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - dev_desc->if_type = IF_TYPE_IDE; -#ifdef CONFIG_ATAPI - - retries = 0; - - /* Warning: This will be tricky to read */ - while (retries <= 1) { - /* check signature */ - if ((ide_inb(device, ATA_SECT_CNT) == 0x01) && - (ide_inb(device, ATA_SECT_NUM) == 0x01) && - (ide_inb(device, ATA_CYL_LOW) == 0x14) && - (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) { - /* ATAPI Signature found */ - dev_desc->if_type = IF_TYPE_ATAPI; - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT); - /* - * Wait for completion - ATAPI devices need more time - * to become ready - */ - c = ide_wait(device, ATAPI_TIME_OUT); - } else -#endif - { - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT); - - /* - * Wait for completion - */ - c = ide_wait(device, IDE_TIME_OUT); - } - ide_led(DEVICE_LED(device), 0); /* LED off */ - - if (((c & ATA_STAT_DRQ) == 0) || - ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) { -#ifdef CONFIG_ATAPI - { - /* - * Need to soft reset the device - * in case it's an ATAPI... - */ - debug("Retrying...\n"); - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - udelay(100000); - ide_outb(device, ATA_COMMAND, 0x08); - udelay(500000); /* 500 ms */ - } - /* - * Select device - */ - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - retries++; -#else - return; -#endif - } -#ifdef CONFIG_ATAPI - else - break; - } /* see above - ugly to read */ - - if (retries == 2) /* Not found */ - return; -#endif - - ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); - - ident_cpy((unsigned char *) dev_desc->revision, iop.fw_rev, - sizeof(dev_desc->revision)); - ident_cpy((unsigned char *) dev_desc->vendor, iop.model, - sizeof(dev_desc->vendor)); - ident_cpy((unsigned char *) dev_desc->product, iop.serial_no, - sizeof(dev_desc->product)); -#ifdef __LITTLE_ENDIAN - /* - * firmware revision, model, and serial number have Big Endian Byte - * order in Word. Convert all three to little endian. - * - * See CF+ and CompactFlash Specification Revision 2.0: - * 6.2.1.6: Identify Drive, Table 39 for more details - */ - - strswab(dev_desc->revision); - strswab(dev_desc->vendor); - strswab(dev_desc->product); -#endif /* __LITTLE_ENDIAN */ - - if ((iop.config & 0x0080) == 0x0080) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - -#ifdef CONFIG_ATAPI - if (dev_desc->if_type == IF_TYPE_ATAPI) { - atapi_inquiry(dev_desc); - return; - } -#endif /* CONFIG_ATAPI */ - -#ifdef __BIG_ENDIAN - /* swap shorts */ - dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16); -#else /* ! __BIG_ENDIAN */ - /* - * do not swap shorts on little endian - * - * See CF+ and CompactFlash Specification Revision 2.0: - * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details. - */ - dev_desc->lba = iop.lba_capacity; -#endif /* __BIG_ENDIAN */ - -#ifdef CONFIG_LBA48 - if (iop.command_set_2 & 0x0400) { /* LBA 48 support */ - dev_desc->lba48 = 1; - dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] | - ((unsigned long long) iop.lba48_capacity[1] << 16) | - ((unsigned long long) iop.lba48_capacity[2] << 32) | - ((unsigned long long) iop.lba48_capacity[3] << 48); - } else { - dev_desc->lba48 = 0; - } -#endif /* CONFIG_LBA48 */ - /* assuming HD */ - dev_desc->type = DEV_TYPE_HARDDISK; - dev_desc->blksz = ATA_BLOCKSIZE; - dev_desc->log2blksz = LOG2(dev_desc->blksz); - dev_desc->lun = 0; /* just to fill something in... */ - -#if 0 /* only used to test the powersaving mode, - * if enabled, the drive goes after 5 sec - * in standby mode */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, 0); - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, 0xe3); - udelay(50); - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ -#endif -} - - -/* ------------------------------------------------------------------------- */ - -ulong ide_read(block_dev_desc_t *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->dev; - ulong n = 0; - unsigned char c; - unsigned char pwrsave = 0; /* power save */ - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - - /* first check if the drive is in Powersaving mode, if yes, - * increase the timeout value */ - ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); - udelay(50); - - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - printf("No Powersaving mode %X\n", c); - } else { - c = ide_inb(device, ATA_SECT_CNT); - debug("Powersaving %02X\n", c); - if (c == 0) - pwrsave = 1; - } - - - while (blkcnt-- > 0) { - - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - break; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif - } -#endif - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); - ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); - -#ifdef CONFIG_LBA48 - if (lba48) { - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT); - - } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_READ); - } - - udelay(50); - - if (pwrsave) { - /* may take up to 4 sec */ - c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); - pwrsave = 0; - } else { - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - } - - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF ": status " - "%#02x\n", device, blknr, c); - break; - } - - ide_input_data(device, buffer, ATA_SECTORWORDS); - (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ - - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -IDE_READ_E: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return (n); -} - -/* ------------------------------------------------------------------------- */ - - -ulong ide_write(block_dev_desc_t *block_dev, lbaint_t blknr, lbaint_t blkcnt, - const void *buffer) -{ - int device = block_dev->dev; - ulong n = 0; - unsigned char c; - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - - while (blkcnt-- > 0) { - - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto WR_OUT; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif - } -#endif - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); - ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); - -#ifdef CONFIG_LBA48 - if (lba48) { - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT); - - } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); - } - - udelay(50); - - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF ": status " - "%#02x\n", device, blknr, c); - goto WR_OUT; - } - - ide_output_data(device, buffer, ATA_SECTORWORDS); - c = ide_inb(device, ATA_STATUS); /* clear IRQ */ - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -WR_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return (n); -} - -/* ------------------------------------------------------------------------- */ - -/* - * copy src to dest, skipping leading and trailing blanks and null - * terminate the string - * "len" is the size of available memory including the terminating '\0' - */ -static void ident_cpy(unsigned char *dst, unsigned char *src, - unsigned int len) -{ - unsigned char *end, *last; - - last = dst; - end = src + len - 1; - - /* reserve space for '\0' */ - if (len < 2) - goto OUT; - - /* skip leading white space */ - while ((*src) && (src < end) && (*src == ' ')) - ++src; - - /* copy string, omitting trailing white space */ - while ((*src) && (src < end)) { - *dst++ = *src; - if (*src++ != ' ') - last = dst; - } -OUT: - *last = '\0'; -} - -/* ------------------------------------------------------------------------- */ - -/* - * Wait until Busy bit is off, or timeout (in ms) - * Return last status - */ -static uchar ide_wait(int dev, ulong t) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { - udelay(100); - if (delay-- == 0) - break; - } - return (c); -} - -/* ------------------------------------------------------------------------- */ - -#ifdef CONFIG_IDE_RESET -extern void ide_set_reset(int idereset); - -static void ide_reset(void) -{ - int i; - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) - ide_bus_ok[i] = 0; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - - ide_set_reset(1); /* assert reset */ - - /* the reset signal shall be asserted for et least 25 us */ - udelay(25); - - WATCHDOG_RESET(); - - /* de-assert RESET signal */ - ide_set_reset(0); - - /* wait 250 ms */ - for (i = 0; i < 250; ++i) - udelay(1000); -} - -#endif /* CONFIG_IDE_RESET */ - -/* ------------------------------------------------------------------------- */ - -#if defined(CONFIG_OF_IDE_FIXUP) -int ide_device_present(int dev) -{ - if (dev >= CONFIG_SYS_IDE_MAXBUS) - return 0; - return (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1); -} -#endif -/* ------------------------------------------------------------------------- */ - -#ifdef CONFIG_ATAPI -/**************************************************************************** - * ATAPI Support - */ - -#if defined(CONFIG_IDE_SWAP_IO) -/* since ATAPI may use commands with not 4 bytes alligned length - * we have our own transfer functions, 2 bytes alligned */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - - debug("in output data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *pbuf = *dbuf++; - } -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - - debug("in input data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *dbuf++ = *pbuf; - } -} - -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -#endif /* CONFIG_IDE_SWAP_IO */ - -/* - * Wait until (Status & mask) == res, or timeout (in ms) - * Return last status - * This is used since some ATAPI CD ROMs clears their Busy Bit first - * and then they set their DRQ Bit - */ -static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - /* prevents to read the status before valid */ - c = ide_inb(dev, ATA_DEV_CTL); - - while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { - /* break if error occurs (doesn't make sense to wait more) */ - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) - break; - udelay(100); - if (delay-- == 0) - break; - } - return (c); -} - -/* - * issue an atapi command - */ -unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char c, err, mask, res; - int n; - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - mask = ATA_STAT_BUSY | ATA_STAT_DRQ; - res = 0; - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - printf("ATAPI_ISSUE: device %d not ready status %X\n", device, - c); - err = 0xFF; - goto AI_OUT; - } - /* write taskfile */ - ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_SECT_NUM, 0); - ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); - ide_outb(device, ATA_CYL_HIGH, - (unsigned char) ((buflen >> 8) & 0xFF)); - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - - ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); - udelay(50); - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - - if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ - printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); - err = 0xFF; - goto AI_OUT; - } - - /* write command block */ - ide_output_data_shorts(device, (unsigned short *) ccb, ccblen / 2); - - /* ATAPI Command written wait for completition */ - udelay(5000); /* device must set bsy */ - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - /* - * if no data wait for DRQ = 0 BSY = 0 - * if data wait for DRQ = 1 BSY = 0 - */ - res = 0; - if (buflen) - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - if (c & ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG)) >> 4; - debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); - } else { - printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); - err = 0xFF; - } - goto AI_OUT; - } - n = ide_inb(device, ATA_CYL_HIGH); - n <<= 8; - n += ide_inb(device, ATA_CYL_LOW); - if (n > buflen) { - printf("ERROR, transfer bytes %d requested only %d\n", n, - buflen); - err = 0xff; - goto AI_OUT; - } - if ((n == 0) && (buflen < 0)) { - printf("ERROR, transfer bytes %d requested %d\n", n, buflen); - err = 0xff; - goto AI_OUT; - } - if (n != buflen) { - debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); - } - if (n != 0) { /* data transfer */ - debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); - /* we transfer shorts */ - n >>= 1; - /* ok now decide if it is an in or output */ - if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { - debug("Write to device\n"); - ide_output_data_shorts(device, - (unsigned short *) buffer, n); - } else { - debug("Read from device @ %p shorts %d\n", buffer, n); - ide_input_data_shorts(device, - (unsigned short *) buffer, n); - } - } - udelay(5000); /* seems that some CD ROMs need this... */ - mask = ATA_STAT_BUSY | ATA_STAT_ERR; - res = 0; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG) >> 4); - debug("atapi_issue 2 returned sense key %X status %X\n", err, - c); - } else { - err = 0; - } -AI_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return (err); -} - -/* - * sending the command to atapi_issue. If an status other than good - * returns, an request_sense will be issued - */ - -#define ATAPI_DRIVE_NOT_READY 100 -#define ATAPI_UNIT_ATTN 10 - -unsigned char atapi_issue_autoreq(int device, - unsigned char *ccb, - int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char sense_data[18], sense_ccb[12]; - unsigned char res, key, asc, ascq; - int notready, unitattn; - - unitattn = ATAPI_UNIT_ATTN; - notready = ATAPI_DRIVE_NOT_READY; - -retry: - res = atapi_issue(device, ccb, ccblen, buffer, buflen); - if (res == 0) - return 0; /* Ok */ - - if (res == 0xFF) - return 0xFF; /* error */ - - debug("(auto_req)atapi_issue returned sense key %X\n", res); - - memset(sense_ccb, 0, sizeof(sense_ccb)); - memset(sense_data, 0, sizeof(sense_data)); - sense_ccb[0] = ATAPI_CMD_REQ_SENSE; - sense_ccb[4] = 18; /* allocation Length */ - - res = atapi_issue(device, sense_ccb, 12, sense_data, 18); - key = (sense_data[2] & 0xF); - asc = (sense_data[12]); - ascq = (sense_data[13]); - - debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); - debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", - sense_data[0], key, asc, ascq); - - if ((key == 0)) - return 0; /* ok device ready */ - - if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ - if (unitattn-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); - goto error; - } - if ((asc == 0x4) && (ascq == 0x1)) { - /* not ready, but will be ready soon */ - if (notready-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Drive not ready, tried %d times\n", - ATAPI_DRIVE_NOT_READY); - goto error; - } - if (asc == 0x3a) { - debug("Media not present\n"); - goto error; - } - - printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, - ascq); -error: - debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return (0xFF); -} - - -static void atapi_inquiry(block_dev_desc_t *dev_desc) -{ - unsigned char ccb[12]; /* Command descriptor block */ - unsigned char iobuf[64]; /* temp buf */ - unsigned char c; - int device; - - device = dev_desc->dev; - dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ - dev_desc->block_read = atapi_read; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - - ccb[0] = ATAPI_CMD_INQUIRY; - ccb[4] = 40; /* allocation Legnth */ - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 40); - - debug("ATAPI_CMD_INQUIRY returned %x\n", c); - if (c != 0) - return; - - /* copy device ident strings */ - ident_cpy((unsigned char *) dev_desc->vendor, &iobuf[8], 8); - ident_cpy((unsigned char *) dev_desc->product, &iobuf[16], 16); - ident_cpy((unsigned char *) dev_desc->revision, &iobuf[32], 5); - - dev_desc->lun = 0; - dev_desc->lba = 0; - dev_desc->blksz = 0; - dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); - dev_desc->type = iobuf[0] & 0x1f; - - if ((iobuf[1] & 0x80) == 0x80) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_START_STOP; - ccb[4] = 0x03; /* start */ - - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); - - debug("ATAPI_CMD_START_STOP returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); - - debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_READ_CAP; - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 8); - debug("ATAPI_CMD_READ_CAP returned %x\n", c); - if (c != 0) - return; - - debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", - iobuf[0], iobuf[1], iobuf[2], iobuf[3], - iobuf[4], iobuf[5], iobuf[6], iobuf[7]); - - dev_desc->lba = ((unsigned long) iobuf[0] << 24) + - ((unsigned long) iobuf[1] << 16) + - ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); - dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + - ((unsigned long) iobuf[5] << 16) + - ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); - dev_desc->log2blksz = LOG2(dev_desc->blksz); -#ifdef CONFIG_LBA48 - /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ - dev_desc->lba48 = 0; -#endif - return; -} - - -/* - * atapi_read: - * we transfer only one block per command, since the multiple DRQ per - * command is not yet implemented - */ -#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ -#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ -#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) - -ulong atapi_read(block_dev_desc_t *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->dev; - ulong n = 0; - unsigned char ccb[12]; /* Command descriptor block */ - ulong cnt; - - debug("atapi_read dev %d start " LBAF " blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); - - do { - if (blkcnt > ATAPI_READ_MAX_BLOCK) - cnt = ATAPI_READ_MAX_BLOCK; - else - cnt = blkcnt; - - ccb[0] = ATAPI_CMD_READ_12; - ccb[1] = 0; /* reserved */ - ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ - ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ - ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; - ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ - ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ - ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; - ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; - ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ - ccb[10] = 0; /* reserved */ - ccb[11] = 0; /* reserved */ - - if (atapi_issue_autoreq(device, ccb, 12, - (unsigned char *) buffer, - cnt * ATAPI_READ_BLOCK_SIZE) - == 0xFF) { - return (n); - } - n += cnt; - blkcnt -= cnt; - blknr += cnt; - buffer += (cnt * ATAPI_READ_BLOCK_SIZE); - } while (blkcnt > 0); - return (n); -} - -/* ------------------------------------------------------------------------- */ - -#endif /* CONFIG_ATAPI */ - -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/cmd/cmd_immap.c b/cmd/cmd_immap.c deleted file mode 100644 index 1414f9a..0000000 --- a/cmd/cmd_immap.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * (C) Copyright 2000-2003 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * MPC8xx/MPC8260 Internal Memory Map Functions - */ - -#include -#include - -#if defined(CONFIG_8xx) || defined(CONFIG_MPC8260) - -#if defined(CONFIG_8xx) -#include -#include -#include -#elif defined(CONFIG_MPC8260) -#include -#include -#include -#endif - -DECLARE_GLOBAL_DATA_PTR; - -static void -unimplemented ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - printf ("Sorry, but the '%s' command has not been implemented\n", - cmdtp->name); -} - -int -do_siuinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; - -#if defined(CONFIG_8xx) - volatile sysconf8xx_t *sc = &immap->im_siu_conf; -#elif defined(CONFIG_MPC8260) - volatile sysconf8260_t *sc = &immap->im_siu_conf; -#endif - - printf ("SIUMCR= %08x SYPCR = %08x\n", sc->sc_siumcr, sc->sc_sypcr); -#if defined(CONFIG_8xx) - printf ("SWT = %08x\n", sc->sc_swt); - printf ("SIPEND= %08x SIMASK= %08x\n", sc->sc_sipend, sc->sc_simask); - printf ("SIEL = %08x SIVEC = %08x\n", sc->sc_siel, sc->sc_sivec); - printf ("TESR = %08x SDCR = %08x\n", sc->sc_tesr, sc->sc_sdcr); -#elif defined(CONFIG_MPC8260) - printf ("BCR = %08x\n", sc->sc_bcr); - printf ("P_ACR = %02x P_ALRH= %08x P_ALRL= %08x\n", - sc->sc_ppc_acr, sc->sc_ppc_alrh, sc->sc_ppc_alrl); - printf ("L_ACR = %02x L_ALRH= %08x L_ALRL= %08x\n", - sc->sc_lcl_acr, sc->sc_lcl_alrh, sc->sc_lcl_alrl); - printf ("PTESR1= %08x PTESR2= %08x\n", sc->sc_tescr1, sc->sc_tescr2); - printf ("LTESR1= %08x LTESR2= %08x\n", sc->sc_ltescr1, sc->sc_ltescr2); - printf ("PDTEA = %08x PDTEM = %02x\n", sc->sc_pdtea, sc->sc_pdtem); - printf ("LDTEA = %08x LDTEM = %02x\n", sc->sc_ldtea, sc->sc_ldtem); -#endif - return 0; -} - -int -do_memcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; - -#if defined(CONFIG_8xx) - volatile memctl8xx_t *memctl = &immap->im_memctl; - int nbanks = 8; -#elif defined(CONFIG_MPC8260) - volatile memctl8260_t *memctl = &immap->im_memctl; - int nbanks = 12; -#endif - volatile uint *p = &memctl->memc_br0; - int i; - - for (i = 0; i < nbanks; i++, p += 2) { - if (i < 10) { - printf ("BR%d = %08x OR%d = %08x\n", - i, p[0], i, p[1]); - } else { - printf ("BR%d = %08x OR%d = %08x\n", - i, p[0], i, p[1]); - } - } - - printf ("MAR = %08x", memctl->memc_mar); -#if defined(CONFIG_8xx) - printf (" MCR = %08x\n", memctl->memc_mcr); -#elif defined(CONFIG_MPC8260) - putc ('\n'); -#endif - printf ("MAMR = %08x MBMR = %08x", - memctl->memc_mamr, memctl->memc_mbmr); -#if defined(CONFIG_8xx) - printf ("\nMSTAT = %04x\n", memctl->memc_mstat); -#elif defined(CONFIG_MPC8260) - printf (" MCMR = %08x\n", memctl->memc_mcmr); -#endif - printf ("MPTPR = %04x MDR = %08x\n", - memctl->memc_mptpr, memctl->memc_mdr); -#if defined(CONFIG_MPC8260) - printf ("PSDMR = %08x LSDMR = %08x\n", - memctl->memc_psdmr, memctl->memc_lsdmr); - printf ("PURT = %02x PSRT = %02x\n", - memctl->memc_purt, memctl->memc_psrt); - printf ("LURT = %02x LSRT = %02x\n", - memctl->memc_lurt, memctl->memc_lsrt); - printf ("IMMR = %08x\n", memctl->memc_immr); -#endif - return 0; -} - -int -do_sitinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} - -#ifdef CONFIG_MPC8260 -int -do_icinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} -#endif - -int -do_carinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; - -#if defined(CONFIG_8xx) - volatile car8xx_t *car = &immap->im_clkrst; -#elif defined(CONFIG_MPC8260) - volatile car8260_t *car = &immap->im_clkrst; -#endif - -#if defined(CONFIG_8xx) - printf ("SCCR = %08x\n", car->car_sccr); - printf ("PLPRCR= %08x\n", car->car_plprcr); - printf ("RSR = %08x\n", car->car_rsr); -#elif defined(CONFIG_MPC8260) - printf ("SCCR = %08x\n", car->car_sccr); - printf ("SCMR = %08x\n", car->car_scmr); - printf ("RSR = %08x\n", car->car_rsr); - printf ("RMR = %08x\n", car->car_rmr); -#endif - return 0; -} - -static int counter; - -static void -header(void) -{ - char *data = "\ - -------------------------------- --------------------------------\ - 00000000001111111111222222222233 00000000001111111111222222222233\ - 01234567890123456789012345678901 01234567890123456789012345678901\ - -------------------------------- --------------------------------\ - "; - int i; - - if (counter % 2) - putc('\n'); - counter = 0; - - for (i = 0; i < 4; i++, data += 79) - printf("%.79s\n", data); -} - -static void binary (char *label, uint value, int nbits) -{ - uint mask = 1 << (nbits - 1); - int i, second = (counter++ % 2); - - if (second) - putc (' '); - puts (label); - for (i = 32 + 1; i != nbits; i--) - putc (' '); - - while (mask != 0) { - if (value & mask) - putc ('1'); - else - putc ('0'); - mask >>= 1; - } - - if (second) - putc ('\n'); -} - -#if defined(CONFIG_8xx) -#define PA_NBITS 16 -#define PA_NB_ODR 8 -#define PB_NBITS 18 -#define PB_NB_ODR 16 -#define PC_NBITS 12 -#define PD_NBITS 13 -#elif defined(CONFIG_MPC8260) -#define PA_NBITS 32 -#define PA_NB_ODR 32 -#define PB_NBITS 28 -#define PB_NB_ODR 28 -#define PC_NBITS 32 -#define PD_NBITS 28 -#endif - -int -do_iopinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; - -#if defined(CONFIG_8xx) - volatile iop8xx_t *iop = &immap->im_ioport; - volatile ushort *l, *r; -#elif defined(CONFIG_MPC8260) - volatile iop8260_t *iop = &immap->im_ioport; - volatile uint *l, *r; -#endif - volatile uint *R; - - counter = 0; - header (); - - /* - * Ports A & B - */ - -#if defined(CONFIG_8xx) - l = &iop->iop_padir; - R = &immap->im_cpm.cp_pbdir; -#elif defined(CONFIG_MPC8260) - l = &iop->iop_pdira; - R = &iop->iop_pdirb; -#endif - binary ("PA_DIR", *l++, PA_NBITS); - binary ("PB_DIR", *R++, PB_NBITS); - binary ("PA_PAR", *l++, PA_NBITS); - binary ("PB_PAR", *R++, PB_NBITS); -#if defined(CONFIG_MPC8260) - binary ("PA_SOR", *l++, PA_NBITS); - binary ("PB_SOR", *R++, PB_NBITS); -#endif - binary ("PA_ODR", *l++, PA_NB_ODR); - binary ("PB_ODR", *R++, PB_NB_ODR); - binary ("PA_DAT", *l++, PA_NBITS); - binary ("PB_DAT", *R++, PB_NBITS); - - header (); - - /* - * Ports C & D - */ - -#if defined(CONFIG_8xx) - l = &iop->iop_pcdir; - r = &iop->iop_pddir; -#elif defined(CONFIG_MPC8260) - l = &iop->iop_pdirc; - r = &iop->iop_pdird; -#endif - binary ("PC_DIR", *l++, PC_NBITS); - binary ("PD_DIR", *r++, PD_NBITS); - binary ("PC_PAR", *l++, PC_NBITS); - binary ("PD_PAR", *r++, PD_NBITS); -#if defined(CONFIG_8xx) - binary ("PC_SO ", *l++, PC_NBITS); - binary (" ", 0, 0); - r++; -#elif defined(CONFIG_MPC8260) - binary ("PC_SOR", *l++, PC_NBITS); - binary ("PD_SOR", *r++, PD_NBITS); - binary ("PC_ODR", *l++, PC_NBITS); - binary ("PD_ODR", *r++, PD_NBITS); -#endif - binary ("PC_DAT", *l++, PC_NBITS); - binary ("PD_DAT", *r++, PD_NBITS); -#if defined(CONFIG_8xx) - binary ("PC_INT", *l++, PC_NBITS); -#endif - - header (); - return 0; -} - -/* - * set the io pins - * this needs a clean up for smaller tighter code - * use *uint and set the address based on cmd + port - */ -int -do_iopset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - uint rcode = 0; - iopin_t iopin; - static uint port = 0; - static uint pin = 0; - static uint value = 0; - static enum { - DIR, - PAR, - SOR, - ODR, - DAT, -#if defined(CONFIG_8xx) - INT -#endif - } cmd = DAT; - - if (argc != 5) { - puts ("iopset PORT PIN CMD VALUE\n"); - return 1; - } - port = argv[1][0] - 'A'; - if (port > 3) - port -= 0x20; - if (port > 3) - rcode = 1; - pin = simple_strtol (argv[2], NULL, 10); - if (pin > 31) - rcode = 1; - - - switch (argv[3][0]) { - case 'd': - if (argv[3][1] == 'a') - cmd = DAT; - else if (argv[3][1] == 'i') - cmd = DIR; - else - rcode = 1; - break; - case 'p': - cmd = PAR; - break; - case 'o': - cmd = ODR; - break; - case 's': - cmd = SOR; - break; -#if defined(CONFIG_8xx) - case 'i': - cmd = INT; - break; -#endif - default: - printf ("iopset: unknown command %s\n", argv[3]); - rcode = 1; - } - if (argv[4][0] == '1') - value = 1; - else if (argv[4][0] == '0') - value = 0; - else - rcode = 1; - if (rcode == 0) { - iopin.port = port; - iopin.pin = pin; - iopin.flag = 0; - switch (cmd) { - case DIR: - if (value) - iopin_set_out (&iopin); - else - iopin_set_in (&iopin); - break; - case PAR: - if (value) - iopin_set_ded (&iopin); - else - iopin_set_gen (&iopin); - break; - case SOR: - if (value) - iopin_set_opt2 (&iopin); - else - iopin_set_opt1 (&iopin); - break; - case ODR: - if (value) - iopin_set_odr (&iopin); - else - iopin_set_act (&iopin); - break; - case DAT: - if (value) - iopin_set_high (&iopin); - else - iopin_set_low (&iopin); - break; -#if defined(CONFIG_8xx) - case INT: - if (value) - iopin_set_falledge (&iopin); - else - iopin_set_anyedge (&iopin); - break; -#endif - } - - } - return rcode; -} - -int -do_dmainfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} - -int -do_fccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} - -static void prbrg (int n, uint val) -{ - uint extc = (val >> 14) & 3; - uint cd = (val & CPM_BRG_CD_MASK) >> 1; - uint div16 = (val & CPM_BRG_DIV16) != 0; - -#if defined(CONFIG_8xx) - ulong clock = gd->cpu_clk; -#elif defined(CONFIG_MPC8260) - ulong clock = gd->arch.brg_clk; -#endif - - printf ("BRG%d:", n); - - if (val & CPM_BRG_RST) - puts (" RESET"); - else - puts (" "); - - if (val & CPM_BRG_EN) - puts (" ENABLED"); - else - puts (" DISABLED"); - - printf (" EXTC=%d", extc); - - if (val & CPM_BRG_ATB) - puts (" ATB"); - else - puts (" "); - - printf (" DIVIDER=%4d", cd); - if (extc == 0 && cd != 0) { - uint baudrate; - - if (div16) - baudrate = (clock / 16) / (cd + 1); - else - baudrate = clock / (cd + 1); - - printf ("=%6d bps", baudrate); - } else { - puts (" "); - } - - if (val & CPM_BRG_DIV16) - puts (" DIV16"); - else - puts (" "); - - putc ('\n'); -} - -int -do_brginfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; - -#if defined(CONFIG_8xx) - volatile cpm8xx_t *cp = &immap->im_cpm; - volatile uint *p = &cp->cp_brgc1; -#elif defined(CONFIG_MPC8260) - volatile uint *p = &immap->im_brgc1; -#endif - int i = 1; - - while (i <= 4) - prbrg (i++, *p++); - -#if defined(CONFIG_MPC8260) - p = &immap->im_brgc5; - while (i <= 8) - prbrg (i++, *p++); -#endif - return 0; -} - -int -do_i2cinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; - -#if defined(CONFIG_8xx) - volatile i2c8xx_t *i2c = &immap->im_i2c; - volatile cpm8xx_t *cp = &immap->im_cpm; - volatile iic_t *iip = (iic_t *) & cp->cp_dparam[PROFF_IIC]; -#elif defined(CONFIG_MPC8260) - volatile i2c8260_t *i2c = &immap->im_i2c; - volatile iic_t *iip; - uint dpaddr; - - dpaddr = immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)]; - if (dpaddr == 0) - iip = NULL; - else - iip = (iic_t *) & immap->im_dprambase[dpaddr]; -#endif - - printf ("I2MOD = %02x I2ADD = %02x\n", i2c->i2c_i2mod, i2c->i2c_i2add); - printf ("I2BRG = %02x I2COM = %02x\n", i2c->i2c_i2brg, i2c->i2c_i2com); - printf ("I2CER = %02x I2CMR = %02x\n", i2c->i2c_i2cer, i2c->i2c_i2cmr); - - if (iip == NULL) - puts ("i2c parameter ram not allocated\n"); - else { - printf ("RBASE = %08x TBASE = %08x\n", - iip->iic_rbase, iip->iic_tbase); - printf ("RFCR = %02x TFCR = %02x\n", - iip->iic_rfcr, iip->iic_tfcr); - printf ("MRBLR = %04x\n", iip->iic_mrblr); - printf ("RSTATE= %08x RDP = %08x\n", - iip->iic_rstate, iip->iic_rdp); - printf ("RBPTR = %04x RBC = %04x\n", - iip->iic_rbptr, iip->iic_rbc); - printf ("RXTMP = %08x\n", iip->iic_rxtmp); - printf ("TSTATE= %08x TDP = %08x\n", - iip->iic_tstate, iip->iic_tdp); - printf ("TBPTR = %04x TBC = %04x\n", - iip->iic_tbptr, iip->iic_tbc); - printf ("TXTMP = %08x\n", iip->iic_txtmp); - } - return 0; -} - -int -do_sccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} - -int -do_smcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} - -int -do_spiinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} - -int -do_muxinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} - -int -do_siinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} - -int -do_mccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unimplemented (cmdtp, flag, argc, argv); - return 0; -} - -/***************************************************/ - -U_BOOT_CMD( - siuinfo, 1, 1, do_siuinfo, - "print System Interface Unit (SIU) registers", - "" -); - -U_BOOT_CMD( - memcinfo, 1, 1, do_memcinfo, - "print Memory Controller registers", - "" -); - -U_BOOT_CMD( - sitinfo, 1, 1, do_sitinfo, - "print System Integration Timers (SIT) registers", - "" -); - -#ifdef CONFIG_MPC8260 -U_BOOT_CMD( - icinfo, 1, 1, do_icinfo, - "print Interrupt Controller registers", - "" -); -#endif - -U_BOOT_CMD( - carinfo, 1, 1, do_carinfo, - "print Clocks and Reset registers", - "" -); - -U_BOOT_CMD( - iopinfo, 1, 1, do_iopinfo, - "print I/O Port registers", - "" -); - -U_BOOT_CMD( - iopset, 5, 0, do_iopset, - "set I/O Port registers", - "PORT PIN CMD VALUE\nPORT: A-D, PIN: 0-31, CMD: [dat|dir|odr|sor], VALUE: 0|1" -); - -U_BOOT_CMD( - dmainfo, 1, 1, do_dmainfo, - "print SDMA/IDMA registers", - "" -); - -U_BOOT_CMD( - fccinfo, 1, 1, do_fccinfo, - "print FCC registers", - "" -); - -U_BOOT_CMD( - brginfo, 1, 1, do_brginfo, - "print Baud Rate Generator (BRG) registers", - "" -); - -U_BOOT_CMD( - i2cinfo, 1, 1, do_i2cinfo, - "print I2C registers", - "" -); - -U_BOOT_CMD( - sccinfo, 1, 1, do_sccinfo, - "print SCC registers", - "" -); - -U_BOOT_CMD( - smcinfo, 1, 1, do_smcinfo, - "print SMC registers", - "" -); - -U_BOOT_CMD( - spiinfo, 1, 1, do_spiinfo, - "print Serial Peripheral Interface (SPI) registers", - "" -); - -U_BOOT_CMD( - muxinfo, 1, 1, do_muxinfo, - "print CPM Multiplexing registers", - "" -); - -U_BOOT_CMD( - siinfo, 1, 1, do_siinfo, - "print Serial Interface (SI) registers", - "" -); - -U_BOOT_CMD( - mccinfo, 1, 1, do_mccinfo, - "print MCC registers", - "" -); - -#endif diff --git a/cmd/cmd_ini.c b/cmd/cmd_ini.c deleted file mode 100644 index 727fd1c..0000000 --- a/cmd/cmd_ini.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * inih -- simple .INI file parser - * - * Copyright (c) 2009, Brush Technology - * Copyright (c) 2012: - * Joe Hershberger, National Instruments, joe.hershberger@ni.com - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Go to the project home page for more info: - * http://code.google.com/p/inih/ - */ - -#include -#include -#include -#include -#include - -#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 - setenv(name, value); - printf("ini: Imported %s as %s\n", name, value); - } - - /* success */ - return 1; -} - -static int do_ini(cmd_tbl_t *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 ? getenv("loadaddr") : argv[2], NULL, 16); - file_size = (size_t)simple_strtoul( - argc < 4 ? getenv("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/cmd/cmd_io.c b/cmd/cmd_io.c deleted file mode 100644 index c59148f..0000000 --- a/cmd/cmd_io.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2012 The Chromium OS Authors. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * IO space access commands. - */ - -#include -#include -#include - -/* - * IO Display - * - * Syntax: - * iod{.b, .w, .l} {addr} - */ -int do_io_iod(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - ulong addr; - int size; - - if (argc != 2) - return CMD_RET_USAGE; - - size = cmd_get_data_size(argv[0], 4); - if (size < 0) - return 1; - - addr = simple_strtoul(argv[1], NULL, 16); - - printf("%04x: ", (u16) addr); - - if (size == 4) - printf("%08x\n", inl(addr)); - else if (size == 2) - printf("%04x\n", inw(addr)); - else - printf("%02x\n", inb(addr)); - - return 0; -} - -int do_io_iow(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - ulong addr, size, val; - - 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, 2, 0, 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/cmd/cmd_iotrace.c b/cmd/cmd_iotrace.c deleted file mode 100644 index f54276d..0000000 --- a/cmd/cmd_iotrace.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2014 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -static void do_print_stats(void) -{ - ulong start, size, offset, count; - - printf("iotrace is %sabled\n", iotrace_get_enabled() ? "en" : "dis"); - iotrace_get_buffer(&start, &size, &offset, &count); - printf("Start: %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 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; -} - -int do_iotrace(cmd_tbl_t *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 'p': - iotrace_set_enabled(0); - break; - case 'r': - iotrace_set_enabled(1); - break; - case 's': - do_print_stats(); - 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
- set iotrace buffer\n" - "iotrace pause - pause tracing\n" - "iotrace resume - resume tracing" -); diff --git a/cmd/cmd_irq.c b/cmd/cmd_irq.c deleted file mode 100644 index 02da450..0000000 --- a/cmd/cmd_irq.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2008 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -static int do_interrupts(cmd_tbl_t *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 (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); - -U_BOOT_CMD( - irqinfo, 1, 1, do_irqinfo, - "print information about IRQs", - "" -); diff --git a/cmd/cmd_itest.c b/cmd/cmd_itest.c deleted file mode 100644 index 91ae5c2..0000000 --- a/cmd/cmd_itest.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * (C) Copyright 2003 - * Tait Electronics Limited, Christchurch, New Zealand - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * 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 -#include -#include -#include - -#include - -#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) { - puts("Failed to map physical memory\n"); - return 0; - } - switch (w) { - case 1: - l = (long)(*(unsigned char *)buf); - break; - case 2: - l = (long)(*(unsigned short *)buf); - break; - case 4: - l = (long)(*(unsigned long *)buf); - break; - } - unmap_physmem(buf, w); - return l; - } else { - l = simple_strtoul(s, NULL, 16); - } - - return 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 getenv((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(cmd_tbl_t *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: - value = binary_test (argv[2], argv[1], argv[3], w); - break; - case -2: - value = binary_test (argv[2], argv[1], argv[3], 0); - break; - case -1: - 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", - "[.b, .w, .l, .s] [*]value1 [*]value2" -); diff --git a/cmd/cmd_jffs2.c b/cmd/cmd_jffs2.c deleted file mode 100644 index bce0983..0000000 --- a/cmd/cmd_jffs2.c +++ /dev/null @@ -1,619 +0,0 @@ -/* - * (C) Copyright 2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2002 - * Robert Schwebel, Pengutronix, - * - * (C) Copyright 2003 - * Kai-Uwe Bloem, Auerswald GmbH & Co KG, - * - * (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 - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Three environment variables are used by the parsing routines: - * - * 'partition' - keeps current partition identifier - * - * partition := - * := ,part_num - * - * - * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping - * - * mtdids=[,,...] - * - * := = - * := 'nand'|'nor'|'onenand' - * := mtd device number, 0... - * := unique device tag used by linux kernel to find mtd device (mtd->name) - * - * - * 'mtdparts' - partition list - * - * mtdparts=mtdparts=[;...] - * - * := :[,...] - * := unique device tag used by linux kernel to find mtd device (mtd->name) - * := [@][][] - * := standard linux memsize OR '-' to denote all remaining space - * := partition start offset within the device - * := '(' NAME ')' - * := when set to 'ro' makes partition read-only (not used, passed to kernel) - * - * Notes: - * - each 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 -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_NAND) -#include -#include -#endif - -#if defined(CONFIG_CMD_ONENAND) -#include -#include -#include -#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) - if (num < CONFIG_SYS_MAX_NAND_DEVICE) { - *size = nand_info[num].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 := 'nand'|'nor'|'onenand', - * 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) - nand_info_t *nand; - - nand = &nand_info[id->num]; - - return nand->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(¤t_mtd_dev->link); - current_mtd_dev->num_parts = 1; - INIT_LIST_HEAD(¤t_mtd_dev->parts); - list_add(&part->link, ¤t_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *fsname; - char *filename; - int size; - struct part_info *part; - ulong offset = load_addr; - - /* pre-set Boot file name */ - if ((filename = getenv("bootfile")) == NULL) { - filename = "uImage"; - } - - if (argc == 2) { - filename = argv[1]; - } - if (argc == 3) { - offset = simple_strtoul(argv[1], NULL, 16); - 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); - setenv_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(cmd_tbl_t *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(cmd_tbl_t *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( - ls, 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/cmd/cmd_ldrinfo.c b/cmd/cmd_ldrinfo.c deleted file mode 100644 index 2aa56bd..0000000 --- a/cmd/cmd_ldrinfo.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * U-boot - ldrinfo - * - * Copyright (c) 2010 Analog Devices Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include - -#include -#include - -static uint32_t ldrinfo_header(const void *addr) -{ - uint32_t skip = 0; - -#if defined(__ADSPBF561__) - /* BF56x has a 4 byte global header */ - uint32_t header, sign; - static const char * const spi_speed[] = { - "500K", "1M", "2M", "??", - }; - - memcpy(&header, addr, sizeof(header)); - - sign = (header & GFLAG_56X_SIGN_MASK) >> GFLAG_56X_SIGN_SHIFT; - printf("Header: %08X ( %s-bit-flash wait:%i hold:%i spi:%s %s)\n", - header, - (header & GFLAG_56X_16BIT_FLASH) ? "16" : "8", - (header & GFLAG_56X_WAIT_MASK) >> GFLAG_56X_WAIT_SHIFT, - (header & GFLAG_56X_HOLD_MASK) >> GFLAG_56X_HOLD_SHIFT, - spi_speed[(header & GFLAG_56X_SPI_MASK) >> GFLAG_56X_SPI_SHIFT], - sign == GFLAG_56X_SIGN_MAGIC ? "" : "!!hdrsign!! "); - - skip = 4; -#endif - - /* |Block @ 12345678: 12345678 12345678 12345678 12345678 | */ -#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ - defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ - defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) - printf(" Address Count Flags\n"); -#else - printf(" BCode Address Count Argument\n"); -#endif - - return skip; -} - -struct ldr_flag { - uint16_t flag; - const char *desc; -}; - -static uint32_t ldrinfo_block(const void *base_addr) -{ - uint32_t count; - - printf("Block @ %08X: ", (uint32_t)base_addr); - -#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ - defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ - defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) - - uint32_t addr, pval; - uint16_t flags; - int i; - static const struct ldr_flag ldr_flags[] = { - { BFLAG_53X_ZEROFILL, "zerofill" }, - { BFLAG_53X_RESVECT, "resvect" }, - { BFLAG_53X_INIT, "init" }, - { BFLAG_53X_IGNORE, "ignore" }, - { BFLAG_53X_COMPRESSED, "compressed"}, - { BFLAG_53X_FINAL, "final" }, - }; - - memcpy(&addr, base_addr, sizeof(addr)); - memcpy(&count, base_addr+4, sizeof(count)); - memcpy(&flags, base_addr+8, sizeof(flags)); - - printf("%08X %08X %04X ( ", addr, count, flags); - - for (i = 0; i < ARRAY_SIZE(ldr_flags); ++i) - if (flags & ldr_flags[i].flag) - printf("%s ", ldr_flags[i].desc); - - pval = (flags & BFLAG_53X_PFLAG_MASK) >> BFLAG_53X_PFLAG_SHIFT; - if (pval) - printf("gpio%i ", pval); - pval = (flags & BFLAG_53X_PPORT_MASK) >> BFLAG_53X_PPORT_SHIFT; - if (pval) - printf("port%c ", 'e' + pval); - - if (flags & BFLAG_53X_ZEROFILL) - count = 0; - if (flags & BFLAG_53X_FINAL) - count = 0; - else - count += sizeof(addr) + sizeof(count) + sizeof(flags); - -#else - - const uint8_t *raw8 = base_addr; - uint32_t bcode, addr, arg, sign, chk; - int i; - static const struct ldr_flag ldr_flags[] = { - { BFLAG_SAFE, "safe" }, - { BFLAG_AUX, "aux" }, - { BFLAG_FILL, "fill" }, - { BFLAG_QUICKBOOT, "quickboot" }, - { BFLAG_CALLBACK, "callback" }, - { BFLAG_INIT, "init" }, - { BFLAG_IGNORE, "ignore" }, - { BFLAG_INDIRECT, "indirect" }, - { BFLAG_FIRST, "first" }, - { BFLAG_FINAL, "final" }, - }; - - memcpy(&bcode, base_addr, sizeof(bcode)); - memcpy(&addr, base_addr+4, sizeof(addr)); - memcpy(&count, base_addr+8, sizeof(count)); - memcpy(&arg, base_addr+12, sizeof(arg)); - - printf("%08X %08X %08X %08X ( ", bcode, addr, count, arg); - - if (addr % 4) - printf("!!addralgn!! "); - if (count % 4) - printf("!!cntalgn!! "); - - sign = (bcode & BFLAG_HDRSIGN_MASK) >> BFLAG_HDRSIGN_SHIFT; - if (sign != BFLAG_HDRSIGN_MAGIC) - printf("!!hdrsign!! "); - - chk = 0; - for (i = 0; i < 16; ++i) - chk ^= raw8[i]; - if (chk) - printf("!!hdrchk!! "); - - printf("dma:%i ", bcode & BFLAG_DMACODE_MASK); - - for (i = 0; i < ARRAY_SIZE(ldr_flags); ++i) - if (bcode & ldr_flags[i].flag) - printf("%s ", ldr_flags[i].desc); - - if (bcode & BFLAG_FILL) - count = 0; - if (bcode & BFLAG_FINAL) - count = 0; - else - count += sizeof(bcode) + sizeof(addr) + sizeof(count) + sizeof(arg); - -#endif - - printf(")\n"); - - return count; -} - -static int do_ldrinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - const void *addr; - uint32_t skip; - - /* Get the address */ - if (argc < 2) - addr = (void *)load_addr; - else - addr = (void *)simple_strtoul(argv[1], NULL, 16); - - /* Walk the LDR */ - addr += ldrinfo_header(addr); - do { - skip = ldrinfo_block(addr); - addr += skip; - } while (skip); - - return 0; -} - -U_BOOT_CMD( - ldrinfo, 2, 0, do_ldrinfo, - "validate ldr image in memory", - "[addr]\n" -); diff --git a/cmd/cmd_led.c b/cmd/cmd_led.c deleted file mode 100644 index b0f1a61..0000000 --- a/cmd/cmd_led.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * (C) Copyright 2010 - * Jason Kridner - * - * Based on cmd_led.c patch from: - * http://www.mail-archive.com/u-boot@lists.denx.de/msg06873.html - * (C) Copyright 2008 - * Ulf Samuelsson - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -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_BOARD_SPECIFIC_LED -#ifdef STATUS_LED_BIT - { "0", STATUS_LED_BIT, NULL, NULL, NULL }, -#endif -#ifdef STATUS_LED_BIT1 - { "1", STATUS_LED_BIT1, NULL, NULL, NULL }, -#endif -#ifdef STATUS_LED_BIT2 - { "2", STATUS_LED_BIT2, NULL, NULL, NULL }, -#endif -#ifdef STATUS_LED_BIT3 - { "3", STATUS_LED_BIT3, NULL, NULL, NULL }, -#endif -#ifdef STATUS_LED_BIT4 - { "4", STATUS_LED_BIT4, NULL, NULL, NULL }, -#endif -#ifdef STATUS_LED_BIT5 - { "5", STATUS_LED_BIT5, NULL, NULL, NULL }, -#endif -#endif -#ifdef STATUS_LED_GREEN - { "green", STATUS_LED_GREEN, green_led_off, green_led_on, NULL }, -#endif -#ifdef STATUS_LED_YELLOW - { "yellow", STATUS_LED_YELLOW, yellow_led_off, yellow_led_on, NULL }, -#endif -#ifdef STATUS_LED_RED - { "red", STATUS_LED_RED, red_led_off, red_led_on, NULL }, -#endif -#ifdef STATUS_LED_BLUE - { "blue", STATUS_LED_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_led (cmd_tbl_t *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, - STATUS_LED_ON); - break; - case LED_OFF: - if (led_commands[i].off) - led_commands[i].off(); - else - __led_set(led_commands[i].mask, - STATUS_LED_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_led, - "[" -#ifdef CONFIG_BOARD_SPECIFIC_LED -#ifdef STATUS_LED_BIT - "0|" -#endif -#ifdef STATUS_LED_BIT1 - "1|" -#endif -#ifdef STATUS_LED_BIT2 - "2|" -#endif -#ifdef STATUS_LED_BIT3 - "3|" -#endif -#ifdef STATUS_LED_BIT4 - "4|" -#endif -#ifdef STATUS_LED_BIT5 - "5|" -#endif -#endif -#ifdef STATUS_LED_GREEN - "green|" -#endif -#ifdef STATUS_LED_YELLOW - "yellow|" -#endif -#ifdef STATUS_LED_RED - "red|" -#endif -#ifdef STATUS_LED_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/cmd/cmd_license.c b/cmd/cmd_license.c deleted file mode 100644 index b07de72..0000000 --- a/cmd/cmd_license.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * (C) Copyright 2007 by OpenMoko, Inc. - * Author: Harald Welte - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -/* COPYING is currently 15951 bytes in size */ -#define LICENSE_MAX 20480 - -#include -#include -#include - -int do_license(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *tok, *dst = malloc(LICENSE_MAX); - unsigned long len = LICENSE_MAX; - - if (!dst) - return -1; - - if (gunzip(dst, LICENSE_MAX, license_gz, &len) != 0) { - printf("Error uncompressing license text\n"); - free(dst); - return -1; - } - puts(dst); - free(dst); - - return 0; -} - -U_BOOT_CMD( - license, 1, 1, do_license, - "print GPL license text", - "" -); diff --git a/cmd/cmd_load.c b/cmd/cmd_load.c deleted file mode 100644 index 0aa7937..0000000 --- a/cmd/cmd_load.c +++ /dev/null @@ -1,1113 +0,0 @@ -/* - * (C) Copyright 2000-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Serial up- and download support - */ -#include -#include -#include -#include -#include -#include -#include - -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(cmd_tbl_t *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 - - if (((env_echo = getenv("loads_echo")) != NULL) && (*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 (getc() == '\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()) { - (void) getc(); - } - udelay(1000); - } - - if (addr == ~0) { - printf("## S-Record download aborted\n"); - rcode = 1; - } else { - printf("## Start Addr = 0x%08lX\n", addr); - 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 (getc() == 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; -#ifndef CONFIG_SYS_NO_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); - setenv_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 = getc(); /* 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 != getc) { - if (ctrlc()) { - return (-1); - } - } - } - - /* line too long - truncate */ - *p = '\0'; - return (p - buf); -} - -#if defined(CONFIG_CMD_SAVES) - -int do_save_serial (cmd_tbl_t *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 (getc() == '\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 (getc() == '\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 (getc() == 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(cmd_tbl_t *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 */ - if ((s = getenv("loadaddr")) != NULL) { - 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 (getc() == '\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) { - load_addr = 0; - printf("## Binary (kermit) download aborted\n"); - rcode = 1; - } else { - printf("## Start Addr = 0x%08lX\n", addr); - 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 (getc() == 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()) { - (void) getc(); - } - udelay(1000); - } - - flush_cache(offset, size); - - printf("## Total Size = 0x%08x = %d Bytes\n", size, size); - setenv_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 (getc ()) { - 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 = getc(); - if ((new_char & 0xE0) == 0) - goto packet_error; - sum += new_char & 0xff; - length = untochar(new_char); - /* get sequence number */ - new_char = getc(); - 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 = getc(); - 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 = getc(); - if ((new_char & 0xE0) == 0) - goto packet_error; - sum += new_char & 0xff; - len_hi = untochar(new_char); - new_char = getc(); - 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 = getc(); - 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 = getc(); - 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 = getc(); - 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 = getc(); - 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 (getc()); - 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; -#ifndef CONFIG_SYS_NO_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); - } - - } - } else { - printf("%s\n", xyzModem_error(err)); - } - - xyzModem_stream_close(&err); - xyzModem_stream_terminate(false, &getcxmodem); - - - flush_cache(offset, size); - - printf("## Total Size = 0x%08x = %d Bytes\n", size, size); - setenv_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)", - "[ off ] [ baud ]\n" - " - load binary file over serial line" - " with offset 'off' and baudrate 'baud'" -); - -U_BOOT_CMD( - loadx, 3, 0, do_load_serial_bin, - "load binary file over serial line (xmodem mode)", - "[ off ] [ baud ]\n" - " - load binary file over serial line" - " with offset 'off' and baudrate 'baud'" -); - -U_BOOT_CMD( - loady, 3, 0, do_load_serial_bin, - "load binary file over serial line (ymodem mode)", - "[ off ] [ baud ]\n" - " - load binary file over serial line" - " with offset 'off' and baudrate 'baud'" -); - -#endif /* CONFIG_CMD_LOADB */ - -/* -------------------------------------------------------------------- */ - -#if defined(CONFIG_CMD_HWFLOW) -int do_hwflow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - extern int hwflow_onoff(int); - - if (argc == 2) { - if (strcmp(argv[1], "off") == 0) - hwflow_onoff(-1); - else - if (strcmp(argv[1], "on") == 0) - hwflow_onoff(1); - else - return CMD_RET_USAGE; - } - printf("RTS/CTS hardware flow control: %s\n", hwflow_onoff(0) ? "on" : "off"); - return 0; -} - -/* -------------------------------------------------------------------- */ - -U_BOOT_CMD( - hwflow, 2, 0, do_hwflow, - "turn RTS/CTS hardware flow control in serial line on/off", - "[on|off]" -); - -#endif /* CONFIG_CMD_HWFLOW */ diff --git a/cmd/cmd_log.c b/cmd/cmd_log.c deleted file mode 100644 index 873ee40..0000000 --- a/cmd/cmd_log.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * (C) Copyright 2002-2007 - * Detlev Zundel, DENX Software Engineering, dzu@denx.de. - * - * Code used from linux/kernel/printk.c - * Copyright (C) 1991, 1992 Linus Torvalds - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Comments: - * - * After relocating the code, the environment variable "loglevel" is - * copied to console_loglevel. The functionality is similar to the - * handling in the Linux kernel, i.e. messages logged with a priority - * less than console_loglevel are also output to stdout. - * - * If you want messages with the default level (e.g. POST messages) to - * appear on stdout also, make sure the environment variable - * "loglevel" is set at boot time to a number higher than - * default_message_loglevel below. - */ - -/* - * Logbuffer handling routines - */ - -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -/* Local prototypes */ -static void logbuff_putc(struct stdio_dev *dev, const char c); -static void logbuff_puts(struct stdio_dev *dev, const char *s); -static int logbuff_printk(const char *line); - -static char buf[1024]; - -/* This combination will not print messages with the default loglevel */ -static unsigned console_loglevel = 3; -static unsigned default_message_loglevel = 4; -static unsigned log_version = 1; -#ifdef CONFIG_ALT_LB_ADDR -static volatile logbuff_t *log; -#else -static logbuff_t *log; -#endif -static char *lbuf; - -unsigned long __logbuffer_base(void) -{ - return CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - LOGBUFF_LEN; -} -unsigned long logbuffer_base(void) -__attribute__((weak, alias("__logbuffer_base"))); - -void logbuff_init_ptrs(void) -{ - unsigned long tag, post_word; - char *s; - -#ifdef CONFIG_ALT_LB_ADDR - log = (logbuff_t *)CONFIG_ALT_LH_ADDR; - lbuf = (char *)CONFIG_ALT_LB_ADDR; -#else - log = (logbuff_t *)(logbuffer_base()) - 1; - lbuf = (char *)log->buf; -#endif - - /* Set up log version */ - if ((s = getenv ("logversion")) != NULL) - log_version = (int)simple_strtoul(s, NULL, 10); - - if (log_version == 2) - tag = log->v2.tag; - else - tag = log->v1.tag; - post_word = post_word_load(); -#ifdef CONFIG_POST - /* The post routines have setup the word so we can simply test it */ - if (tag != LOGBUFF_MAGIC || (post_word & POST_COLDBOOT)) - logbuff_reset(); -#else - /* No post routines, so we do our own checking */ - if (tag != LOGBUFF_MAGIC || post_word != LOGBUFF_MAGIC) { - logbuff_reset (); - post_word_store (LOGBUFF_MAGIC); - } -#endif - if (log_version == 2 && (long)log->v2.start > (long)log->v2.con) - log->v2.start = log->v2.con; - - /* Initialize default loglevel if present */ - if ((s = getenv ("loglevel")) != NULL) - console_loglevel = (int)simple_strtoul(s, NULL, 10); - - gd->flags |= GD_FLG_LOGINIT; -} - -void logbuff_reset(void) -{ -#ifndef CONFIG_ALT_LB_ADDR - memset(log, 0, sizeof(logbuff_t)); -#endif - if (log_version == 2) { - log->v2.tag = LOGBUFF_MAGIC; -#ifdef CONFIG_ALT_LB_ADDR - log->v2.start = 0; - log->v2.con = 0; - log->v2.end = 0; - log->v2.chars = 0; -#endif - } else { - log->v1.tag = LOGBUFF_MAGIC; -#ifdef CONFIG_ALT_LB_ADDR - log->v1.dummy = 0; - log->v1.start = 0; - log->v1.size = 0; - log->v1.chars = 0; -#endif - } -} - -int drv_logbuff_init(void) -{ - struct stdio_dev logdev; - int rc; - - /* Device initialization */ - memset (&logdev, 0, sizeof (logdev)); - - strcpy (logdev.name, "logbuff"); - logdev.ext = 0; /* No extensions */ - logdev.flags = DEV_FLAGS_OUTPUT; /* Output only */ - logdev.putc = logbuff_putc; /* 'putc' function */ - logdev.puts = logbuff_puts; /* 'puts' function */ - - rc = stdio_register(&logdev); - - return (rc == 0) ? 1 : rc; -} - -static void logbuff_putc(struct stdio_dev *dev, const char c) -{ - char buf[2]; - buf[0] = c; - buf[1] = '\0'; - logbuff_printk(buf); -} - -static void logbuff_puts(struct stdio_dev *dev, const char *s) -{ - logbuff_printk (s); -} - -void logbuff_log(char *msg) -{ - if ((gd->flags & GD_FLG_LOGINIT)) { - logbuff_printk(msg); - } else { - /* - * Can happen only for pre-relocated errors as logging - * at that stage should be disabled - */ - puts (msg); - } -} - -/* - * Subroutine: do_log - * - * Description: Handler for 'log' command.. - * - * Inputs: argv[1] contains the subcommand - * - * Return: None - * - */ -int do_log(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct stdio_dev *sdev = NULL; - char *s; - unsigned long i, start, size; - - if (strcmp(argv[1], "append") == 0) { - /* Log concatenation of all arguments separated by spaces */ - for (i = 2; i < argc; i++) { - logbuff_printk(argv[i]); - logbuff_putc(sdev, (i < argc - 1) ? ' ' : '\n'); - } - return 0; - } - - switch (argc) { - - case 2: - if (strcmp(argv[1], "show") == 0) { - if (log_version == 2) { - start = log->v2.start; - size = log->v2.end - log->v2.start; - } else { - start = log->v1.start; - size = log->v1.size; - } - if (size > LOGBUFF_LEN) - size = LOGBUFF_LEN; - for (i = 0; i < size; i++) { - s = lbuf + ((start + i) & LOGBUFF_MASK); - putc(*s); - } - return 0; - } else if (strcmp(argv[1], "reset") == 0) { - logbuff_reset(); - return 0; - } else if (strcmp(argv[1], "info") == 0) { - printf("Logbuffer at %08lx\n", (unsigned long)lbuf); - if (log_version == 2) { - printf("log_start = %08lx\n", - log->v2.start); - printf("log_end = %08lx\n", log->v2.end); - printf("log_con = %08lx\n", log->v2.con); - printf("logged_chars = %08lx\n", - log->v2.chars); - } - else { - printf("log_start = %08lx\n", - log->v1.start); - printf("log_size = %08lx\n", - log->v1.size); - printf("logged_chars = %08lx\n", - log->v1.chars); - } - return 0; - } - return CMD_RET_USAGE; - - default: - return CMD_RET_USAGE; - } -} - -U_BOOT_CMD( - log, 255, 1, do_log, - "manipulate logbuffer", - "info - show pointer details\n" - "log reset - clear contents\n" - "log show - show contents\n" - "log append - append to the logbuffer" -); - -static int logbuff_printk(const char *line) -{ - int i; - char *msg, *p, *buf_end; - int line_feed; - static signed char msg_level = -1; - - strcpy(buf + 3, line); - i = strlen(line); - buf_end = buf + 3 + i; - for (p = buf + 3; p < buf_end; p++) { - msg = p; - if (msg_level < 0) { - if ( - p[0] != '<' || - p[1] < '0' || - p[1] > '7' || - p[2] != '>' - ) { - p -= 3; - p[0] = '<'; - p[1] = default_message_loglevel + '0'; - p[2] = '>'; - } else { - msg += 3; - } - msg_level = p[1] - '0'; - } - line_feed = 0; - for (; p < buf_end; p++) { - if (log_version == 2) { - lbuf[log->v2.end & LOGBUFF_MASK] = *p; - log->v2.end++; - if (log->v2.end - log->v2.start > LOGBUFF_LEN) - log->v2.start++; - log->v2.chars++; - } else { - lbuf[(log->v1.start + log->v1.size) & - LOGBUFF_MASK] = *p; - if (log->v1.size < LOGBUFF_LEN) - log->v1.size++; - else - log->v1.start++; - log->v1.chars++; - } - if (*p == '\n') { - line_feed = 1; - break; - } - } - if (msg_level < console_loglevel) { - printf("%s", msg); - } - if (line_feed) - msg_level = -1; - } - return i; -} diff --git a/cmd/cmd_lzmadec.c b/cmd/cmd_lzmadec.c deleted file mode 100644 index 1ad9ed6..0000000 --- a/cmd/cmd_lzmadec.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * (C) Copyright 2013 Patrice Bouchand - * 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. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -#include - -static int do_lzmadec(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - unsigned long src, dst; - unsigned long 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 = 0x%lX\n", src_len, src_len); - setenv_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/cmd/cmd_mac.c b/cmd/cmd_mac.c deleted file mode 100644 index 52d3ba0..0000000 --- a/cmd/cmd_mac.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2006 Freescale Semiconductor - * York Sun (yorksun@freescale.com) - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -extern int do_mac(cmd_tbl_t *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|0|1|2|3|4|5|6|7]\n" - "mac read\n" - " - read EEPROM content into memory\n" - "mac save\n" - " - save to the EEPROM\n" - "mac id\n" - " - program system id\n" - "mac num\n" - " - program system serial number\n" - "mac errata\n" - " - program errata data\n" - "mac date\n" - " - program date\n" - "mac ports\n" - " - program the number of ports\n" - "mac X\n" - " - program the MAC address for port X [X=0...7]" -); diff --git a/cmd/cmd_md5sum.c b/cmd/cmd_md5sum.c deleted file mode 100644 index 23bb81e..0000000 --- a/cmd/cmd_md5sum.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * (C) Copyright 2011 - * Joe Hershberger, National Instruments, joe.hershberger@ni.com - * - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -/* - * 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; - } - setenv(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 = getenv(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(cmd_tbl_t *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(cmd_tbl_t *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/cmd/cmd_mdio.c b/cmd/cmd_mdio.c deleted file mode 100644 index fb13d05..0000000 --- a/cmd/cmd_mdio.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * (C) Copyright 2011 Freescale Semiconductor, Inc - * Andy Fleming - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * MDIO Commands - */ - -#include -#include -#include -#include - - -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, 0); - if (end == input) - return -1; - - if ((*end == '-') && *(++end)) - *phi = simple_strtol(end, NULL, 0); - else if (*end == '\0') - *phi = *plo; - else - return -1; - - return 0; -} - -static int mdio_write_ranges(struct phy_device *phydev, struct mii_dev *bus, - int addrlo, - int addrhi, int devadlo, int devadhi, - int reglo, int reghi, unsigned short data, - int extended) -{ - int addr, devad, reg; - int err = 0; - - for (addr = addrlo; addr <= addrhi; addr++) { - for (devad = devadlo; devad <= devadhi; devad++) { - for (reg = reglo; reg <= reghi; reg++) { - if (!extended) - err = bus->write(bus, addr, 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 phy_device *phydev, struct mii_dev *bus, - int addrlo, - int addrhi, int devadlo, int devadhi, - int reglo, int reghi, int extended) -{ - int addr, devad, reg; - - printf("Reading from bus %s\n", bus->name); - for (addr = addrlo; addr <= addrhi; addr++) { - printf("PHY at address %d:\n", addr); - - for (devad = devadlo; devad <= devadhi; devad++) { - for (reg = reglo; reg <= reghi; reg++) { - int val; - - if (!extended) - val = bus->read(bus, addr, 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(cmd_tbl_t *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; - - /* - * 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 -1; - } - - if (!phydev->drv || - (!phydev->drv->writeext && (op[0] == 'w')) || - (!phydev->drv->readext && (op[0] == 'r'))) { - puts("PHY does not have extended functions\n"); - return -1; - } - } - } - - switch (op[0]) { - case 'w': - if (pos > 1) - data = simple_strtoul(argv[pos--], NULL, 16); - case 'r': - if (pos > 1) - if (extract_reg_range(argv[pos--], &devadlo, &devadhi, - ®lo, ®hi)) - return -1; - - default: - if (pos > 1) - if (extract_phy_range(&(argv[2]), pos - 1, &bus, - &phydev, &addrlo, &addrhi)) - return -1; - - break; - } - - 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(phydev, bus, addrlo, addrhi, devadlo, devadhi, - reglo, reghi, data, extended); - break; - - case 'r': - mdio_read_ranges(phydev, 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 [.] - " - "read PHY's register at .\n" - "mdio write [.] - " - "write PHY's register at .\n" - "mdio rx [.] - " - "read PHY's extended register at .\n" - "mdio wx [.] - " - "write PHY's extended register at .\n" - " may be:\n" - " \n" - " \n" - " \n" - " , and may be ranges, e.g. 1-5.4-0x1f.\n" -); diff --git a/cmd/cmd_mem.c b/cmd/cmd_mem.c deleted file mode 100644 index efa3929..0000000 --- a/cmd/cmd_mem.c +++ /dev/null @@ -1,1410 +0,0 @@ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Memory Functions - * - * Copied from FADS ROM, Dan Malek (dmalek@jlc.net) - */ - -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_HAS_DATAFLASH -#include -#endif -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#ifndef CONFIG_SYS_MEMTEST_SCRATCH -#define CONFIG_SYS_MEMTEST_SCRATCH 0 -#endif - -static int mod_mem(cmd_tbl_t *, 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; - -/* Memory Display - * - * Syntax: - * md{.b, .w, .l, .q} {addr} {len} - */ -#define DISP_LINE_LEN 16 -static int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - ulong addr, length; -#if defined(CONFIG_HAS_DATAFLASH) - ulong nbytes, linebytes; -#endif - 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); - } - -#if defined(CONFIG_HAS_DATAFLASH) - /* Print the lines. - * - * We buffer all read data, so we can make sure data is read only - * once, and all accesses are with the specified bus width. - */ - nbytes = length * size; - do { - char linebuf[DISP_LINE_LEN]; - void* p; - linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes; - - rc = read_dataflash(addr, (linebytes/size)*size, linebuf); - p = (rc == DATAFLASH_OK) ? linebuf : (void*)addr; - print_buffer(addr, p, size, linebytes/size, DISP_LINE_LEN/size); - - nbytes -= linebytes; - addr += linebytes; - if (ctrlc()) { - rc = 1; - break; - } - } while (nbytes > 0); -#else - -# if defined(CONFIG_BLACKFIN) - /* See if we're trying to display L1 inst */ - if (addr_bfin_on_chip_mem(addr)) { - char linebuf[DISP_LINE_LEN]; - ulong linebytes, nbytes = length * size; - do { - linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes; - memcpy(linebuf, (void *)addr, linebytes); - print_buffer(addr, linebuf, size, linebytes/size, DISP_LINE_LEN/size); - - nbytes -= linebytes; - addr += linebytes; - if (ctrlc()) { - rc = 1; - break; - } - } while (nbytes > 0); - } else -# endif - - { - ulong bytes = size * length; - const void *buf = map_sysmem(addr, bytes); - - /* Print the lines. */ - print_buffer(addr, buf, size, length, DISP_LINE_LEN / size); - addr += bytes; - unmap_sysmem(buf); - } -#endif - - dp_last_addr = addr; - dp_last_length = length; - dp_last_size = size; - return (rc); -} - -static int do_mem_mm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - return mod_mem (cmdtp, 1, flag, argc, argv); -} -static int do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - return mod_mem (cmdtp, 0, flag, argc, argv); -} - -static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - u64 writeval; -#else - ulong writeval; -#endif - 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. - */ -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - writeval = simple_strtoull(argv[2], NULL, 16); -#else - writeval = simple_strtoul(argv[2], NULL, 16); -#endif - - /* 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; -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - else if (size == 8) - *((u64 *)buf) = (u64)writeval; -#endif - else if (size == 2) - *((u16 *)buf) = (u16)writeval; - else - *((u8 *)buf) = (u8)writeval; - buf += size; - } - unmap_sysmem(start); - return 0; -} - -#ifdef CONFIG_MX_CYCLIC -static int do_mem_mdc(cmd_tbl_t *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 ms... */ - for (i=0; i ms... */ - for (i=0; i 0) { - if (size == 4) - *((u32 *)buf) = *((u32 *)src); -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - else if (size == 8) - *((u64 *)buf) = *((u64 *)src); -#endif - else if (size == 2) - *((u16 *)buf) = *((u16 *)src); - else - *((u8 *)buf) = *((u8 *)src); - src += size; - buf += size; - - /* reset watchdog from time to time */ - if ((count % (64 << 10)) == 0) - WATCHDOG_RESET(); - } - unmap_sysmem(buf); - unmap_sysmem(src); - - return 0; -} - -static int do_mem_base(cmd_tbl_t *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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - ulong addr, length, i, bytes; - int size; -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - volatile u64 *llp; -#endif - 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) { -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - if (size == 8) { - llp = (u64 *)buf; - for (;;) - i = *llp; - } -#endif - if (size == 4) { - longp = (u32 *)buf; - for (;;) - i = *longp; - } - if (size == 2) { - shortp = (u16 *)buf; - for (;;) - i = *shortp; - } - cp = (u8 *)buf; - for (;;) - i = *cp; - } - -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - if (size == 8) { - for (;;) { - llp = (u64 *)buf; - i = length; - while (i-- > 0) - *llp++; - } - } -#endif - 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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - ulong addr, length, i, bytes; - int size; -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - volatile u64 *llp; - u64 data; -#else - ulong data; -#endif - 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 */ -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - data = simple_strtoull(argv[3], NULL, 16); -#else - data = simple_strtoul(argv[3], NULL, 16); -#endif - - 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) { -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - if (size == 8) { - llp = (u64 *)buf; - for (;;) - *llp = data; - } -#endif - if (size == 4) { - longp = (u32 *)buf; - for (;;) - *longp = data; - } - if (size == 2) { - shortp = (u16 *)buf; - for (;;) - *shortp = data; - } - cp = (u8 *)buf; - for (;;) - *cp = data; - } - -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - if (size == 8) { - for (;;) { - llp = (u64 *)buf; - i = length; - while (i-- > 0) - *llp++ = data; - } - } -#endif - 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 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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - ulong start, end; - vu_long *buf, *dummy; - ulong iteration_limit = 0; - int ret; - ulong errs = 0; /* number of errors, or -1 if interrupted */ - ulong pattern = 0; - int iteration; -#if defined(CONFIG_SYS_ALT_MEMTEST) - const int alt_test = 1; -#else - const int alt_test = 0; -#endif - - 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 %08x ... %08x:\n", (uint)start, (uint)end); - debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__, - start, end); - - buf = map_sysmem(start, end - start); - dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long)); - for (iteration = 0; - !iteration_limit || iteration < iteration_limit; - iteration++) { - if (ctrlc()) { - errs = -1UL; - break; - } - - printf("Iteration: %6d\r", iteration + 1); - debug("\n"); - if (alt_test) { - errs = mem_test_alt(buf, start, end, dummy); - } else { - errs = mem_test_quick(buf, start, end, pattern, - iteration); - } - if (errs == -1UL) - break; - } - - /* - * Work-around for eldk-4.2 which gives this warning if we try to - * case in the unmap_sysmem() call: - * warning: initialization discards qualifiers from pointer target type - */ - { - void *vbuf = (void *)buf; - void *vdummy = (void *)dummy; - - unmap_sysmem(vbuf); - unmap_sysmem(vdummy); - } - - if (errs == -1UL) { - /* Memory test was aborted - write a newline to finish off */ - putc('\n'); - ret = 1; - } else { - printf("Tested %d iteration(s) with %lu errors.\n", - iteration, errs); - ret = errs != 0; - } - - return ret; -} -#endif /* CONFIG_CMD_MEMTEST */ - -/* Modify memory. - * - * Syntax: - * mm{.b, .w, .l, .q} {addr} - * nm{.b, .w, .l, .q} {addr} - */ -static int -mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) -{ - ulong addr; -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - u64 i; -#else - ulong i; -#endif - 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; - } - -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash(addr)){ - puts ("Can't modify DataFlash in place. Use cp instead.\n\r"); - return 0; - } -#endif - -#ifdef CONFIG_BLACKFIN - if (addr_bfin_on_chip_mem(addr)) { - puts ("Can't modify L1 instruction in place. Use cp instead.\n\r"); - return 0; - } -#endif - - /* 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)); -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - else if (size == 8) - printf(" %016" PRIx64, *((u64 *)ptr)); -#endif - else if (size == 2) - printf(" %04x", *((u16 *)ptr)); - else - printf(" %02x", *((u8 *)ptr)); - - nbytes = cli_readline(" ? "); - if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { - /* 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; -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - i = simple_strtoull(console_buffer, &endp, 16); -#else - i = simple_strtoul(console_buffer, &endp, 16); -#endif - nbytes = endp - console_buffer; - if (nbytes) { - /* good enough to not time out - */ - bootretry_reset_cmd_timeout(); - if (size == 4) - *((u32 *)ptr) = i; -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - else if (size == 8) - *((u64 *)ptr) = i; -#endif - 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(cmd_tbl_t *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_HASH_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 - -/**************************************************/ -U_BOOT_CMD( - md, 3, 1, do_mem_md, - "memory display", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] address [# of objects]" -#else - "[.b, .w, .l] address [# of objects]" -#endif -); - - -U_BOOT_CMD( - mm, 2, 1, do_mem_mm, - "memory modify (auto-incrementing address)", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] address" -#else - "[.b, .w, .l] address" -#endif -); - - -U_BOOT_CMD( - nm, 2, 1, do_mem_nm, - "memory modify (constant address)", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] address" -#else - "[.b, .w, .l] address" -#endif -); - -U_BOOT_CMD( - mw, 4, 1, do_mem_mw, - "memory write (fill)", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] address value [count]" -#else - "[.b, .w, .l] address value [count]" -#endif -); - -U_BOOT_CMD( - cp, 4, 1, do_mem_cp, - "memory copy", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] source target count" -#else - "[.b, .w, .l] source target count" -#endif -); - -U_BOOT_CMD( - cmp, 4, 1, do_mem_cmp, - "memory compare", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] addr1 addr2 count" -#else - "[.b, .w, .l] addr1 addr2 count" -#endif -); - -#ifdef CONFIG_CMD_CRC32 - -#ifndef CONFIG_HASH_VERIFY - -U_BOOT_CMD( - crc32, 4, 1, do_mem_crc, - "checksum calculation", - "address count [addr]\n - compute CRC32 checksum [save at addr]" -); - -#else /* CONFIG_HASH_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_HASH_VERIFY */ - -#endif - -#ifdef CONFIG_CMD_MEMINFO -__weak void board_show_dram(phys_size_t size) -{ - puts("DRAM: "); - print_size(size, "\n"); -} - -static int do_mem_info(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - board_show_dram(gd->ram_size); - - 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", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] address number_of_objects" -#else - "[.b, .w, .l] address number_of_objects" -#endif -); - -#ifdef CONFIG_LOOPW -U_BOOT_CMD( - loopw, 4, 1, do_mem_loopw, - "infinite write loop on address range", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] address number_of_objects data_to_write" -#else - "[.b, .w, .l] address number_of_objects data_to_write" -#endif -); -#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_MX_CYCLIC -U_BOOT_CMD( - mdc, 4, 1, do_mem_mdc, - "memory display cyclic", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] address count delay(ms)" -#else - "[.b, .w, .l] address count delay(ms)" -#endif -); - -U_BOOT_CMD( - mwc, 4, 1, do_mem_mwc, - "memory write cyclic", -#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - "[.b, .w, .l, .q] address value delay(ms)" -#else - "[.b, .w, .l] address value delay(ms)" -#endif -); -#endif /* CONFIG_MX_CYCLIC */ - -#ifdef CONFIG_CMD_MEMINFO -U_BOOT_CMD( - meminfo, 3, 1, do_mem_info, - "display memory information", - "" -); -#endif diff --git a/cmd/cmd_mfsl.c b/cmd/cmd_mfsl.c deleted file mode 100644 index e8e8e3c..0000000 --- a/cmd/cmd_mfsl.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * (C) Copyright 2007 Michal Simek - * - * Michal SIMEK - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Microblaze FSL support - */ - -#include -#include -#include -#include - -int do_frd (cmd_tbl_t * 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 (cmd_tbl_t * 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 (cmd_tbl_t * 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/cmd/cmd_mii.c b/cmd/cmd_mii.c deleted file mode 100644 index 7ef7532..0000000 --- a/cmd/cmd_mii.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * (C) Copyright 2001 - * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * MII Utilities - */ - -#include -#include -#include - -typedef struct _MII_reg_desc_t { - ushort regno; - char * name; -} MII_reg_desc_t; - -static const MII_reg_desc_t reg_0_5_desc_tbl[] = { - { MII_BMCR, "PHY control register" }, - { MII_BMSR, "PHY status register" }, - { MII_PHYSID1, "PHY ID 1 register" }, - { MII_PHYSID2, "PHY ID 2 register" }, - { MII_ADVERTISE, "Autonegotiation advertisement register" }, - { MII_LPA, "Autonegotiation partner abilities register" }, -}; - -typedef struct _MII_field_desc_t { - ushort hi; - ushort lo; - ushort mask; - 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, "xxx to do" }, -}; - -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, "xxx to do" }, -}; -typedef struct _MII_field_desc_and_len_t { - const MII_field_desc_t *pdesc; - ushort len; -} MII_field_desc_and_len_t; - -static const MII_field_desc_and_len_t desc_and_len_tbl[] = { - { reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl) }, - { reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl) }, - { reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl) }, - { reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl) }, - { reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl) }, - { reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl) }, -}; - -static void dump_reg( - ushort regval, - const MII_reg_desc_t *prd, - const MII_field_desc_and_len_t *pdl); - -static int special_field( - ushort regno, - const MII_field_desc_t *pdesc, - ushort regval); - -static void MII_dump_0_to_5( - ushort regvals[6], - uchar reglo, - uchar reghi) -{ - ulong i; - - for (i = 0; i < 6; i++) { - if ((reglo <= i) && (i <= reghi)) - dump_reg(regvals[i], ®_0_5_desc_tbl[i], - &desc_and_len_tbl[i]); - } -} - -static void dump_reg( - ushort regval, - const MII_reg_desc_t *prd, - const MII_field_desc_and_len_t *pdl) -{ - 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 < pdl->len; i++) { - pdesc = &pdl->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)) { - } - else { - if (pdesc->hi == pdesc->lo) - printf("%2u ", pdesc->lo); - else - printf("%2u-%2u", pdesc->hi, pdesc->lo); - printf(" = %5u %s", - (regval & mask_in_place) >> pdesc->lo, - pdesc->name); - } - printf("\n"); - - } - printf("\n"); -} - -/* Special fields: -** 0.6,13 -** 0.8 -** 2.15-0 -** 3.15-0 -** 4.4-0 -** 5.4-0 -*/ - -static int special_field( - ushort regno, - const MII_field_desc_t *pdesc, - ushort regval) -{ - 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)) { - printf("%2u = %5u duplex = %s", - pdesc->lo, - (regval >> pdesc->lo) & 1, - ((regval >> pdesc->lo) & 1) ? "full" : "half"); - return 1; - } - - else if ((regno == MII_ADVERTISE) && (pdesc->lo == 0)) { - ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask; - printf("%2u-%2u = %5u selector = %s", - pdesc->hi, pdesc->lo, sel_bits, - sel_bits == PHY_ANLPAR_PSB_802_3 ? - "IEEE 802.3" : - sel_bits == PHY_ANLPAR_PSB_802_9 ? - "IEEE 802.9 ISLAN-16T" : - "???"); - return 1; - } - - else if ((regno == MII_LPA) && (pdesc->lo == 0)) { - ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask; - printf("%2u-%2u = %u selector = %s", - pdesc->hi, pdesc->lo, sel_bits, - sel_bits == PHY_ANLPAR_PSB_802_3 ? - "IEEE 802.3" : - 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(cmd_tbl_t *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], ®lo, ®hi); - if (argc >= 5) - data = simple_strtoul(argv[4], NULL, 16); - if (argc >= 6) - mask = simple_strtoul(argv[5], NULL, 16); - } - - if (addrhi > 31) { - 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[6]; - int ok = 1; - if ((reglo > 5) || (reghi > 5)) { - printf( - "The MII dump command only formats the " - "standard MII registers, 0-5.\n"); - return 1; - } - for (addr = addrlo; addr <= addrhi; addr++) { - for (reg = reglo; reg < reghi + 1; reg++) { - if (miiphy_read(devname, addr, reg, ®s[reg]) != 0) { - ok = 0; - printf( - "Error reading from the PHY addr=%02x reg=%02x\n", - addr, reg); - rcode = 1; - } - } - if (ok) - MII_dump_0_to_5(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 - set current device\n" - "mii info - display MII PHY info\n" - "mii read - read MII PHY register \n" - "mii write - write MII PHY register \n" - "mii modify - modify MII PHY register \n" - " updating bits identified in \n" - "mii dump - pretty-print (0-5 only)\n" - "Addr and/or reg may be ranges, e.g. 2-7." -); diff --git a/cmd/cmd_misc.c b/cmd/cmd_misc.c deleted file mode 100644 index 39d8683..0000000 --- a/cmd/cmd_misc.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * (C) Copyright 2001 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Misc functions - */ -#include -#include -#include - -static int do_sleep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - ulong start = get_timer(0); - ulong delay; - - if (argc != 2) - return CMD_RET_USAGE; - - delay = simple_strtoul(argv[1], NULL, 10) * CONFIG_SYS_HZ; - - while (get_timer(start) < delay) { - if (ctrlc()) - return (-1); - - 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_ !!!)" -); - -#ifdef CONFIG_CMD_TIMER -static int do_timer(cmd_tbl_t *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'." -); -#endif diff --git a/cmd/cmd_mmc.c b/cmd/cmd_mmc.c deleted file mode 100644 index 1c7156f..0000000 --- a/cmd/cmd_mmc.c +++ /dev/null @@ -1,882 +0,0 @@ -/* - * (C) Copyright 2003 - * Kyle Harris, kharris@nexus-tech.net - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -static int curr_device = -1; -#ifndef CONFIG_GENERIC_MMC -int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int dev; - - if (argc < 2) - return CMD_RET_USAGE; - - if (strcmp(argv[1], "init") == 0) { - if (argc == 2) { - if (curr_device < 0) - dev = 1; - else - dev = curr_device; - } else if (argc == 3) { - dev = (int)simple_strtoul(argv[2], NULL, 10); - } else { - return CMD_RET_USAGE; - } - - if (mmc_legacy_init(dev) != 0) { - puts("No MMC card found\n"); - return 1; - } - - curr_device = dev; - printf("mmc%d is available\n", curr_device); - } else if (strcmp(argv[1], "device") == 0) { - if (argc == 2) { - if (curr_device < 0) { - puts("No MMC device available\n"); - return 1; - } - } else if (argc == 3) { - dev = (int)simple_strtoul(argv[2], NULL, 10); - -#ifdef CONFIG_SYS_MMC_SET_DEV - if (mmc_set_dev(dev) != 0) - return 1; -#endif - curr_device = dev; - } else { - return CMD_RET_USAGE; - } - - printf("mmc%d is current device\n", curr_device); - } else { - return CMD_RET_USAGE; - } - - return 0; -} - -U_BOOT_CMD( - mmc, 3, 1, do_mmc, - "MMC sub-system", - "init [dev] - init MMC sub system\n" - "mmc device [dev] - show or set current device" -); -#else /* !CONFIG_GENERIC_MMC */ - -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("Tran Speed: %d\n", mmc->tran_speed); - 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" : ""); - - puts("Erase Group Size: "); - print_size(((u64)mmc->erase_grp_size) << 9, "\n"); - - 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); - - puts("HC WP Group Size: "); - print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n"); - - 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'); - } - } - } -} -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 (force_init) - mmc->has_init = 0; - if (mmc_init(mmc)) - return NULL; - return mmc; -} -static int do_mmcinfo(cmd_tbl_t *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; -} - -#ifdef CONFIG_SUPPORT_EMMC_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? "); - if (confirm_yesno()) - return 1; - - puts("Authentication key programming aborted\n"); - return 0; -} -static int do_mmcrpmb_key(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - cmd_tbl_t *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 && !cp->repeatable) - 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 a 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 */ - original_part = mmc->block_dev.part_num; - if (mmc_select_hwpart(curr_device, MMC_PART_RPMB) != 0) - return CMD_RET_FAILURE; - ret = cp->cmd(cmdtp, flag, argc, argv); - - /* Return to original partition */ - if (mmc_select_hwpart(curr_device, original_part) != 0) - return CMD_RET_FAILURE; - return ret; -} -#endif - -static int do_mmc_read(cmd_tbl_t *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 = mmc->block_dev.block_read(&mmc->block_dev, blk, cnt, addr); - /* flush cache after read */ - flush_cache((ulong)addr, cnt * 512); /* FIXME */ - printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); - - return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; -} -static int do_mmc_write(cmd_tbl_t *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 = mmc->block_dev.block_write(&mmc->block_dev, 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(cmd_tbl_t *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 = mmc->block_dev.block_erase(&mmc->block_dev, blk, cnt); - printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR"); - - return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; -} -static int do_mmc_rescan(cmd_tbl_t *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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - block_dev_desc_t *mmc_dev; - struct mmc *mmc; - - mmc = init_mmc_device(curr_device, false); - if (!mmc) - return CMD_RET_FAILURE; - - mmc_dev = mmc_get_dev(curr_device); - if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) { - print_part(mmc_dev); - return CMD_RET_SUCCESS; - } - - puts("get mmc type error!\n"); - return CMD_RET_FAILURE; -} -static int do_mmc_dev(cmd_tbl_t *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 = mmc_select_hwpart(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->block_dev.hwpart); - - return CMD_RET_SUCCESS; -} -static int do_mmc_list(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - print_mmc_devices('\n'); - return CMD_RET_SUCCESS; -} - -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(cmd_tbl_t *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; - } -} - -#ifdef CONFIG_SUPPORT_EMMC_BOOT -static int do_mmc_bootbus(cmd_tbl_t *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; - } - - /* acknowledge to be sent during boot operation */ - return mmc_set_boot_bus_width(mmc, width, reset, mode); -} -static int do_mmc_boot_resize(cmd_tbl_t *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 a 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 do_mmc_partconf(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - int dev; - struct mmc *mmc; - u8 ack, part_num, access; - - if (argc != 5) - return CMD_RET_USAGE; - - dev = simple_strtoul(argv[1], NULL, 10); - ack = simple_strtoul(argv[2], NULL, 10); - part_num = simple_strtoul(argv[3], NULL, 10); - access = simple_strtoul(argv[4], 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; - } - - /* acknowledge to be sent during boot operation */ - return mmc_set_part_conf(mmc, ack, part_num, access); -} -static int do_mmc_rst_func(cmd_tbl_t *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(cmd_tbl_t *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[2], 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; -} - -static cmd_tbl_t 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(write, 4, 0, do_mmc_write, "", ""), - U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""), - 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, "", ""), - U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""), -#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 -#ifdef CONFIG_SUPPORT_EMMC_RPMB - U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), -#endif - U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), -}; - -static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *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 && !cp->repeatable) - 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" - "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 hwpartition [args...] - does hardware partitioning\n" - " arguments (sizes in 512-byte blocks):\n" - " [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n" - " [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n" - " [check|set|complete] - 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" -#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 \n" - " - Change sizes of boot and RPMB partitions of specified device\n" - "mmc partconf dev boot_ack boot_partition partition_access\n" - " - Change the bits of the PARTITION_CONFIG field of the specified device\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 -#ifdef CONFIG_SUPPORT_EMMC_RPMB - "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n" - "mmc rpmb write addr blk# cnt
- block size is 256 bytes\n" - "mmc rpmb key
- program the RPMB authentication key.\n" - "mmc rpmb counter - read the value of the write counter\n" -#endif - "mmc setdsr - set DSR register value\n" - ); - -/* 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" -); - -#endif /* !CONFIG_GENERIC_MMC */ diff --git a/cmd/cmd_mmc_spi.c b/cmd/cmd_mmc_spi.c deleted file mode 100644 index a2138b8..0000000 --- a/cmd/cmd_mmc_spi.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Command for mmc_spi setup. - * - * Copyright (C) 2010 Thomas Chou - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include - -#ifndef CONFIG_MMC_SPI_BUS -# define CONFIG_MMC_SPI_BUS 0 -#endif -#ifndef CONFIG_MMC_SPI_CS -# define CONFIG_MMC_SPI_CS 1 -#endif -/* in SPI mode, MMC speed limit is 20MHz, while SD speed limit is 25MHz */ -#ifndef CONFIG_MMC_SPI_SPEED -# define CONFIG_MMC_SPI_SPEED 25000000 -#endif -/* MMC and SD specs only seem to care that sampling is on the - * rising edge ... meaning SPI modes 0 or 3. So either SPI mode - * should be legit. We'll use mode 0 since the steady state is 0, - * which is appropriate for hotplugging, unless the platform data - * specify mode 3 (if hardware is not compatible to mode 0). - */ -#ifndef CONFIG_MMC_SPI_MODE -# define CONFIG_MMC_SPI_MODE SPI_MODE_0 -#endif - -static int do_mmc_spi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - uint bus = CONFIG_MMC_SPI_BUS; - uint cs = CONFIG_MMC_SPI_CS; - uint speed = CONFIG_MMC_SPI_SPEED; - uint mode = CONFIG_MMC_SPI_MODE; - char *endp; - struct mmc *mmc; - - if (argc < 2) - goto usage; - - cs = simple_strtoul(argv[1], &endp, 0); - if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) - goto usage; - if (*endp == ':') { - if (endp[1] == 0) - goto usage; - bus = cs; - cs = simple_strtoul(endp + 1, &endp, 0); - if (*endp != 0) - goto usage; - } - if (argc >= 3) { - speed = simple_strtoul(argv[2], &endp, 0); - if (*argv[2] == 0 || *endp != 0) - goto usage; - } - if (argc >= 4) { - mode = simple_strtoul(argv[3], &endp, 16); - if (*argv[3] == 0 || *endp != 0) - goto usage; - } - if (!spi_cs_is_valid(bus, cs)) { - printf("Invalid SPI bus %u cs %u\n", bus, cs); - return 1; - } - - mmc = mmc_spi_init(bus, cs, speed, mode); - if (!mmc) { - printf("Failed to create MMC Device\n"); - return 1; - } - printf("%s: %d at %u:%u hz %u mode %u\n", mmc->cfg->name, mmc->block_dev.dev, - bus, cs, speed, mode); - mmc_init(mmc); - return 0; - -usage: - return CMD_RET_USAGE; -} - -U_BOOT_CMD( - mmc_spi, 4, 0, do_mmc_spi, - "mmc_spi setup", - "[bus:]cs [hz] [mode] - setup mmc_spi device" -); diff --git a/cmd/cmd_mp.c b/cmd/cmd_mp.c deleted file mode 100644 index a80c642..0000000 --- a/cmd/cmd_mp.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2008-2009 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -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(cmd_tbl_t *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[] = - " reset - Reset cpu \n" - "cpu status - Status of all cpus\n" - "cpu status - Status of cpu \n" - "cpu disable - Disable cpu \n" - "cpu release [args] - Release cpu at with [args]" -#ifdef CONFIG_PPC - "\n" - " [args] : \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 and r6 is 0\n" \ - "\n" \ - " When cpu 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/cmd/cmd_mtdparts.c b/cmd/cmd_mtdparts.c deleted file mode 100644 index dab1958..0000000 --- a/cmd/cmd_mtdparts.c +++ /dev/null @@ -1,2106 +0,0 @@ -/* - * (C) Copyright 2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2002 - * Robert Schwebel, Pengutronix, - * - * (C) Copyright 2003 - * Kai-Uwe Bloem, Auerswald GmbH & Co KG, - * - * (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 - * - * $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $ - * Copyright 2002 SYSGO Real-Time Solutions GmbH - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Three environment variables are used by the parsing routines: - * - * 'partition' - keeps current partition identifier - * - * partition := - * := ,part_num - * - * - * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping - * - * mtdids=[,,...] - * - * := = - * := 'nand'|'nor'|'onenand' - * := mtd device number, 0... - * := unique device tag used by linux kernel to find mtd device (mtd->name) - * - * - * 'mtdparts' - partition list - * - * mtdparts=mtdparts=[;...] - * - * := :[,...] - * := unique device tag used by linux kernel to find mtd device (mtd->name) - * := [@][][] - * := standard linux memsize OR '-' to denote all remaining space - * := partition start offset within the device - * := '(' NAME ')' - * := when set to 'ro' makes partition read-only (not used, passed to kernel) - * - * Notes: - * - each 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 -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_NAND) -#include -#include -#endif - -#if defined(CONFIG_CMD_ONENAND) -#include -#include -#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) -static const char *const mtdids_default = MTDIDS_DEFAULT; -#else -static const char *const mtdids_default = NULL; -#endif - -#if defined(MTDPARTS_DEFAULT) -static const char *const mtdparts_default = MTDPARTS_DEFAULT; -#else -static const char *const mtdparts_default = NULL; -#endif - -/* 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]; -static char last_parts[MTDPARTS_MAXLEN]; -static char last_partition[PARTITION_MAXLEN]; - -/* 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; - -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; - case 'M': - case 'm': - ret <<= 10; - case 'K': - case 'k': - ret <<= 10; - (*retptr)++; - 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; - setenv_ulong("mtddevnum", mtddevnum); - break; - } - mtddevnum += dev->num_parts; - } - - part = mtd_part_info(current_mtd_dev, current_mtd_partnum); - setenv("mtddevname", part->name); - - debug("=> mtddevnum %d,\n=> mtddevname %s\n", mtddevnum, part->name); - } else { - setenv("mtddevnum", NULL); - setenv("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); - - setenv("partition", buf); - strncpy(last_partition, buf, 16); - - debug("=> partition %s\n", buf); - } else { - setenv("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, 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. - * @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 */ - sprintf(part->name, "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. - * @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 = p = mtd_dev; - if (!(p = strchr(mtd_id, ':'))) { - printf("no 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; - } - -#ifdef DEBUG - pend = strchr(p, ';'); -#endif - 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; - } - - if (num_parts == 0) { - printf("no partitions for device %s%d (%s)\n", - MTD_DEV_TYPE(id->type), id->num, id->mtd_id); - 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 := 'nand'|'nor'|'onenand', - * 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 { - 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; - } - - strcpy(p, "mtdparts="); - p += 9; - - 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)) - setenv("mtdparts", buf); - else - setenv("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%08x\t0x%08x%s\t0x%08x\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 , 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%08x@0x%08x\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 */ - -/** - * 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 = mtdparts; - struct mtd_device *dev; - int err = 1; - char tmp_parts[MTDPARTS_MAXLEN]; - - debug("\n---parse_mtdparts---\nmtdparts = %s\n\n", p); - - /* 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 */ - if (gd->flags & GD_FLG_ENV_READY) { - p = getenv("mtdparts"); - } else { - p = tmp_parts; - getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN); - } - - if (strncmp(p, "mtdparts=", 9) != 0) { - printf("mtdparts variable doesn't start with 'mtdparts='\n"); - return err; - } - p += 9; - - while (p && (*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) { - device_delall(&devices); - return 1; - } - - return 0; -} - -/** - * 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' */ - if (mtd_id_parse(p, &p, &type, &num) != 0) - break; - - if (*p != '=') { - printf("mtdids: incorrect \n"); - break; - } - p++; - - /* check if requested device exists */ - if (mtd_device_validate(type, num, &size) != 0) - return 1; - - /* locate */ - 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 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]; - char tmp_parts[MTDPARTS_MAXLEN]; - - debug("\n---mtdparts_init---\n"); - if (!initialized) { - INIT_LIST_HEAD(&mtdids); - INIT_LIST_HEAD(&devices); - memset(last_ids, 0, MTDIDS_MAXLEN); - memset(last_parts, 0, MTDPARTS_MAXLEN); - memset(last_partition, 0, PARTITION_MAXLEN); - initialized = 1; - } - - /* get variables */ - ids = getenv("mtdids"); - /* - * 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. - */ - if (gd->flags & GD_FLG_ENV_READY) { - parts = getenv("mtdparts"); - } else { - parts = tmp_parts; - getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN); - } - current_partition = getenv("partition"); - - /* save it for later parsing, cannot rely on current partition pointer - * as 'partition' variable may be updated during init */ - tmp_ep[0] = '\0'; - 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 varible is empty try to use defaults */ - if (!ids) { - if (mtdids_default) { - debug("mtdids variable not defined, using default\n"); - ids = mtdids_default; - setenv("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; - } - - /* do no try to use defaults when mtdparts variable is not defined, - * just check the length */ - if (!parts) - 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 (getenv("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(cmd_tbl_t *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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - if (argc == 2) { - if (strcmp(argv[1], "default") == 0) { - setenv("mtdids", (char *)mtdids_default); - setenv("mtdparts", (char *)mtdparts_default); - setenv("partition", NULL); - - mtdparts_init(); - return 0; - } else if (strcmp(argv[1], "delall") == 0) { - /* this may be the first run, initialize lists if needed */ - mtdparts_init(); - - setenv("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 [@] [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 %d 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 [@] [] [ro]\n" - " - add partition\n" -#if defined(CONFIG_CMD_MTDPARTS_SPREAD) - "mtdparts add.spread [@] [] [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 := \n" - " := ,part_num\n\n" - "'mtdids' - linux kernel mtd device id <-> u-boot device id mapping\n\n" - "mtdids=[,,...]\n\n" - " := =\n" - " := 'nand'|'nor'|'onenand'\n" - " := mtd device number, 0...\n" - " := unique device tag used by linux kernel to find mtd device (mtd->name)\n\n" - "'mtdparts' - partition list\n\n" - "mtdparts=mtdparts=[;...]\n\n" - " := :[,...]\n" - " := unique device tag used by linux kernel to find mtd device (mtd->name)\n" - " := [@][][]\n" - " := standard linux memsize OR '-' to denote all remaining space\n" - " := partition start offset within the device\n" - " := '(' NAME ')'\n" - " := 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/cmd/cmd_nand.c b/cmd/cmd_nand.c deleted file mode 100644 index a6b67e2..0000000 --- a/cmd/cmd_nand.c +++ /dev/null @@ -1,973 +0,0 @@ -/* - * Driver for NAND support, Rick Bronson - * borrowed heavily from: - * (c) 1999 Machine Vision Holdings, Inc. - * (c) 1999, 2000 David Woodhouse - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_MTDPARTS) - -/* partition handling routines */ -int mtdparts_init(void); -int 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 - -static int nand_dump(nand_info_t *nand, 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 + nand->writesize; - - last = off; - - datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize); - if (!datbuf) { - puts("No memory for page buffer\n"); - return 1; - } - - oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize); - if (!oobbuf) { - puts("No memory for page buffer\n"); - ret = 1; - goto free_dat; - } - off &= ~(nand->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 = nand->writesize; - ops.ooblen = nand->oobsize; - ops.mode = MTD_OPS_RAW; - i = mtd_read_oob(nand, 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 = nand->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 = nand->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) -{ - if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || - !nand_info[dev].name) { - puts("No such device\n"); - return -1; - } - - if (nand_curr_device == dev) - return 0; - - printf("Device %d: %s", dev, nand_info[dev].name); - puts("... is now current device\n"); - nand_curr_device = dev; - -#ifdef CONFIG_SYS_NAND_SELECT_DEVICE - board_nand_select_device(nand_info[dev].priv, 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(nand_info_t *nand) -{ - ulong block_start = 0; - ulong off; - int last_status = -1; - - struct nand_chip *nand_chip = nand->priv; - /* check the WP bit */ - nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1); - printf("device is %swrite protected\n", - (nand_chip->read_byte(nand) & 0x80 ? - "NOT " : "")); - - for (off = 0; off < nand->size; off += nand->erasesize) { - int s = nand_get_lock_status(nand, off); - - /* print message only if status has changed */ - if (s != last_status && off != 0) { - print_status(block_start, off, nand->erasesize, - last_status); - block_start = off; - } - last_status = s; - } - /* Print the last block info */ - print_status(block_start, off, nand->erasesize, last_status); -} -#endif - -#ifdef CONFIG_ENV_OFFSET_OOB -unsigned long nand_env_oob_offset; - -int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[]) -{ - int ret; - uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)]; - nand_info_t *nand = &nand_info[0]; - char *cmd = argv[1]; - - if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) { - puts("no devices available\n"); - return 1; - } - - set_dev(0); - - if (!strcmp(cmd, "get")) { - ret = get_nand_env_oob(nand, &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; - - /* We don't care about size, or maxsize. */ - if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize, - MTD_DEV_TYPE_NAND, nand_info[idx].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 (nand->oobavail < ENV_OFFSET_SIZE) { - printf("Insufficient available OOB bytes:\n" - "%d OOB bytes available but %d required for " - "env.oob support\n", - nand->oobavail, ENV_OFFSET_SIZE); - return 1; - } - - if ((addr & (nand->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 / nand->erasesize; - - ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops); - if (ret) { - printf("Error writing OOB block 0\n"); - return ret; - } - - ret = get_nand_env_oob(nand, &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) -{ - nand_info_t *nand = &nand_info[idx]; - struct nand_chip *chip = nand->priv; - - printf("Device %d: ", idx); - if (chip->numchips > 1) - printf("%dx ", chip->numchips); - printf("%s, sector size %u KiB\n", - nand->name, nand->erasesize >> 10); - printf(" Page size %8d b\n", nand->writesize); - printf(" OOB size %8d b\n", nand->oobsize); - printf(" Erase size %8d b\n", nand->erasesize); - printf(" subpagesize %8d b\n", chip->subpagesize); - printf(" options 0x%8x\n", chip->options); - printf(" bbt options 0x%8x\n", chip->bbt_options); - - /* Set geometry info */ - setenv_hex("nand_writesize", nand->writesize); - setenv_hex("nand_oobsize", nand->oobsize); - setenv_hex("nand_erasesize", nand->erasesize); -} - -static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, - int read) -{ - int ret = 0; - - while (count--) { - /* Raw access */ - mtd_oob_ops_t ops = { - .datbuf = (u8 *)addr, - .oobbuf = ((u8 *)addr) + nand->writesize, - .len = nand->writesize, - .ooblen = nand->oobsize, - .mode = MTD_OPS_RAW - }; - - if (read) { - ret = mtd_read_oob(nand, off, &ops); - } else { - ret = mtd_write_oob(nand, off, &ops); - if (!ret) - ret = nand_verify_page_oob(nand, &ops, off); - } - - if (ret) { - printf("%s: error at offset %llx, ret %d\n", - __func__, (long long)off, ret); - break; - } - - addr += nand->writesize + nand->oobsize; - off += nand->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. - */ - nand_info_t *nand = &nand_info[dev]; - loff_t maxoffset = offset + *size; - int badblocks = 0; - - /* count badblocks in NAND from offset to offset + size */ - for (; offset < maxoffset; offset += nand->erasesize) { - if (nand_block_isbad(nand, offset)) - badblocks++; - } - /* adjust size if any bad blocks found */ - if (badblocks) { - *size -= badblocks * nand->erasesize; - printf("size adjusted to 0x%llx (%d bad blocks)\n", - (unsigned long long)*size, badblocks); - } -} - -static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int i, ret = 0; - ulong addr; - loff_t off, size, maxsize; - char *cmd, *s; - nand_info_t *nand; -#ifdef CONFIG_SYS_NAND_QUIET - int quiet = CONFIG_SYS_NAND_QUIET; -#else - int quiet = 0; -#endif - const char *quiet_str = getenv("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++) { - if (nand_info[i].name) - 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. - */ - if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || - !nand_info[dev].name) { - puts("\nno devices available\n"); - return 1; - } - nand = &nand_info[dev]; - - if (strcmp(cmd, "bad") == 0) { - printf("\nDevice %d bad blocks:\n", dev); - for (off = 0; off < nand->size; off += nand->erasesize) - if (nand_block_isbad(nand, 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? \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, - nand_info[dev].size) != 0) - return 1; - - if (set_dev(dev)) - return 1; - - nand = &nand_info[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(nand, &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(nand, 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; - - 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 && !strcmp(s, ".raw")) { - raw = 1; - - if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize, - MTD_DEV_TYPE_NAND, - nand_info[dev].size)) - return 1; - - if (set_dev(dev)) - return 1; - - nand = &nand_info[dev]; - - if (argc > 4 && !str2long(argv[4], &pagecount)) { - printf("'%s' is not a number\n", argv[4]); - return 1; - } - - if (pagecount * nand->writesize > size) { - puts("Size exceeds partition or device limit\n"); - return -1; - } - - rwsize = pagecount * (nand->writesize + nand->oobsize); - } else { - if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off, - &size, &maxsize, - MTD_DEV_TYPE_NAND, - nand_info[dev].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; - } - - nand = &nand_info[dev]; - - if (!s || !strcmp(s, ".jffs2") || - !strcmp(s, ".e") || !strcmp(s, ".i")) { - if (read) - ret = nand_read_skip_bad(nand, off, &rwsize, - NULL, maxsize, - (u_char *)addr); - else - ret = nand_write_skip_bad(nand, 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(nand, 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(nand, off, &ops); - else - ret = mtd_write_oob(nand, off, &ops); - } else if (raw) { - ret = raw_access(nand, addr, off, pagecount, read); - } 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) { - if (argc < 3) - goto usage; - - if (!str2off(argv[2], &off)) { - puts("Offset is not a valid number\n"); - return 1; - } - - printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n", - dev, off, nand->erasesize); - ret = nand_torture(nand, off); - printf(" %s\n", ret ? "Failed" : "Passed"); - - return ret == 0 ? 0 : 1; - } -#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(nand, 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(nand); - } else { - if (!nand_lock(nand, 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, - nand_info[dev].size) < 0) - return 1; - - if (set_dev(dev)) - return 1; - - if (!nand_unlock(&nand_info[dev], 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 - 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 block at offset\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(cmd_tbl_t *cmdtp, nand_info_t *nand, - ulong offset, ulong addr, char *cmd) -{ - int r; - char *s; - size_t cnt; -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - 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", nand->name, offset); - - cnt = nand->writesize; - r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->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_IMAGE_FORMAT_LEGACY) - 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(nand, offset, &cnt, NULL, nand->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)) { - 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 */ - - load_addr = addr; - - return bootm_maybe_autostart(cmdtp, cmd); -} - -static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - char *boot_device = NULL; - int idx; - ulong addr, offset = 0; -#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; - return nand_load_image(cmdtp, &nand_info[dev->id->num], - part->offset, addr, argv[0]); - } - } -#endif - - bootstage_mark(BOOTSTAGE_ID_NAND_PART); - switch (argc) { - case 1: - addr = CONFIG_SYS_LOAD_ADDR; - boot_device = getenv("bootdevice"); - break; - case 2: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = getenv("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); - - if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) { - 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, &nand_info[idx], offset, addr, argv[0]); -} - -U_BOOT_CMD(nboot, 4, 1, do_nandboot, - "boot from NAND device", - "[partition] | [[[loadAddr] dev] offset]" -); diff --git a/cmd/cmd_net.c b/cmd/cmd_net.c deleted file mode 100644 index b2f3c7b..0000000 --- a/cmd/cmd_net.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Boot support - */ -#include -#include -#include - -static int netboot_common(enum proto_t, cmd_tbl_t *, int, char * const []); - -static int do_bootp(cmd_tbl_t *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]" -); - -int do_tftpb(cmd_tbl_t *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]" -); - -#ifdef CONFIG_CMD_TFTPPUT -int do_tftpput(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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); - setenv("gatewayip", tmp); - } - - if (net_netmask.s_addr) { - ip_to_string(net_netmask, tmp); - setenv("netmask", tmp); - } - - if (net_hostname[0]) - setenv("hostname", net_hostname); - - if (net_root_path[0]) - setenv("rootpath", net_root_path); - - if (net_ip.s_addr) { - ip_to_string(net_ip, tmp); - setenv("ipaddr", tmp); - } -#if !defined(CONFIG_BOOTP_SERVERIP) - /* - * Only attempt to change serverip if net/bootp.c:BootpCopyNetParams() - * could have set it - */ - if (net_server_ip.s_addr) { - ip_to_string(net_server_ip, tmp); - setenv("serverip", tmp); - } -#endif - if (net_dns_server.s_addr) { - ip_to_string(net_dns_server, tmp); - setenv("dnsip", tmp); - } -#if defined(CONFIG_BOOTP_DNS2) - if (net_dns_server2.s_addr) { - ip_to_string(net_dns_server2, tmp); - setenv("dnsip2", tmp); - } -#endif - if (net_nis_domain[0]) - setenv("domain", net_nis_domain); - -#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET) - if (net_ntp_time_offset) { - sprintf(tmp, "%d", net_ntp_time_offset); - setenv("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); - setenv("ntpserverip", tmp); - } -#endif -} - -static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, - char * const argv[]) -{ - char *s; - char *end; - int rcode = 0; - int size; - ulong addr; - - /* pre-set load_addr */ - s = getenv("loadaddr"); - if (s != NULL) - load_addr = simple_strtoul(s, NULL, 16); - - switch (argc) { - case 1: - 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]))) - load_addr = addr; - else - copy_filename(net_boot_file_name, argv[1], - sizeof(net_boot_file_name)); - break; - - case 3: - load_addr = simple_strtoul(argv[1], NULL, 16); - 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, &save_addr) < 0 || - strict_strtoul(argv[2], 16, &save_size) < 0) { - printf("Invalid address/size\n"); - return CMD_RET_USAGE; - } - 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; - } - - /* flush cache */ - flush_cache(load_addr, size); - - 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(cmd_tbl_t *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); - setenv("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); - setenv("nvlan", tmp); - net_native_vlan = cdp_native_vlan; - } -} - -int do_cdp(cmd_tbl_t *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) -int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *toff; - - if (argc < 2) { - net_ntp_server = getenv_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 = getenv("timeoffset"); - if (toff == NULL) - net_ntp_time_offset = 0; - else - net_ntp_time_offset = simple_strtol(toff, NULL, 10); - - if (net_loop(SNTP) < 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(cmd_tbl_t *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(cmd_tbl_t *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); - setenv("gatewayip", tmp); - - ip_to_string(net_netmask, tmp); - setenv("netmask", tmp); - - ip_to_string(net_ip, tmp); - setenv("ipaddr", tmp); - setenv("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/cmd/cmd_nvedit.c b/cmd/cmd_nvedit.c deleted file mode 100644 index 5ae9d9d..0000000 --- a/cmd/cmd_nvedit.c +++ /dev/null @@ -1,1298 +0,0 @@ -/* - * (C) Copyright 2000-2013 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH - * Andreas Heppel - * - * Copyright 2011 Freescale Semiconductor, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * 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 preceeded 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#if !defined(CONFIG_ENV_IS_IN_EEPROM) && \ - !defined(CONFIG_ENV_IS_IN_FLASH) && \ - !defined(CONFIG_ENV_IS_IN_DATAFLASH) && \ - !defined(CONFIG_ENV_IS_IN_MMC) && \ - !defined(CONFIG_ENV_IS_IN_FAT) && \ - !defined(CONFIG_ENV_IS_IN_NAND) && \ - !defined(CONFIG_ENV_IS_IN_NVRAM) && \ - !defined(CONFIG_ENV_IS_IN_ONENAND) && \ - !defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \ - !defined(CONFIG_ENV_IS_IN_REMOTE) && \ - !defined(CONFIG_ENV_IS_IN_UBI) && \ - !defined(CONFIG_ENV_IS_NOWHERE) -# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|ONENAND|\ -SPI_FLASH|NVRAM|MMC|FAT|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 get_env_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 get_env_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 */ - ENTRY e, *ep; - - e.key = name; - e.data = NULL; - hsearch_r(e, 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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - int i; - int rcode = 0; - int env_flag = H_HIDE_DOT; - - 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(cmd_tbl_t *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; - ENTRY e, *ep; - - 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); - name = argv[1]; - value = argv[2]; - - 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); - return !rc; - } - - /* - * 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, 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 setenv(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 setenv_ulong(const char *varname, ulong value) -{ - /* TODO: this should be unsigned */ - char *str = simple_itoa(value); - - return setenv(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 setenv_hex(const char *varname, ulong value) -{ - char str[17]; - - sprintf(str, "%lx", value); - return setenv(varname, str); -} - -ulong getenv_hex(const char *varname, ulong default_val) -{ - const char *s; - ulong value; - char *endp; - - s = getenv(varname); - if (s) - value = simple_strtoul(s, &endp, 16); - if (!s || endp == s) - return default_val; - - return value; -} - -#ifndef CONFIG_SPL_BUILD -static int do_env_set(cmd_tbl_t *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(cmd_tbl_t *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; i++) { - if (pos) - message[pos++] = ' '; - - strcpy(message + pos, argv[i]); - pos += strlen(argv[i]); - } - message[pos++] = ' '; - message[pos] = '\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(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(cmd_tbl_t *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(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(cmd_tbl_t *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(cmd_tbl_t *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 = getenv(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 *getenv(const char *name) -{ - if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */ - ENTRY e, *ep; - - WATCHDOG_RESET(); - - e.key = name; - e.data = NULL; - hsearch_r(e, FIND, &ep, &env_htab, 0); - - return ep ? ep->data : NULL; - } - - /* restricted capabilities before import */ - if (getenv_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0) - return (char *)(gd->env_buf); - - return NULL; -} - -/* - * Look up variable from environment for restricted C runtime env. - */ -int getenv_f(const char *name, char *buf, unsigned len) -{ - int i, nxt; - - for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { - int val, n; - - for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) { - if (nxt >= CONFIG_ENV_SIZE) - return -1; - } - - val = envmatch((uchar *)name, i); - if (val < 0) - continue; - - /* found; copy out */ - for (n = 0; n < len; ++n, ++buf) { - *buf = env_get_char(val++); - if (*buf == '\0') - return n; - } - - if (n) - *--buf = '\0'; - - printf("env_buf [%d 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 environemnt 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 getenv_ulong(const char *name, int base, ulong default_val) -{ - /* - * We can use getenv() here, even before relocation, since the - * environment variable value is an integer and thus short. - */ - const char *str = getenv(name); - - return str ? simple_strtoul(str, NULL, base) : default_val; -} - -#ifndef CONFIG_SPL_BUILD -#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) -static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - printf("Saving Environment to %s...\n", env_name_spec); - - return saveenv() ? 1 : 0; -} - -U_BOOT_CMD( - saveenv, 1, 0, do_env_save, - "save environment variables to persistent storage", - "" -); -#endif -#endif /* CONFIG_SPL_BUILD */ - - -/* - * Match a name / name=value pair - * - * s1 is either a simple 'name', or a 'name=value' pair. - * i2 is the environment index for a 'name2=value2' pair. - * If the names match, return the index for the value2, else -1. - */ -int envmatch(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(cmd_tbl_t *cmdtp, int __flag, - int argc, char * const argv[]) -{ - int all = 0, flag = 0; - - 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 */ - 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 */ - set_default_env("## Resetting to default environment\n"); - return 0; - } - if (!all && (argc > 0)) { - /* Reset individual variables */ - set_default_vars(argc, argv); - return 0; - } - - return cmd_usage(cmdtp); -} - -static int do_env_delete(cmd_tbl_t *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 resundant - * 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 remainign 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 szenario: 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(cmd_tbl_t *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) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - sprintf(buf, "%zX", (size_t)len); - setenv("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) { - error("Cannot export environment: errno = %d\n", errno); - return 1; - } - - if (chk) { - envp->crc = crc32(0, envp->data, ENV_SIZE); -#ifdef CONFIG_ENV_ADDR_REDUND - envp->flags = ACTIVE_FLAG; -#endif - } - setenv_hex("filesize", len + offsetof(env_t, data)); - - return 0; - -sep_err: - printf("## %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] - * -d: delete existing environment before importing; - * otherwise overwrite / append to existion 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 - */ -static int do_env_import(cmd_tbl_t *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; - 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) { - size = simple_strtoul(argv[1], NULL, 16); - } else if (argc == 1 && 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 (chk) { - uint32_t crc; - env_t *ep = (env_t *)ptr; - - 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, 0, NULL) == 0) { - 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_ENV_EXISTS) -static int do_env_exists(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - ENTRY e, *ep; - - if (argc < 2) - return CMD_RET_USAGE; - - e.key = argv[1]; - e.data = NULL; - hsearch_r(e, FIND, &ep, &env_htab, 0); - - return (ep == NULL) ? 1 : 0; -} -#endif - -/* - * New command line interface: "env" command with subcommands - */ -static cmd_tbl_t 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 - 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(CONFIG_ENV_IS_NOWHERE) - U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""), -#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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *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] - import environment\n" -#endif - "env print [-a | name ...] - print environment\n" -#if defined(CONFIG_CMD_RUN) - "env run var [...] - run commands in an environment variable\n" -#endif -#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) - "env save - save environment\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" - "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", - "[-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/cmd/cmd_onenand.c b/cmd/cmd_onenand.c deleted file mode 100644 index feab01a..0000000 --- a/cmd/cmd_onenand.c +++ /dev/null @@ -1,595 +0,0 @@ -/* - * U-Boot command for OneNAND support - * - * Copyright (C) 2005-2008 Samsung Electronics - * Kyungmin Park - * - * 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 -#include -#include - -#include -#include -#include - -#include - -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 == 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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - printf("%s\n", mtd->name); - return 0; -} - -static int do_onenand_bad(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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 cmd_tbl_t 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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *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/cmd/cmd_otp.c b/cmd/cmd_otp.c deleted file mode 100644 index 10c1475..0000000 --- a/cmd/cmd_otp.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * cmd_otp.c - interface to Blackfin on-chip One-Time-Programmable memory - * - * Copyright (c) 2007-2008 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -/* There are 512 128-bit "pages" (0x000 through 0x1FF). - * The pages are accessable as 64-bit "halfpages" (an upper and lower half). - * The pages are not part of the memory map. There is an OTP controller which - * handles scanning in/out of bits. While access is done through OTP MMRs, - * the bootrom provides C-callable helper functions to handle the interaction. - */ - -#include -#include -#include -#include - -#include -#include -#include - -static const char *otp_strerror(uint32_t err) -{ - switch (err) { - case 0: return "no error"; - case OTP_WRITE_ERROR: return "OTP fuse write error"; - case OTP_READ_ERROR: return "OTP fuse read error"; - case OTP_ACC_VIO_ERROR: return "invalid OTP address"; - case OTP_DATA_MULT_ERROR: return "multiple bad bits detected"; - case OTP_ECC_MULT_ERROR: return "error in ECC bits"; - case OTP_PREV_WR_ERROR: return "space already written"; - case OTP_DATA_SB_WARN: return "single bad bit in half page"; - case OTP_ECC_SB_WARN: return "single bad bit in ECC"; - default: return "unknown error"; - } -} - -#define lowup(x) ((x) % 2 ? "upper" : "lower") - -static int check_voltage(void) -{ - /* Make sure voltage limits are within datasheet spec */ - uint16_t vr_ctl = bfin_read_VR_CTL(); - -#ifdef __ADSPBF54x__ - /* 0.9V <= VDDINT <= 1.1V */ - if ((vr_ctl & 0xc) && (vr_ctl & 0xc0) == 0xc0) - return 1; -#else - /* for the parts w/out qualification yet */ - (void)vr_ctl; -#endif - - return 0; -} - -static void set_otp_timing(bool write) -{ - static uint32_t timing; - if (!timing) { - uint32_t tp1, tp2, tp3; - /* OTP_TP1 = 1000 / sclk_period (in nanoseconds) - * OTP_TP1 = 1000 / (1 / get_sclk() * 10^9) - * OTP_TP1 = (1000 * get_sclk()) / 10^9 - * OTP_TP1 = get_sclk() / 10^6 - */ - tp1 = get_sclk() / 1000000; - /* OTP_TP2 = 400 / (2 * sclk_period) - * OTP_TP2 = 400 / (2 * 1 / get_sclk() * 10^9) - * OTP_TP2 = (400 * get_sclk()) / (2 * 10^9) - * OTP_TP2 = (2 * get_sclk()) / 10^7 - */ - tp2 = (2 * get_sclk() / 10000000) << 8; - /* OTP_TP3 = magic constant */ - tp3 = (0x1401) << 15; - timing = tp1 | tp2 | tp3; - } - - bfrom_OtpCommand(OTP_INIT, write ? timing : timing & ~(-1 << 15)); -} - -int do_otp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *cmd; - uint32_t ret, base_flags; - bool prompt_user, force_read; - uint32_t (*otp_func)(uint32_t page, uint32_t flags, uint64_t *page_content); - - if (argc < 4) { - usage: - return CMD_RET_USAGE; - } - - prompt_user = false; - base_flags = 0; - cmd = argv[1]; - if (!strcmp(cmd, "read")) - otp_func = bfrom_OtpRead; - else if (!strcmp(cmd, "dump")) { - otp_func = bfrom_OtpRead; - force_read = true; - } else if (!strcmp(cmd, "write")) { - otp_func = bfrom_OtpWrite; - base_flags = OTP_CHECK_FOR_PREV_WRITE; - if (!strcmp(argv[2], "--force")) { - argv++; - --argc; - } else - prompt_user = false; - } else if (!strcmp(cmd, "lock")) { - if (argc != 4) - goto usage; - otp_func = bfrom_OtpWrite; - base_flags = OTP_LOCK; - } else - goto usage; - - uint64_t *addr = (uint64_t *)simple_strtoul(argv[2], NULL, 16); - uint32_t page = simple_strtoul(argv[3], NULL, 16); - uint32_t flags; - size_t i, count; - ulong half; - - if (argc > 4) - count = simple_strtoul(argv[4], NULL, 16); - else - count = 2; - - if (argc > 5) { - half = simple_strtoul(argv[5], NULL, 16); - if (half != 0 && half != 1) { - puts("Error: 'half' can only be '0' or '1'\n"); - goto usage; - } - } else - half = 0; - - /* "otp lock" has slightly different semantics */ - if (base_flags & OTP_LOCK) { - count = page; - page = (uint32_t)addr; - addr = NULL; - } - - /* do to the nature of OTP, make sure users are sure */ - if (prompt_user) { - printf( - "Writing one time programmable memory\n" - "Make sure your operating voltages and temperature are within spec\n" - " source address: 0x%p\n" - " OTP destination: %s page 0x%03X - %s page 0x%03lX\n" - " number to write: %lu halfpages\n" - " type \"YES\" (no quotes) to confirm: ", - addr, - lowup(half), page, - lowup(half + count - 1), page + (half + count - 1) / 2, - half + count - ); - if (!confirm_yesno()) { - printf(" Aborting\n"); - return 1; - } - } - - printf("OTP memory %s: addr 0x%p page 0x%03X count %zu ... ", - cmd, addr, page, count); - - set_otp_timing(otp_func == bfrom_OtpWrite); - if (otp_func == bfrom_OtpWrite && check_voltage()) { - puts("ERROR: VDDINT voltage is out of spec for writing\n"); - return -1; - } - - /* Do the actual reading/writing stuff */ - ret = 0; - for (i = half; i < count + half; ++i) { - flags = base_flags | (i % 2 ? OTP_UPPER_HALF : OTP_LOWER_HALF); - try_again: - ret = otp_func(page, flags, addr); - if (ret & OTP_MASTER_ERROR) { - if (force_read) { - if (flags & OTP_NO_ECC) - break; - else - flags |= OTP_NO_ECC; - puts("E"); - goto try_again; - } else - break; - } else if (ret) - puts("W"); - else - puts("."); - if (!(base_flags & OTP_LOCK)) { - ++addr; - if (i % 2) - ++page; - } else - ++page; - } - if (ret & 0x1) - printf("\nERROR at page 0x%03X (%s-halfpage): 0x%03X: %s\n", - page, lowup(i), ret, otp_strerror(ret)); - else - puts(" done\n"); - - /* Make sure we disable writing */ - set_otp_timing(false); - bfrom_OtpCommand(OTP_CLOSE, 0); - - return ret; -} - -U_BOOT_CMD( - otp, 7, 0, do_otp, - "One-Time-Programmable sub-system", - "read [count] [half]\n" - " - read 'count' half-pages starting at 'page' (offset 'half') to 'addr'\n" - "otp dump [count] [half]\n" - " - like 'otp read', but skip read errors\n" - "otp write [--force] [count] [half]\n" - " - write 'count' half-pages starting at 'page' (offset 'half') from 'addr'\n" - "otp lock \n" - " - lock 'count' pages starting at 'page'" -); diff --git a/cmd/cmd_part.c b/cmd/cmd_part.c deleted file mode 100644 index 5599509..0000000 --- a/cmd/cmd_part.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. - * - * made from cmd_ext2, which was: - * - * (C) Copyright 2004 - * esd gmbh - * Reinhard Arlt - * - * made from cmd_reiserfs by - * - * (C) Copyright 2003 - 2004 - * Sysgo Real-Time Solutions, AG - * Pavel Bartusek - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -#ifndef CONFIG_PARTITION_UUIDS -#error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_PART to be enabled -#endif - -static int do_part_uuid(int argc, char * const argv[]) -{ - int part; - block_dev_desc_t *dev_desc; - disk_partition_t info; - - if (argc < 2) - return CMD_RET_USAGE; - if (argc > 3) - return CMD_RET_USAGE; - - part = get_device_and_partition(argv[0], argv[1], &dev_desc, &info, 0); - if (part < 0) - return 1; - - if (argc > 2) - setenv(argv[2], info.uuid); - else - printf("%s\n", info.uuid); - - return 0; -} - -static int do_part_list(int argc, char * const argv[]) -{ - int ret; - block_dev_desc_t *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 = get_device(argv[0], argv[1], &desc); - if (ret < 0) - return 1; - - if (var != NULL) { - int p; - char str[512] = { '\0', }; - disk_partition_t info; - - for (p = 1; p < 128; p++) { - char t[5]; - int r = get_partition_info(desc, p, &info); - - if (r != 0) - continue; - - if (bootable && !info.bootable) - continue; - - sprintf(t, "%s%x", str[0] ? " " : "", p); - strcat(str, t); - } - setenv(var, str); - return 0; - } - - print_part(desc); - - return 0; -} - -static int do_part_start(int argc, char * const argv[]) -{ - block_dev_desc_t *desc; - disk_partition_t info; - char buf[512] = { 0 }; - int part; - int err; - int ret; - - if (argc < 3) - return CMD_RET_USAGE; - if (argc > 4) - return CMD_RET_USAGE; - - part = simple_strtoul(argv[2], NULL, 0); - - ret = get_device(argv[0], argv[1], &desc); - if (ret < 0) - return 1; - - err = get_partition_info(desc, part, &info); - if (err) - return 1; - - snprintf(buf, sizeof(buf), LBAF, info.start); - - if (argc > 3) - setenv(argv[3], buf); - else - printf("%s\n", buf); - - return 0; -} - -static int do_part_size(int argc, char * const argv[]) -{ - block_dev_desc_t *desc; - disk_partition_t info; - char buf[512] = { 0 }; - int part; - int err; - int ret; - - if (argc < 3) - return CMD_RET_USAGE; - if (argc > 4) - return CMD_RET_USAGE; - - part = simple_strtoul(argv[2], NULL, 0); - - ret = get_device(argv[0], argv[1], &desc); - if (ret < 0) - return 1; - - err = get_partition_info(desc, part, &info); - if (err) - return 1; - - snprintf(buf, sizeof(buf), LBAF, info.size); - - if (argc > 3) - setenv(argv[3], buf); - else - printf("%s\n", buf); - - return 0; -} - -static int do_part(cmd_tbl_t *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); - - return CMD_RET_USAGE; -} - -U_BOOT_CMD( - part, CONFIG_SYS_MAXARGS, 1, do_part, - "disk partition related commands", - "uuid :\n" - " - print partition UUID\n" - "part uuid : \n" - " - set environment variable to partition UUID\n" - "part list \n" - " - print a device's partition table\n" - "part list [flags] \n" - " - set environment variable to the list of partitions\n" - " flags can be -bootable (list only bootable partitions)\n" - "part start \n" - " - set environment variable to the start of the partition (in blocks)\n" - "part size \n" - " - set environment variable to the size of the partition (in blocks)" -); diff --git a/cmd/cmd_pci.c b/cmd/cmd_pci.c deleted file mode 100644 index 8094d33..0000000 --- a/cmd/cmd_pci.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH - * Andreas Heppel - * - * (C) Copyright 2002 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * PCI routines - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 - -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(bus->seq, short_listing); - - for (device_find_first_child(bus, &dev); - dev; - device_find_next_child(&dev)) { - struct pci_child_platdata *pplat; - - pplat = dev_get_parent_platdata(dev); - if (short_listing) { - printf("%02x.%02x.%02x ", bus->seq, - PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn)); - pci_header_show_brief(dev); - } else { - printf("\nFound PCI device %02x.%02x.%02x:\n", bus->seq, - 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] == '-')) { - /* 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; -} - -/* 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(cmd_tbl_t *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 */ - if (argc < 3) - goto usage; - if ((bdf = get_pci_dev(argv[2])) == -1) - return 1; - break; -#ifdef CONFIG_CMD_PCI_ENUM - case 'e': - break; -#endif - default: /* scan bus */ - value = 1; /* short listing */ - if (argc > 1) { - if (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; - } - 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); -#ifdef CONFIG_CMD_PCI_ENUM - case 'e': -# ifdef CONFIG_DM_PCI - printf("This command is not yet supported with driver model\n"); -# else - pci_init(); -# endif - break; -#endif - 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; - 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" -#ifdef CONFIG_CMD_PCI_ENUM - "pci enum\n" - " - re-enumerate PCI buses\n" -#endif - "pci header b.d.f\n" - " - show header of PCI device 'bus.device.function'\n" - "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/cmd/cmd_pcmcia.c b/cmd/cmd_pcmcia.c deleted file mode 100644 index 682d18f..0000000 --- a/cmd/cmd_pcmcia.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * (C) Copyright 2000-2006 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - * - ******************************************************************** - * - * Lots of code copied from: - * - * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series. - * (C) 1999-2000 Magnus Damm - * - * "The ExCA standard specifies that socket controllers should provide - * two IO and five memory windows per socket, which can be independently - * configured and positioned in the host address space and mapped to - * arbitrary segments of card address space. " - David A Hinds. 1999 - * - * This controller does _not_ meet the ExCA standard. - * - * m8xx pcmcia controller brief info: - * + 8 windows (attrib, mem, i/o) - * + up to two slots (SLOT_A and SLOT_B) - * + inputpins, outputpins, event and mask registers. - * - no offset register. sigh. - * - * Because of the lacking offset register we must map the whole card. - * We assign each memory window PCMCIA_MEM_WIN_SIZE address space. - * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO - * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE. - * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE. - * They are maximum 64KByte each... - */ - -/* #define DEBUG 1 */ - -/* - * PCMCIA support - */ -#include -#include -#include -#include -#include - -/* -------------------------------------------------------------------- */ - -#if defined(CONFIG_CMD_PCMCIA) - -extern int pcmcia_on (void); -extern int pcmcia_off (void); - -int do_pinit (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int rcode = 0; - - if (argc != 2) { - printf ("Usage: pinit {on | off}\n"); - return 1; - } - if (strcmp(argv[1],"on") == 0) { - rcode = pcmcia_on (); - } else if (strcmp(argv[1],"off") == 0) { - rcode = pcmcia_off (); - } else { - printf ("Usage: pinit {on | off}\n"); - return 1; - } - - return rcode; -} - -U_BOOT_CMD( - pinit, 2, 0, do_pinit, - "PCMCIA sub-system", - "on - power on PCMCIA socket\n" - "pinit off - power off PCMCIA socket" -); - -#endif - -/* -------------------------------------------------------------------- */ - -#undef CHECK_IDE_DEVICE - -#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) -#define CHECK_IDE_DEVICE -#endif - -#if defined(CONFIG_PXA_PCMCIA) -#define CHECK_IDE_DEVICE -#endif - -#ifdef CHECK_IDE_DEVICE - -int ide_devices_found; -static uchar *known_cards[] = { - (uchar *)"ARGOSY PnPIDE D5", - NULL -}; - -#define MAX_TUPEL_SZ 512 -#define MAX_FEATURES 4 - -#define MAX_IDENT_CHARS 64 -#define MAX_IDENT_FIELDS 4 - -#define indent "\t " - -static void print_funcid (int func) -{ - puts (indent); - switch (func) { - case CISTPL_FUNCID_MULTI: - puts (" Multi-Function"); - break; - case CISTPL_FUNCID_MEMORY: - puts (" Memory"); - break; - case CISTPL_FUNCID_SERIAL: - puts (" Serial Port"); - break; - case CISTPL_FUNCID_PARALLEL: - puts (" Parallel Port"); - break; - case CISTPL_FUNCID_FIXED: - puts (" Fixed Disk"); - break; - case CISTPL_FUNCID_VIDEO: - puts (" Video Adapter"); - break; - case CISTPL_FUNCID_NETWORK: - puts (" Network Adapter"); - break; - case CISTPL_FUNCID_AIMS: - puts (" AIMS Card"); - break; - case CISTPL_FUNCID_SCSI: - puts (" SCSI Adapter"); - break; - default: - puts (" Unknown"); - break; - } - puts (" Card\n"); -} - -static void print_fixed (volatile uchar *p) -{ - if (p == NULL) - return; - - puts(indent); - - switch (*p) { - case CISTPL_FUNCE_IDE_IFACE: - { uchar iface = *(p+2); - - puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown"); - puts (" interface "); - break; - } - case CISTPL_FUNCE_IDE_MASTER: - case CISTPL_FUNCE_IDE_SLAVE: - { uchar f1 = *(p+2); - uchar f2 = *(p+4); - - puts ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]"); - - if (f1 & CISTPL_IDE_UNIQUE) - puts (" [unique]"); - - puts ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]"); - - if (f2 & CISTPL_IDE_HAS_SLEEP) - puts (" [sleep]"); - - if (f2 & CISTPL_IDE_HAS_STANDBY) - puts (" [standby]"); - - if (f2 & CISTPL_IDE_HAS_IDLE) - puts (" [idle]"); - - if (f2 & CISTPL_IDE_LOW_POWER) - puts (" [low power]"); - - if (f2 & CISTPL_IDE_REG_INHIBIT) - puts (" [reg inhibit]"); - - if (f2 & CISTPL_IDE_HAS_INDEX) - puts (" [index]"); - - if (f2 & CISTPL_IDE_IOIS16) - puts (" [IOis16]"); - - break; - } - } - putc ('\n'); -} - -static int identify (volatile uchar *p) -{ - uchar id_str[MAX_IDENT_CHARS]; - uchar data; - uchar *t; - uchar **card; - int i, done; - - if (p == NULL) - return (0); /* Don't know */ - - t = id_str; - done =0; - - for (i=0; i<=4 && !done; ++i, p+=2) { - while ((data = *p) != '\0') { - if (data == 0xFF) { - done = 1; - break; - } - *t++ = data; - if (t == &id_str[MAX_IDENT_CHARS-1]) { - done = 1; - break; - } - p += 2; - } - if (!done) - *t++ = ' '; - } - *t = '\0'; - while (--t > id_str) { - if (*t == ' ') - *t = '\0'; - else - break; - } - puts ((char *)id_str); - putc ('\n'); - - for (card=known_cards; *card; ++card) { - debug ("## Compare against \"%s\"\n", *card); - if (strcmp((char *)*card, (char *)id_str) == 0) { /* found! */ - debug ("## CARD FOUND ##\n"); - return (1); - } - } - - return (0); /* don't know */ -} - -int check_ide_device (int slot) -{ - volatile uchar *ident = NULL; - volatile uchar *feature_p[MAX_FEATURES]; - volatile uchar *p, *start, *addr; - int n_features = 0; - uchar func_id = ~0; - uchar code, len; - ushort config_base = 0; - int found = 0; - int i; - - addr = (volatile uchar *)(CONFIG_SYS_PCMCIA_MEM_ADDR + - CONFIG_SYS_PCMCIA_MEM_SIZE * (slot * 4)); - debug ("PCMCIA MEM: %08lX\n", (ulong)addr); - - start = p = (volatile uchar *) addr; - - while ((p - start) < MAX_TUPEL_SZ) { - - code = *p; p += 2; - - if (code == 0xFF) { /* End of chain */ - break; - } - - len = *p; p += 2; -#if defined(DEBUG) && (DEBUG > 1) - { volatile uchar *q = p; - printf ("\nTuple code %02x length %d\n\tData:", - code, len); - - for (i = 0; i < len; ++i) { - printf (" %02x", *q); - q+= 2; - } - } -#endif /* DEBUG */ - switch (code) { - case CISTPL_VERS_1: - ident = p + 4; - break; - case CISTPL_FUNCID: - /* Fix for broken SanDisk which may have 0x80 bit set */ - func_id = *p & 0x7F; - break; - case CISTPL_FUNCE: - if (n_features < MAX_FEATURES) - feature_p[n_features++] = p; - break; - case CISTPL_CONFIG: - config_base = (*(p+6) << 8) + (*(p+4)); - debug ("\n## Config_base = %04x ###\n", config_base); - default: - break; - } - p += 2 * len; - } - - found = identify (ident); - - if (func_id != ((uchar)~0)) { - print_funcid (func_id); - - if (func_id == CISTPL_FUNCID_FIXED) - found = 1; - else - return (1); /* no disk drive */ - } - - for (i=0; i only valid for ARGOSY D5!!! */ - *((uchar *)(addr + config_base)) = 1; -#if 0 - printf("\n## Config_base = %04x ###\n", config_base); - printf("Configuration Option Register: %02x @ %x\n", readb(addr + config_base), addr + config_base); - printf("Card Configuration and Status Register: %02x\n", readb(addr + config_base + 2)); - printf("Pin Replacement Register Register: %02x\n", readb(addr + config_base + 4)); - printf("Socket and Copy Register: %02x\n", readb(addr + config_base + 6)); -#endif - return (0); -} - -#endif /* CHECK_IDE_DEVICE */ diff --git a/cmd/cmd_pmic.c b/cmd/cmd_pmic.c deleted file mode 100644 index 970767c..0000000 --- a/cmd/cmd_pmic.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2014-2015 Samsung Electronics - * Przemyslaw Marczak - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include - -#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(cmd_tbl_t *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", currdev->seq, currdev->name); - } - - return CMD_RET_SUCCESS; -} - -static int do_list(cmd_tbl_t *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->parent->seq); - } - - if (ret) - return CMD_RET_FAILURE; - - return CMD_RET_SUCCESS; -} - -static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct udevice *dev; - uint8_t value; - uint reg; - int ret; - - if (!currdev) { - printf("First, set the PMIC device!\n"); - return CMD_RET_USAGE; - } - - dev = currdev; - - printf("Dump pmic: %s registers\n", dev->name); - - for (reg = 0; reg < pmic_reg_count(dev); reg++) { - ret = pmic_read(dev, reg, &value, 1); - if (ret) { - printf("Can't read register: %d\n", reg); - return failure(ret); - } - - if (!(reg % 16)) - printf("\n0x%02x: ", reg); - - printf("%2.2x ", value); - } - printf("\n"); - - return CMD_RET_SUCCESS; -} - -static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct udevice *dev; - int regs, ret; - uint8_t value; - uint reg; - - if (!currdev) { - printf("First, set the PMIC device!\n"); - return CMD_RET_USAGE; - } - - dev = currdev; - - 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_read(dev, reg, &value, 1); - if (ret) { - printf("Can't read PMIC register: %d!\n", reg); - return failure(ret); - } - - printf("0x%02x: 0x%2.2x\n", reg, value); - - return CMD_RET_SUCCESS; -} - -static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct udevice *dev; - int regs, ret; - uint8_t value; - uint reg; - - 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_write(dev, reg, &value, 1); - if (ret) { - printf("Can't write PMIC register: %d!\n", reg); - return failure(ret); - } - - return CMD_RET_SUCCESS; -} - -static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - cmd_tbl_t *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, - " operations", - "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/cmd/cmd_portio.c b/cmd/cmd_portio.c deleted file mode 100644 index bf3a997..0000000 --- a/cmd/cmd_portio.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * (C) Copyright 2003 - * Marc Singer, elf@buici.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Port I/O Functions - * - * Copied from FADS ROM, Dan Malek (dmalek@jlc.net) - */ - -#include -#include - -/* Display values from last command. - * Memory modify remembered values are different from display memory. - */ -static uint in_last_addr, in_last_size; -static uint out_last_addr, out_last_size, out_last_value; - - -int do_portio_out (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - uint addr = out_last_addr; - uint size = out_last_size; - uint value = out_last_value; - - if (argc != 3) - 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], 1); - addr = simple_strtoul (argv[1], NULL, 16); - value = simple_strtoul (argv[2], NULL, 16); - } -#if defined (CONFIG_X86) - - { - unsigned short port = addr; - - switch (size) { - default: - case 1: - { - unsigned char ch = value; - __asm__ volatile ("out %0, %%dx"::"a" (ch), "d" (port)); - } - break; - case 2: - { - unsigned short w = value; - __asm__ volatile ("out %0, %%dx"::"a" (w), "d" (port)); - } - break; - case 4: - __asm__ volatile ("out %0, %%dx"::"a" (value), "d" (port)); - - break; - } - } - -#endif /* CONFIG_X86 */ - - out_last_addr = addr; - out_last_size = size; - out_last_value = value; - - return 0; -} - -U_BOOT_CMD( - out, 3, 1, do_portio_out, - "write datum to IO port", - "[.b, .w, .l] port value\n - output to IO port" -); - -int do_portio_in (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - uint addr = in_last_addr; - uint size = in_last_size; - - 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], 1); - addr = simple_strtoul (argv[1], NULL, 16); - } -#if defined (CONFIG_X86) - - { - unsigned short port = addr; - - switch (size) { - default: - case 1: - { - unsigned char ch; - __asm__ volatile ("in %%dx, %0":"=a" (ch):"d" (port)); - - printf (" %02x\n", ch); - } - break; - case 2: - { - unsigned short w; - __asm__ volatile ("in %%dx, %0":"=a" (w):"d" (port)); - - printf (" %04x\n", w); - } - break; - case 4: - { - unsigned long l; - __asm__ volatile ("in %%dx, %0":"=a" (l):"d" (port)); - - printf (" %08lx\n", l); - } - break; - } - } -#endif /* CONFIG_X86 */ - - in_last_addr = addr; - in_last_size = size; - - return 0; -} - -U_BOOT_CMD( - in, 2, 1, do_portio_in, - "read data from an IO port", - "[.b, .w, .l] port\n" - " - read datum from IO port" -); diff --git a/cmd/cmd_pxe.c b/cmd/cmd_pxe.c deleted file mode 100644 index 080b376..0000000 --- a/cmd/cmd_pxe.c +++ /dev/null @@ -1,1725 +0,0 @@ -/* - * Copyright 2010-2011 Calxeda, Inc. - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "menu.h" -#include "cli.h" - -#define MAX_TFTP_PATH_LEN 127 - -const char *pxe_default_paths[] = { -#ifdef CONFIG_SYS_SOC - "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC, -#endif - "default-" CONFIG_SYS_ARCH, - "default", - NULL -}; - -static bool is_pxe; - -/* - * Like getenv, but prints an error if envvar isn't defined in the - * environment. It always returns what getenv does, so it can be used in - * place of getenv without changing error handling otherwise. - */ -static char *from_env(const char *envvar) -{ - char *ret; - - ret = getenv(envvar); - - if (!ret) - printf("missing environment variable: %s\n", envvar); - - return ret; -} - -#ifdef CONFIG_CMD_NET -/* - * 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. - */ -static 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_getenv_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; -} -#endif - -/* - * 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 == NULL) - 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; -} - -static int (*do_getfile)(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr); - -#ifdef CONFIG_CMD_NET -static int do_get_tftp(cmd_tbl_t *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; -} -#endif - -static char *fs_argv[5]; - -static int do_get_ext2(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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; -} - -/* - * 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(cmd_tbl_t *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. - */ -static int get_pxe_file(cmd_tbl_t *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; -} - -#ifdef CONFIG_CMD_NET - -#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. - */ -static int get_pxelinux_path(cmd_tbl_t *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); -} - -/* - * 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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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; -} -#endif - -/* - * 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(cmd_tbl_t *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); -} - -/* - * 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 *append; - char *initrd; - char *fdt; - char *fdtdir; - 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. - * 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; - int timeout; - int prompt; - struct list_head labels; -}; - -/* - * 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->append) - free(label->append); - - if (label->initrd) - free(label->initrd); - - if (label->fdt) - free(label->fdt); - - if (label->fdtdir) - free(label->fdtdir); - - 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); - setenv("bootargs", bootargs); - } - - debug("running: %s\n", localcmd); - - return run_command_list(localcmd, strlen(localcmd), 0); -} - -/* - * 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(cmd_tbl_t *cmdtp, struct pxe_label *label) -{ - char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL }; - char initrd_str[22]; - char mac_str[29] = ""; - char ip_str[68] = ""; - int bootm_argc = 3; - 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 == NULL) { - 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; - strcpy(bootm_argv[2], getenv("ramdisk_addr_r")); - strcat(bootm_argv[2], ":"); - strcat(bootm_argv[2], getenv("filesize")); - } else { - bootm_argv[2] = "-"; - } - - 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", - getenv("ipaddr"), getenv("serverip"), - getenv("gatewayip"), getenv("netmask")); - } - -#ifdef 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'; - } -#endif - - 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) - strcpy(bootargs, label->append); - strcat(bootargs, ip_str); - strcat(bootargs, mac_str); - - cli_simple_process_macros(bootargs, finalbootargs); - setenv("bootargs", finalbootargs); - printf("append: %s\n", finalbootargs); - } - - bootm_argv[1] = getenv("kernel_addr_r"); - - /* - * fdt usage is optional: - * It handles the following scenarios. All scenarios are exclusive - * - * Scenario 1: If fdt_addr_r specified and "fdt" label is defined in - * pxe file, retrieve fdt blob from server. Pass fdt_addr_r to bootm, - * and adjust argc appropriately. - * - * 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] = getenv("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 = getenv("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 = getenv("soc"); - f2 = "-"; - f3 = getenv("board"); - f4 = ".dtb"; - } - - 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"); - return 1; - } - - 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) { - printf("Skipping %s for failure retrieving fdt\n", - label->name); - return 1; - } - } else { - bootm_argv[3] = NULL; - } - } - - if (!bootm_argv[3]) - bootm_argv[3] = getenv("fdt_addr"); - - if (bootm_argv[3]) - 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); -#ifdef CONFIG_CMD_BOOTI - /* Try booting an AArch64 Linux kernel image */ - else - do_booti(cmdtp, 0, bootm_argc, bootm_argv); -#elif defined(CONFIG_CMD_BOOTZ) - /* Try booting a Image */ - else - do_bootz(cmdtp, 0, bootm_argc, bootm_argv); -#endif - unmap_sysmem(buf); - 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_ONTIMEOUT, - T_IPAPPEND, - 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}, - {"ontimeout", T_ONTIMEOUT,}, - {"ipappend", T_IPAPPEND,}, - {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 = 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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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; - - 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; -} - -/* - * 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_sliteral(c, &label->kernel); - 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_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(cmd_tbl_t *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. - */ -static 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. - */ -static struct pxe_menu *parse_pxefile(cmd_tbl_t *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, cfg->timeout, cfg->prompt, 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(cmd_tbl_t *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. - */ -static void handle_pxe_menu(cmd_tbl_t *cmdtp, struct pxe_menu *cfg) -{ - void *choice; - struct menu *m; - int err; - - 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); -} - -#ifdef CONFIG_CMD_NET -/* - * Boots a system using a pxe file - * - * Returns 0 on success, 1 on error. - */ -static int -do_pxe_boot(cmd_tbl_t *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 == NULL) { - 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 cmd_tbl_t cmd_pxe_sub[] = { - U_BOOT_CMD_MKENT(get, 1, 1, do_pxe_get, "", ""), - U_BOOT_CMD_MKENT(boot, 2, 1, do_pxe_boot, "", "") -}; - -static int do_pxe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *cp; - - 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\npxe " - "boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n" -); -#endif - -/* - * Boots a system using a local disk syslinux/extlinux file - * - * Returns 0 on success, 1 on error. - */ -static int do_sysboot(cmd_tbl_t *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 = getenv("bootfile"); - else { - filename = argv[5]; - setenv("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 == NULL) { - 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] [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/cmd/cmd_read.c b/cmd/cmd_read.c deleted file mode 100644 index 8710288..0000000 --- a/cmd/cmd_read.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 -#include -#include - -int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *ep; - block_dev_desc_t *dev_desc = NULL; - int dev; - int part = 0; - disk_partition_t 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 = 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 (get_partition_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 block_dev_desc_t. */ - limit = ~0; - } - - if (cnt + blk > limit) { - printf("Read out of range\n"); - return 1; - } - - if (dev_desc->block_read(dev_desc, offset + blk, cnt, addr) < 0) { - printf("Error reading blocks\n"); - return 1; - } - - return 0; -} - -U_BOOT_CMD( - read, 6, 0, do_read, - "Load binary data from a partition", - " addr blk# cnt" -); diff --git a/cmd/cmd_reginfo.c b/cmd/cmd_reginfo.c deleted file mode 100644 index 5f19e79..0000000 --- a/cmd/cmd_reginfo.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * (C) Copyright 2000 - * Subodh Nijsure, SkyStream Networks, snijsure@skystream.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#if defined(CONFIG_8xx) -#include -#elif defined (CONFIG_4xx) -extern void ppc4xx_reginfo(void); -#elif defined (CONFIG_5xx) -#include -#elif defined (CONFIG_MPC5200) -#include -#elif defined (CONFIG_MPC86xx) -extern void mpc86xx_reginfo(void); -#elif defined(CONFIG_MPC85xx) -extern void mpc85xx_reginfo(void); -#endif - -static int do_reginfo(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ -#if defined(CONFIG_8xx) - volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; - volatile memctl8xx_t *memctl = &immap->im_memctl; - volatile sysconf8xx_t *sysconf = &immap->im_siu_conf; - volatile sit8xx_t *timers = &immap->im_sit; - - /* Hopefully more PowerPC knowledgable people will add code to display - * other useful registers - */ - - printf ("\nSystem Configuration registers\n" - - "\tIMMR\t0x%08X\n", get_immr(0)); - - printf("\tSIUMCR\t0x%08X", sysconf->sc_siumcr); - printf("\tSYPCR\t0x%08X\n",sysconf->sc_sypcr); - - printf("\tSWT\t0x%08X", sysconf->sc_swt); - printf("\tSWSR\t0x%04X\n", sysconf->sc_swsr); - - printf("\tSIPEND\t0x%08X\tSIMASK\t0x%08X\n", - sysconf->sc_sipend, sysconf->sc_simask); - printf("\tSIEL\t0x%08X\tSIVEC\t0x%08X\n", - sysconf->sc_siel, sysconf->sc_sivec); - printf("\tTESR\t0x%08X\tSDCR\t0x%08X\n", - sysconf->sc_tesr, sysconf->sc_sdcr); - - printf ("Memory Controller Registers\n" - - "\tBR0\t0x%08X\tOR0\t0x%08X \n", memctl->memc_br0, memctl->memc_or0); - printf("\tBR1\t0x%08X\tOR1\t0x%08X \n", memctl->memc_br1, memctl->memc_or1); - printf("\tBR2\t0x%08X\tOR2\t0x%08X \n", memctl->memc_br2, memctl->memc_or2); - printf("\tBR3\t0x%08X\tOR3\t0x%08X \n", memctl->memc_br3, memctl->memc_or3); - printf("\tBR4\t0x%08X\tOR4\t0x%08X \n", memctl->memc_br4, memctl->memc_or4); - printf("\tBR5\t0x%08X\tOR5\t0x%08X \n", memctl->memc_br5, memctl->memc_or5); - printf("\tBR6\t0x%08X\tOR6\t0x%08X \n", memctl->memc_br6, memctl->memc_or6); - printf("\tBR7\t0x%08X\tOR7\t0x%08X \n", memctl->memc_br7, memctl->memc_or7); - printf ("\n" - "\tmamr\t0x%08X\tmbmr\t0x%08X \n", - memctl->memc_mamr, memctl->memc_mbmr ); - printf("\tmstat\t0x%08X\tmptpr\t0x%08X \n", - memctl->memc_mstat, memctl->memc_mptpr ); - printf("\tmdr\t0x%08X \n", memctl->memc_mdr); - - printf ("\nSystem Integration Timers\n" - "\tTBSCR\t0x%08X\tRTCSC\t0x%08X \n", - timers->sit_tbscr, timers->sit_rtcsc); - printf("\tPISCR\t0x%08X \n", timers->sit_piscr); - - /* - * May be some CPM info here? - */ - -#elif defined (CONFIG_4xx) - ppc4xx_reginfo(); -#elif defined(CONFIG_5xx) - - volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; - volatile memctl5xx_t *memctl = &immap->im_memctl; - volatile sysconf5xx_t *sysconf = &immap->im_siu_conf; - volatile sit5xx_t *timers = &immap->im_sit; - volatile car5xx_t *car = &immap->im_clkrst; - volatile uimb5xx_t *uimb = &immap->im_uimb; - - puts ("\nSystem Configuration registers\n"); - printf("\tIMMR\t0x%08X\tSIUMCR\t0x%08X \n", get_immr(0), sysconf->sc_siumcr); - printf("\tSYPCR\t0x%08X\tSWSR\t0x%04X \n" ,sysconf->sc_sypcr, sysconf->sc_swsr); - printf("\tSIPEND\t0x%08X\tSIMASK\t0x%08X \n", sysconf->sc_sipend, sysconf->sc_simask); - printf("\tSIEL\t0x%08X\tSIVEC\t0x%08X \n", sysconf->sc_siel, sysconf->sc_sivec); - printf("\tTESR\t0x%08X\n", sysconf->sc_tesr); - - puts ("\nMemory Controller Registers\n"); - printf("\tBR0\t0x%08X\tOR0\t0x%08X \n", memctl->memc_br0, memctl->memc_or0); - printf("\tBR1\t0x%08X\tOR1\t0x%08X \n", memctl->memc_br1, memctl->memc_or1); - printf("\tBR2\t0x%08X\tOR2\t0x%08X \n", memctl->memc_br2, memctl->memc_or2); - printf("\tBR3\t0x%08X\tOR3\t0x%08X \n", memctl->memc_br3, memctl->memc_or3); - printf("\tDMBR\t0x%08X\tDMOR\t0x%08X \n", memctl->memc_dmbr, memctl->memc_dmor ); - printf("\tMSTAT\t0x%08X\n", memctl->memc_mstat); - - puts ("\nSystem Integration Timers\n"); - printf("\tTBSCR\t0x%08X\tRTCSC\t0x%08X \n", timers->sit_tbscr, timers->sit_rtcsc); - printf("\tPISCR\t0x%08X \n", timers->sit_piscr); - - puts ("\nClocks and Reset\n"); - printf("\tSCCR\t0x%08X\tPLPRCR\t0x%08X \n", car->car_sccr, car->car_plprcr); - - puts ("\nU-Bus to IMB3 Bus Interface\n"); - printf("\tUMCR\t0x%08X\tUIPEND\t0x%08X \n", uimb->uimb_umcr, uimb->uimb_uipend); - puts ("\n\n"); - -#elif defined(CONFIG_MPC5200) - puts ("\nMPC5200 registers\n"); - printf ("MBAR=%08x\n", CONFIG_SYS_MBAR); - puts ("Memory map registers\n"); - printf ("\tCS0: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", - *(volatile ulong*)MPC5XXX_CS0_START, - *(volatile ulong*)MPC5XXX_CS0_STOP, - *(volatile ulong*)MPC5XXX_CS0_CFG, - (*(volatile ulong*)MPC5XXX_ADDECR & 0x00010000) ? 1 : 0); - printf ("\tCS1: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", - *(volatile ulong*)MPC5XXX_CS1_START, - *(volatile ulong*)MPC5XXX_CS1_STOP, - *(volatile ulong*)MPC5XXX_CS1_CFG, - (*(volatile ulong*)MPC5XXX_ADDECR & 0x00020000) ? 1 : 0); - printf ("\tCS2: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", - *(volatile ulong*)MPC5XXX_CS2_START, - *(volatile ulong*)MPC5XXX_CS2_STOP, - *(volatile ulong*)MPC5XXX_CS2_CFG, - (*(volatile ulong*)MPC5XXX_ADDECR & 0x00040000) ? 1 : 0); - printf ("\tCS3: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", - *(volatile ulong*)MPC5XXX_CS3_START, - *(volatile ulong*)MPC5XXX_CS3_STOP, - *(volatile ulong*)MPC5XXX_CS3_CFG, - (*(volatile ulong*)MPC5XXX_ADDECR & 0x00080000) ? 1 : 0); - printf ("\tCS4: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", - *(volatile ulong*)MPC5XXX_CS4_START, - *(volatile ulong*)MPC5XXX_CS4_STOP, - *(volatile ulong*)MPC5XXX_CS4_CFG, - (*(volatile ulong*)MPC5XXX_ADDECR & 0x00100000) ? 1 : 0); - printf ("\tCS5: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", - *(volatile ulong*)MPC5XXX_CS5_START, - *(volatile ulong*)MPC5XXX_CS5_STOP, - *(volatile ulong*)MPC5XXX_CS5_CFG, - (*(volatile ulong*)MPC5XXX_ADDECR & 0x00200000) ? 1 : 0); - printf ("\tCS6: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", - *(volatile ulong*)MPC5XXX_CS6_START, - *(volatile ulong*)MPC5XXX_CS6_STOP, - *(volatile ulong*)MPC5XXX_CS6_CFG, - (*(volatile ulong*)MPC5XXX_ADDECR & 0x04000000) ? 1 : 0); - printf ("\tCS7: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", - *(volatile ulong*)MPC5XXX_CS7_START, - *(volatile ulong*)MPC5XXX_CS7_STOP, - *(volatile ulong*)MPC5XXX_CS7_CFG, - (*(volatile ulong*)MPC5XXX_ADDECR & 0x08000000) ? 1 : 0); - printf ("\tBOOTCS: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", - *(volatile ulong*)MPC5XXX_BOOTCS_START, - *(volatile ulong*)MPC5XXX_BOOTCS_STOP, - *(volatile ulong*)MPC5XXX_BOOTCS_CFG, - (*(volatile ulong*)MPC5XXX_ADDECR & 0x02000000) ? 1 : 0); - printf ("\tSDRAMCS0: %08lX\n", - *(volatile ulong*)MPC5XXX_SDRAM_CS0CFG); - printf ("\tSDRAMCS1: %08lX\n", - *(volatile ulong*)MPC5XXX_SDRAM_CS1CFG); -#elif defined(CONFIG_MPC86xx) - mpc86xx_reginfo(); - -#elif defined(CONFIG_MPC85xx) - mpc85xx_reginfo(); - -#elif defined(CONFIG_BLACKFIN) - puts("\nSystem Configuration registers\n"); -#ifndef __ADSPBF60x__ - puts("\nPLL Registers\n"); - printf("\tPLL_DIV: 0x%04x PLL_CTL: 0x%04x\n", - bfin_read_PLL_DIV(), bfin_read_PLL_CTL()); - printf("\tPLL_STAT: 0x%04x PLL_LOCKCNT: 0x%04x\n", - bfin_read_PLL_STAT(), bfin_read_PLL_LOCKCNT()); - printf("\tVR_CTL: 0x%04x\n", bfin_read_VR_CTL()); - - puts("\nEBIU AMC Registers\n"); - printf("\tEBIU_AMGCTL: 0x%04x\n", bfin_read_EBIU_AMGCTL()); - printf("\tEBIU_AMBCTL0: 0x%08x EBIU_AMBCTL1: 0x%08x\n", - bfin_read_EBIU_AMBCTL0(), bfin_read_EBIU_AMBCTL1()); -# ifdef EBIU_MODE - printf("\tEBIU_MBSCTL: 0x%08x EBIU_ARBSTAT: 0x%08x\n", - bfin_read_EBIU_MBSCTL(), bfin_read_EBIU_ARBSTAT()); - printf("\tEBIU_MODE: 0x%08x EBIU_FCTL: 0x%08x\n", - bfin_read_EBIU_MODE(), bfin_read_EBIU_FCTL()); -# endif - -# ifdef EBIU_RSTCTL - puts("\nEBIU DDR Registers\n"); - printf("\tEBIU_DDRCTL0: 0x%08x EBIU_DDRCTL1: 0x%08x\n", - bfin_read_EBIU_DDRCTL0(), bfin_read_EBIU_DDRCTL1()); - printf("\tEBIU_DDRCTL2: 0x%08x EBIU_DDRCTL3: 0x%08x\n", - bfin_read_EBIU_DDRCTL2(), bfin_read_EBIU_DDRCTL3()); - printf("\tEBIU_DDRQUE: 0x%08x EBIU_RSTCTL 0x%04x\n", - bfin_read_EBIU_DDRQUE(), bfin_read_EBIU_RSTCTL()); - printf("\tEBIU_ERRADD: 0x%08x EBIU_ERRMST: 0x%04x\n", - bfin_read_EBIU_ERRADD(), bfin_read_EBIU_ERRMST()); -# else - puts("\nEBIU SDC Registers\n"); - printf("\tEBIU_SDRRC: 0x%04x EBIU_SDBCTL: 0x%04x\n", - bfin_read_EBIU_SDRRC(), bfin_read_EBIU_SDBCTL()); - printf("\tEBIU_SDSTAT: 0x%04x EBIU_SDGCTL: 0x%08x\n", - bfin_read_EBIU_SDSTAT(), bfin_read_EBIU_SDGCTL()); -# endif -#else - puts("\nCGU Registers\n"); - printf("\tCGU_DIV: 0x%08x CGU_CTL: 0x%08x\n", - bfin_read_CGU_DIV(), bfin_read_CGU_CTL()); - printf("\tCGU_STAT: 0x%08x CGU_LOCKCNT: 0x%08x\n", - bfin_read_CGU_STAT(), bfin_read_CGU_CLKOUTSEL()); - - puts("\nSMC DDR Registers\n"); - printf("\tDDR_CFG: 0x%08x DDR_TR0: 0x%08x\n", - bfin_read_DMC0_CFG(), bfin_read_DMC0_TR0()); - printf("\tDDR_TR1: 0x%08x DDR_TR2: 0x%08x\n", - bfin_read_DMC0_TR1(), bfin_read_DMC0_TR2()); - printf("\tDDR_MR: 0x%08x DDR_EMR1: 0x%08x\n", - bfin_read_DMC0_MR(), bfin_read_DMC0_EMR1()); - printf("\tDDR_CTL: 0x%08x DDR_STAT: 0x%08x\n", - bfin_read_DMC0_CTL(), bfin_read_DMC0_STAT()); - printf("\tDDR_DLLCTL:0x%08x\n", bfin_read_DMC0_DLLCTL()); -#endif -#endif /* CONFIG_BLACKFIN */ - - return 0; -} - - /**************************************************/ - -#if defined(CONFIG_CMD_REGINFO) -U_BOOT_CMD( - reginfo, 2, 1, do_reginfo, - "print register information", - "" -); -#endif diff --git a/cmd/cmd_regulator.c b/cmd/cmd_regulator.c deleted file mode 100644 index bfea6e0..0000000 --- a/cmd/cmd_regulator.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (C) 2014-2015 Samsung Electronics - * Przemyslaw Marczak - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include - -#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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct dm_regulator_uclass_platdata *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_platdata(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_platdata(struct udevice **devp, - struct dm_regulator_uclass_platdata **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_platdata(*devp); - if (!*uc_pdata) { - error("Regulator: %s - missing platform data!", 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct dm_regulator_uclass_platdata *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_platdata(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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct udevice *dev; - struct dm_regulator_uclass_platdata *uc_pdata; - struct dm_regulator_mode *modes; - const char *parent_uc; - int mode_count; - int ret; - int i; - - ret = curr_dev_and_platdata(&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_platdata *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_platdata *pdata; - int current, value, mode; - const char *mode_name; - bool enabled; - - pdata = dev_get_uclass_platdata(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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - struct udevice *dev; - int ret; - - if (currdev && (argc < 2 || strcmp(argv[1], "-a"))) { - ret = curr_dev_and_platdata(&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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct udevice *dev; - struct dm_regulator_uclass_platdata *uc_pdata; - int value; - int force; - int ret; - - ret = curr_dev_and_platdata(&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; - } - - ret = regulator_set_value(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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct udevice *dev; - struct dm_regulator_uclass_platdata *uc_pdata; - int current; - int ret; - - ret = curr_dev_and_platdata(&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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct udevice *dev; - struct dm_regulator_uclass_platdata *uc_pdata; - int mode; - int ret; - - ret = curr_dev_and_platdata(&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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct udevice *dev; - struct dm_regulator_uclass_platdata *uc_pdata; - int ret; - - ret = curr_dev_and_platdata(&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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct udevice *dev; - struct dm_regulator_uclass_platdata *uc_pdata; - int ret; - - ret = curr_dev_and_platdata(&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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - cmd_tbl_t *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/cmd/cmd_reiser.c b/cmd/cmd_reiser.c deleted file mode 100644 index 8871564..0000000 --- a/cmd/cmd_reiser.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * (C) Copyright 2003 - 2004 - * Sysgo Real-Time Solutions, AG - * Pavel Bartusek - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Reiserfs support - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_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 (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *filename = "/"; - int dev, part; - block_dev_desc_t *dev_desc=NULL; - disk_partition_t info; - - if (argc < 3) - return CMD_RET_USAGE; - - part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); - if (part < 0) - return 1; - - if (argc == 4) { - filename = argv[3]; - } - - dev = dev_desc->dev; - 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 /)", - " [directory]\n" - " - list files from 'dev' on 'interface' in a 'directory'" -); - -/****************************************************************************** - * Reiserfs boot command intepreter. Derived from diskboot - */ -int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *filename = NULL; - int dev, part; - ulong addr = 0, filelen; - disk_partition_t info; - block_dev_desc_t *dev_desc = NULL; - unsigned long count; - char *addr_str; - - switch (argc) { - case 3: - addr_str = getenv("loadaddr"); - if (addr_str != NULL) { - addr = simple_strtoul (addr_str, NULL, 16); - } else { - addr = CONFIG_SYS_LOAD_ADDR; - } - filename = getenv ("bootfile"); - count = 0; - break; - case 4: - addr = simple_strtoul (argv[3], NULL, 16); - filename = getenv ("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 = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); - if (part < 0) - return 1; - - dev = dev_desc->dev; - - 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 */ - load_addr = addr; - - printf ("\n%ld bytes read\n", filelen); - setenv_hex("filesize", filelen); - - return filelen; -} - -U_BOOT_CMD( - reiserload, 6, 0, do_reiserload, - "load binary file from a Reiser filesystem", - " [addr] [filename] [bytes]\n" - " - load binary file 'filename' from 'dev' on 'interface'\n" - " to address 'addr' from dos filesystem" -); diff --git a/cmd/cmd_remoteproc.c b/cmd/cmd_remoteproc.c deleted file mode 100644 index 794a406..0000000 --- a/cmd/cmd_remoteproc.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * (C) Copyright 2015 - * Texas Instruments Incorporated - http://www.ti.com/ - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include -#include - -/** - * 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_platdata(dev); - - 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, - 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(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - if (rproc_is_initialized()) { - printf("\tRemote Processors are already initialized\n"); - } else { - if (!rproc_init()) - return 0; - printf("Few Remote Processors failed to be initalized\n"); - } - - 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(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - if (!rproc_is_initialized()) { - printf("\t Remote Processors is not initialized\n"); - return CMD_RET_USAGE; - } - - 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(cmd_tbl_t *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, 3); - 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; - } - - if (!rproc_is_initialized()) { - printf("\tRemote Processors are not initialized\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(cmd_tbl_t *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, 3); - - if (!rproc_is_initialized()) { - printf("\tRemote Processors are not initialized\n"); - return CMD_RET_USAGE; - } - - 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 cmd_tbl_t cmd_remoteproc_sub[] = { - U_BOOT_CMD_MKENT(init, 0, 1, do_rproc_init, - "Enumerate and initialize all 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", - " [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(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - cmd_tbl_t *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 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 - Enumerate and initalize the remote processors\n" - "\tlist - list available remote processors\n" - "\tload [addr] [size]- Load the remote processor with binary\n" - "\t image stored at address [addr] in memory\n" - "\tstart - Start the remote processor(must be loaded)\n" - "\tstop - Stop the remote processor\n" - "\treset - Reset the remote processor\n" - "\tis_running - Reports if the remote processor is running\n" - "\tping - Ping the remote processor for communication\n"); diff --git a/cmd/cmd_sata.c b/cmd/cmd_sata.c deleted file mode 100644 index 76bacea..0000000 --- a/cmd/cmd_sata.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2000-2005, DENX Software Engineering - * Wolfgang Denk - * Copyright (C) Procsys. All rights reserved. - * Mushtaq Khan - * - * Copyright (C) 2008 Freescale Semiconductor, Inc. - * Dave Liu - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -static int sata_curr_device = -1; -block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; - -static unsigned long sata_bread(block_dev_desc_t *block_dev, lbaint_t start, - lbaint_t blkcnt, void *dst) -{ - return sata_read(block_dev->dev, start, blkcnt, dst); -} - -static unsigned long sata_bwrite(block_dev_desc_t *block_dev, lbaint_t start, - lbaint_t blkcnt, const void *buffer) -{ - return sata_write(block_dev->dev, start, blkcnt, buffer); -} - -int __sata_initialize(void) -{ - int rc; - int i; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) { - memset(&sata_dev_desc[i], 0, sizeof(struct block_dev_desc)); - sata_dev_desc[i].if_type = IF_TYPE_SATA; - sata_dev_desc[i].dev = i; - sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - sata_dev_desc[i].type = DEV_TYPE_HARDDISK; - sata_dev_desc[i].lba = 0; - sata_dev_desc[i].blksz = 512; - sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); - sata_dev_desc[i].block_read = sata_bread; - sata_dev_desc[i].block_write = sata_bwrite; - - rc = init_sata(i); - if (!rc) { - rc = scan_sata(i); - if (!rc && (sata_dev_desc[i].lba > 0) && - (sata_dev_desc[i].blksz > 0)) - init_part(&sata_dev_desc[i]); - } - } - sata_curr_device = 0; - return rc; -} -int sata_initialize(void) __attribute__((weak,alias("__sata_initialize"))); - -__weak int __sata_stop(void) -{ - int i, err = 0; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) - err |= reset_sata(i); - - if (err) - printf("Could not reset some SATA devices\n"); - - return err; -} -int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); - -#ifdef CONFIG_PARTITIONS -block_dev_desc_t *sata_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; -} -#endif - -static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int rc = 0; - - if (argc == 2 && strcmp(argv[1], "stop") == 0) - return sata_stop(); - - if (argc == 2 && strcmp(argv[1], "init") == 0) { - if (sata_curr_device != -1) - sata_stop(); - - return sata_initialize(); - } - - /* If the user has not yet run `sata init`, do it now */ - if (sata_curr_device == -1) - if (sata_initialize()) - return 1; - - switch (argc) { - case 0: - case 1: - return CMD_RET_USAGE; - case 2: - if (strncmp(argv[1],"inf", 3) == 0) { - int i; - putc('\n'); - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) { - if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; - printf ("SATA device %d: ", i); - dev_print(&sata_dev_desc[i]); - } - return 0; - } else if (strncmp(argv[1],"dev", 3) == 0) { - if ((sata_curr_device < 0) || (sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE)) { - puts("\nno SATA devices available\n"); - return 1; - } - printf("\nSATA device %d: ", sata_curr_device); - dev_print(&sata_dev_desc[sata_curr_device]); - return 0; - } else if (strncmp(argv[1],"part",4) == 0) { - int dev, ok; - - for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) { - if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc ('\n'); - print_part(&sata_dev_desc[dev]); - } - } - if (!ok) { - puts("\nno SATA devices available\n"); - rc ++; - } - return rc; - } - return CMD_RET_USAGE; - case 3: - if (strncmp(argv[1], "dev", 3) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - - printf("\nSATA device %d: ", dev); - if (dev >= CONFIG_SYS_SATA_MAX_DEVICE) { - puts ("unknown device\n"); - return 1; - } - dev_print(&sata_dev_desc[dev]); - - if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - - sata_curr_device = dev; - - puts("... is now current device\n"); - - return 0; - } else if (strncmp(argv[1], "part", 4) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - - if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - print_part(&sata_dev_desc[dev]); - } else { - printf("\nSATA device %d not available\n", dev); - rc = 1; - } - return rc; - } - return CMD_RET_USAGE; - - default: /* at least 4 args */ - if (strcmp(argv[1], "read") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - lbaint_t blk = simple_strtoul(argv[3], NULL, 16); - - printf("\nSATA read: device %d block # %ld, count %ld ... ", - sata_curr_device, blk, cnt); - - n = sata_read(sata_curr_device, blk, cnt, (u32 *)addr); - - /* flush cache after read */ - flush_cache(addr, cnt * sata_dev_desc[sata_curr_device].blksz); - - 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); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - - lbaint_t blk = simple_strtoul(argv[3], NULL, 16); - - printf("\nSATA write: device %d block # %ld, count %ld ... ", - sata_curr_device, blk, cnt); - - n = sata_write(sata_curr_device, blk, cnt, (u32 *)addr); - - printf("%ld blocks written: %s\n", - n, (n == cnt) ? "OK" : "ERROR"); - return (n == cnt) ? 0 : 1; - } else { - return CMD_RET_USAGE; - } - - return rc; - } -} - -U_BOOT_CMD( - sata, 5, 1, do_sata, - "SATA sub system", - "init - init SATA sub system\n" - "sata stop - disable SATA sub system\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/cmd/cmd_scsi.c b/cmd/cmd_scsi.c deleted file mode 100644 index bc7d1b6..0000000 --- a/cmd/cmd_scsi.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * (C) Copyright 2001 - * Denis Peter, MPL AG Switzerland - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * SCSI support. - */ -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SCSI_DEV_LIST -#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST -#else -#ifdef CONFIG_SCSI_SYM53C8XX -#define SCSI_VEND_ID 0x1000 -#ifndef CONFIG_SCSI_DEV_ID -#define SCSI_DEV_ID 0x0001 -#else -#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID -#endif -#elif defined CONFIG_SATA_ULI5288 - -#define SCSI_VEND_ID 0x10b9 -#define SCSI_DEV_ID 0x5288 - -#elif !defined(CONFIG_SCSI_AHCI_PLAT) -#error no scsi device defined -#endif -#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} -#endif - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) -const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; -#endif -static ccb tempccb; /* temporary scsi command buffer */ - -static unsigned char tempbuff[512]; /* temporary data buffer */ - -static int scsi_max_devs; /* number of highest available scsi device */ - -static int scsi_curr_dev; /* current device */ - -static block_dev_desc_t scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; - -/******************************************************************************** - * forward declerations of some Setup Routines - */ -void scsi_setup_test_unit_ready(ccb * pccb); -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks); -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks); -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks); - -static void scsi_setup_write_ext(ccb *pccb, lbaint_t start, - unsigned short blocks); -void scsi_setup_inquiry(ccb * pccb); -void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); - - -static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, - unsigned long *blksz); -static ulong scsi_read(block_dev_desc_t *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer); -static ulong scsi_write(block_dev_desc_t *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer); - - -/********************************************************************************* - * (re)-scan the scsi bus and reports scsi device info - * to the user if mode = 1 - */ -void scsi_scan(int mode) -{ - unsigned char i,perq,modi,lun; - lbaint_t capacity; - unsigned long blksz; - ccb* pccb=(ccb *)&tempccb; - - if(mode==1) { - printf("scanning bus for devices...\n"); - } - for(i=0;itarget=i; - for(lun=0;lunlun=lun; - pccb->pdata=(unsigned char *)&tempbuff; - pccb->datalen=512; - scsi_setup_inquiry(pccb); - if (scsi_exec(pccb) != true) { - if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { - debug ("Selection timeout ID %d\n",pccb->target); - continue; /* selection timeout => assuming no device present */ - } - scsi_print_error(pccb); - continue; - } - perq=tempbuff[0]; - modi=tempbuff[1]; - if((perq & 0x1f)==0x1f) { - continue; /* skip unknown devices */ - } - if((modi&0x80)==0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable=true; - /* get info for this device */ - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], - &tempbuff[8], 8); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0], - &tempbuff[16], 16); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], - &tempbuff[32], 4); - scsi_dev_desc[scsi_max_devs].target=pccb->target; - scsi_dev_desc[scsi_max_devs].lun=pccb->lun; - - pccb->datalen=0; - scsi_setup_test_unit_ready(pccb); - if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable == true) { - scsi_dev_desc[scsi_max_devs].type=perq; - goto removable; - } - scsi_print_error(pccb); - continue; - } - if (scsi_read_capacity(pccb, &capacity, &blksz)) { - scsi_print_error(pccb); - continue; - } - scsi_dev_desc[scsi_max_devs].lba=capacity; - scsi_dev_desc[scsi_max_devs].blksz=blksz; - scsi_dev_desc[scsi_max_devs].log2blksz = - LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type=perq; - init_part(&scsi_dev_desc[scsi_max_devs]); -removable: - if(mode==1) { - printf (" Device %d: ", scsi_max_devs); - dev_print(&scsi_dev_desc[scsi_max_devs]); - } /* if mode */ - scsi_max_devs++; - } /* next LUN */ - } - if(scsi_max_devs>0) - scsi_curr_dev=0; - else - scsi_curr_dev = -1; - - printf("Found %d device(s).\n", scsi_max_devs); -#ifndef CONFIG_SPL_BUILD - setenv_ulong("scsidevs", scsi_max_devs); -#endif -} - -int scsi_get_disk_count(void) -{ - return scsi_max_devs; -} - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) -void scsi_init(void) -{ - int busdevfunc = -1; - int i; - /* - * Find a device from the list, this driver will support a single - * controller. - */ - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - /* get PCI Device ID */ -#ifdef CONFIG_DM_PCI - struct udevice *dev; - int ret; - - ret = dm_pci_find_device(scsi_device_list[i].vendor, - scsi_device_list[i].device, 0, &dev); - if (!ret) { - busdevfunc = dm_pci_get_bdf(dev); - break; - } -#else - busdevfunc = pci_find_device(scsi_device_list[i].vendor, - scsi_device_list[i].device, - 0); -#endif - if (busdevfunc != -1) - break; - } - - if (busdevfunc == -1) { - printf("Error: SCSI Controller(s) "); - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - printf("%04X:%04X ", - scsi_device_list[i].vendor, - scsi_device_list[i].device); - } - printf("not found\n"); - return; - } -#ifdef DEBUG - else { - printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", - scsi_device_list[i].vendor, - scsi_device_list[i].device, - (busdevfunc >> 16) & 0xFF, - (busdevfunc >> 11) & 0x1F, - (busdevfunc >> 8) & 0x7); - } -#endif - bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); - scsi_low_level_init(busdevfunc); - scsi_scan(1); - bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); -} -#endif - -#ifdef CONFIG_PARTITIONS -block_dev_desc_t * scsi_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; -} -#endif - -/****************************************************************************** - * scsi boot command intepreter. Derived from diskboot - */ -int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - return common_diskboot(cmdtp, "scsi", argc, argv); -} - -/********************************************************************************* - * scsi command intepreter - */ -int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - switch (argc) { - case 0: - case 1: - return CMD_RET_USAGE; - - case 2: - if (strncmp(argv[1],"res",3) == 0) { - printf("\nReset SCSI\n"); - scsi_bus_reset(); - scsi_scan(1); - return 0; - } - if (strncmp(argv[1],"inf",3) == 0) { - int i; - for (i=0; i= CONFIG_SYS_SCSI_MAX_DEVICE)) { - printf("\nno SCSI devices available\n"); - return 1; - } - printf ("\n Device %d: ", scsi_curr_dev); - dev_print(&scsi_dev_desc[scsi_curr_dev]); - return 0; - } - if (strncmp(argv[1],"scan",4) == 0) { - scsi_scan(1); - return 0; - } - if (strncmp(argv[1],"part",4) == 0) { - int dev, ok; - for (ok=0, dev=0; dev= CONFIG_SYS_SCSI_MAX_DEVICE) { - printf("unknown device\n"); - return 1; - } - printf ("\n Device %d: ", dev); - dev_print(&scsi_dev_desc[dev]); - if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { - return 1; - } - scsi_curr_dev = dev; - printf("... is now current device\n"); - return 0; - } - if (strncmp(argv[1],"part",4) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { - print_part(&scsi_dev_desc[dev]); - } - else { - printf ("\nSCSI device %d not available\n", dev); - } - return 1; - } - return CMD_RET_USAGE; - default: - /* at least 4 args */ - if (strcmp(argv[1],"read") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - printf ("\nSCSI read: device %d block # %ld, count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_read(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); - return 0; - } else if (strcmp(argv[1], "write") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - printf("\nSCSI write: device %d block # %ld, " - "count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_write(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf("%ld blocks written: %s\n", n, - (n == cnt) ? "OK" : "ERROR"); - return 0; - } - } /* switch */ - return CMD_RET_USAGE; -} - -/**************************************************************************************** - * scsi_read - */ - -/* almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_READ_BLK 0xFFFF -#define SCSI_LBA48_READ 0xFFFFFFF - -static ulong scsi_read(block_dev_desc_t *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer) -{ - int device = block_dev->dev; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks = 0; - ccb* pccb=(ccb *)&tempccb; - device&=0xff; - /* Setup device - */ - pccb->target=scsi_dev_desc[device].target; - pccb->lun=scsi_dev_desc[device].lun; - buf_addr=(unsigned long)buffer; - start=blknr; - blks=blkcnt; - debug("\nscsi_read: dev %d startblk " LBAF - ", blccnt " LBAF " buffer %lx\n", - device, start, blks, (unsigned long)buffer); - do { - pccb->pdata=(unsigned char *)buf_addr; -#ifdef CONFIG_SYS_64BIT_LBA - if (start > SCSI_LBA48_READ) { - unsigned long blocks; - blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); - pccb->datalen = scsi_dev_desc[device].blksz * blocks; - scsi_setup_read16(pccb, start, blocks); - start += blocks; - blks -= blocks; - } else -#endif - if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; - smallblks=SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb,start,smallblks); - start+=SCSI_MAX_READ_BLK; - blks-=SCSI_MAX_READ_BLK; - } - else { - pccb->datalen=scsi_dev_desc[device].blksz * blks; - smallblks=(unsigned short) blks; - scsi_setup_read_ext(pccb,start,smallblks); - start+=blks; - blks=0; - } - debug("scsi_read_ext: startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", - start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt-=blks; - break; - } - buf_addr+=pccb->datalen; - } while(blks!=0); - debug("scsi_read_ext: end startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return(blkcnt); -} - -/******************************************************************************* - * scsi_write - */ - -/* Almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_WRITE_BLK 0xFFFF - -static ulong scsi_write(block_dev_desc_t *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer) -{ - int device = block_dev->dev; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks; - ccb* pccb = (ccb *)&tempccb; - device &= 0xff; - /* Setup device - */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", - __func__, device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; - if (blks > SCSI_MAX_WRITE_BLK) { - pccb->datalen = (scsi_dev_desc[device].blksz * - SCSI_MAX_WRITE_BLK); - smallblks = SCSI_MAX_WRITE_BLK; - scsi_setup_write_ext(pccb, start, smallblks); - start += SCSI_MAX_WRITE_BLK; - blks -= SCSI_MAX_WRITE_BLK; - } else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_write_ext(pccb, start, smallblks); - start += blks; - blks = 0; - } - debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr += pccb->datalen; - } while (blks != 0); - debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - return blkcnt; -} - -/* copy src to dest, skipping leading and trailing blanks - * and null terminate the string - */ -void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len) -{ - int start,end; - - start=0; - while(startstart) { - if(src[end]!=' ') - break; - end--; - } - for( ; start<=end; start++) { - *dest++=src[start]; - } - *dest='\0'; -} - - -/* Trim trailing blanks, and NUL-terminate string - */ -void scsi_trim_trail (unsigned char *str, unsigned int len) -{ - unsigned char *p = str + len - 1; - - while (len-- > 0) { - *p-- = '\0'; - if (*p != ' ') { - return; - } - } -} - -int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) -{ - *capacity = 0; - - memset(pccb->cmd, 0, sizeof(pccb->cmd)); - pccb->cmd[0] = SCSI_RD_CAPAC10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - - pccb->datalen = 8; - if (scsi_exec(pccb) != true) - return 1; - - *capacity = ((lbaint_t)pccb->pdata[0] << 24) | - ((lbaint_t)pccb->pdata[1] << 16) | - ((lbaint_t)pccb->pdata[2] << 8) | - ((lbaint_t)pccb->pdata[3]); - - if (*capacity != 0xffffffff) { - /* Read capacity (10) was sufficient for this drive. */ - *blksz = ((unsigned long)pccb->pdata[4] << 24) | - ((unsigned long)pccb->pdata[5] << 16) | - ((unsigned long)pccb->pdata[6] << 8) | - ((unsigned long)pccb->pdata[7]); - return 0; - } - - /* Read capacity (10) was insufficient. Use read capacity (16). */ - - memset(pccb->cmd, 0, sizeof(pccb->cmd)); - pccb->cmd[0] = SCSI_RD_CAPAC16; - pccb->cmd[1] = 0x10; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - - pccb->datalen = 16; - if (scsi_exec(pccb) != true) - return 1; - - *capacity = ((uint64_t)pccb->pdata[0] << 56) | - ((uint64_t)pccb->pdata[1] << 48) | - ((uint64_t)pccb->pdata[2] << 40) | - ((uint64_t)pccb->pdata[3] << 32) | - ((uint64_t)pccb->pdata[4] << 24) | - ((uint64_t)pccb->pdata[5] << 16) | - ((uint64_t)pccb->pdata[6] << 8) | - ((uint64_t)pccb->pdata[7]); - - *blksz = ((uint64_t)pccb->pdata[8] << 56) | - ((uint64_t)pccb->pdata[9] << 48) | - ((uint64_t)pccb->pdata[10] << 40) | - ((uint64_t)pccb->pdata[11] << 32) | - ((uint64_t)pccb->pdata[12] << 24) | - ((uint64_t)pccb->pdata[13] << 16) | - ((uint64_t)pccb->pdata[14] << 8) | - ((uint64_t)pccb->pdata[15]); - - return 0; -} - - -/************************************************************************************ - * Some setup (fill-in) routines - */ -void scsi_setup_test_unit_ready(ccb * pccb) -{ - pccb->cmd[0]=SCSI_TST_U_RDY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - pccb->cmd[4]=0; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ -} - -#ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) -{ - pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun<<5; - pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; - pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; - pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; - pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; - pccb->cmd[9] = ((unsigned char) (start)) & 0xff; - pccb->cmd[10] = 0; - pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; - pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; - pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; - pccb->cmd[14] = (unsigned char) blocks & 0xff; - pccb->cmd[15] = 0; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read16: cmd: %02X %02X " - "startblk %02X%02X%02X%02X%02X%02X%02X%02X " - "blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); -} -#endif - -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0]=SCSI_READ10; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=((unsigned char) (start>>24))&0xff; - pccb->cmd[3]=((unsigned char) (start>>16))&0xff; - pccb->cmd[4]=((unsigned char) (start>>8))&0xff; - pccb->cmd[5]=((unsigned char) (start))&0xff; - pccb->cmd[6]=0; - pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; - pccb->cmd[8]=(unsigned char) blocks & 0xff; - pccb->cmd[6]=0; - pccb->cmdlen=10; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], - pccb->cmd[7],pccb->cmd[8]); -} - -void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_WRITE10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start)) & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[9] = 0; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - __func__, - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[7], pccb->cmd[8]); -} - -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0]=SCSI_READ6; - pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); - pccb->cmd[2]=((unsigned char) (start>>8))&0xff; - pccb->cmd[3]=((unsigned char) (start))&0xff; - pccb->cmd[4]=(unsigned char) blocks & 0xff; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]); -} - - -void scsi_setup_inquiry(ccb * pccb) -{ - pccb->cmd[0]=SCSI_INQUIRY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - if(pccb->datalen>255) - pccb->cmd[4]=255; - else - pccb->cmd[4]=(unsigned char)pccb->datalen; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ -} - - -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/cmd/cmd_setexpr.c b/cmd/cmd_setexpr.c deleted file mode 100644 index e7194fc..0000000 --- a/cmd/cmd_setexpr.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright 2008 Freescale Semiconductor, Inc. - * Copyright 2013 Wolfgang Denk - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * This file provides a shell like 'expr' function to return. - */ - -#include -#include -#include -#include - -static ulong get_arg(char *s, int w) -{ - /* - * 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; - - addr = simple_strtoul(&s[1], NULL, 16); - switch (w) { - case 1: - p = map_sysmem(addr, sizeof(uchar)); - val = (ulong)*(uchar *)p; - unmap_sysmem(p); - return val; - case 2: - p = map_sysmem(addr, sizeof(ushort)); - val = (ulong)*(ushort *)p; - unmap_sysmem(p); - return val; - case 4: - default: - p = map_sysmem(addr, sizeof(ulong)); - val = *p; - unmap_sysmem(p); - return val; - } - } else { - return simple_strtoul(s, NULL, 16); - } -} - -#ifdef CONFIG_REGEX - -#include - -#define SLRE_BUFSZ 16384 -#define SLRE_PATSZ 4096 - -/* - * 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; -} - -static char *substitute(char *string, /* string buffer */ - int *slen, /* current string length */ - int ssize, /* string bufer size */ - const char *old,/* old (replaced) string */ - int olen, /* length of old string */ - const char *new,/* new (replacement) string */ - int nlen) /* length of new string */ -{ - 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 substitue */ - memcpy(p, new, nlen); - - *slen += nlen - olen; - - return p + nlen; -} - -/* - * Perform regex operations on a environment variable - * - * Returns 0 if OK, 1 in case of errors. - */ -static int regex_sub(const char *name, - const char *r, const char *s, const char *t, - int global) -{ - struct slre slre; - char data[SLRE_BUFSZ]; - char *datap = data; - const char *value; - int res, len, nlen, loop; - - if (name == NULL) - return 1; - - if (slre_compile(&slre, r) == 0) { - printf("Error compiling regex: %s\n", slre.err_str); - return 1; - } - - if (t == NULL) { - value = getenv(name); - - if (value == NULL) { - 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 : "", 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); - - if (s == NULL) - nlen = 0; - else - nlen = strlen(s); - - for (loop = 0;; loop++) { - struct cap caps[slre.num_caps + 2]; - char nbuf[SLRE_PATSZ]; - const char *old; - char *np; - int i, olen; - - (void) memset(caps, 0, sizeof(caps)); - - res = slre_match(&slre, datap, len, 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", t); - return 1; - } else { - break; - } - } - - debug("## MATCH ## %s\n", data); - - if (s == NULL) { - printf("%s=%s\n", name, t); - return 1; - } - - old = caps[0].ptr; - olen = caps[0].len; - - if (nlen + 1 >= SLRE_PATSZ) { - printf("## error: pattern buffer overflow: have %d, need %d\n", - SLRE_BUFSZ, 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, - SLRE_PATSZ, - backref, 2, - caps[i].ptr, caps[i].len); - - if (np == NULL) - return 1; - } - } - debug("## SUBST(2) ## %s\n", nbuf); - - datap = substitute(datap, &len, SLRE_BUFSZ, - 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 setenv()) : %s\n", data); - - printf("%s=%s\n", name, data); - - return setenv(name, data); -} -#endif - -static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - ulong a, b; - ulong value; - 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); - - a = get_arg(argv[2], w); - - /* plain assignment: "setexpr name value" */ - if (argc == 3) { - setenv_hex(argv[1], a); - return 0; - } - - /* 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(argv[1], argv[3], argv[4], argv[5], 1); - - if (strcmp(argv[2], "sub") == 0) - return regex_sub(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; - - b = get_arg(argv[4], w); - - 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; - } - - setenv_hex(argv[1], value); - - return 0; -} - -U_BOOT_CMD( - setexpr, 6, 0, do_setexpr, - "set environment variable as the result of eval expression", - "[.b, .w, .l] name [*]value1 [*]value2\n" - " - set environment variable 'name' to the result of the evaluated\n" - " expression specified by . can be &, |, ^, +, -, *, /, %\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 in the\n" - " string , substitute the string . The result is\n" - " assigned to . If is not supplied, use the old\n" - " value of \n" - "setexpr name sub r s [t]\n" - " - Just like gsub(), but replace only the first matching substring" -#endif -); diff --git a/cmd/cmd_sf.c b/cmd/cmd_sf.c deleted file mode 100644 index 42862d9..0000000 --- a/cmd/cmd_sf.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Command for accessing SPI flash. - * - * Copyright (C) 2008 Atmel Corporation - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -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. offset len - operate on <'offset', 'len') - * 2. 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; - unsigned int speed = CONFIG_SF_DEFAULT_SPEED; - unsigned int mode = CONFIG_SF_DEFAULT_MODE; - char *endp; -#ifdef CONFIG_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; - } - -#ifdef CONFIG_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); - device_unbind(new); - } - 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; - } - - flash = new; -#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) { - 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: %s\n", (size_t)size, (u32)offset, - ret ? "ERROR" : "OK"); - - 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: %d 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 i; - - printf("SPI flash test:\n"); - memset(&test, '\0', sizeof(test)); - test.base_ms = get_timer(0); - test.bytes = len; - if (spi_flash_erase(flash, offset, len)) { - printf("Erase failed\n"); - return -1; - } - spi_test_next_stage(&test); - - if (spi_flash_read(flash, offset, len, vbuf)) { - printf("Check read failed\n"); - 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); - - if (spi_flash_write(flash, offset, len, buf)) { - printf("Write failed\n"); - return -1; - } - memset(vbuf, '\0', len); - spi_test_next_stage(&test); - - if (spi_flash_read(flash, offset, len, vbuf)) { - printf("Read failed\n"); - 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(cmd_tbl_t *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/cmd/cmd_sha1sum.c b/cmd/cmd_sha1sum.c deleted file mode 100644 index 783ea2e..0000000 --- a/cmd/cmd_sha1sum.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * (C) Copyright 2011 - * Joe Hershberger, National Instruments, joe.hershberger@ni.com - * - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -int do_sha1sum(cmd_tbl_t *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/cmd/cmd_softswitch.c b/cmd/cmd_softswitch.c deleted file mode 100644 index f75d926..0000000 --- a/cmd/cmd_softswitch.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * cmd_softswitch.c - set the softswitch for bf60x - * - * Copyright (c) 2012 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include - -int do_softswitch(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int switchaddr, value, pin, port; - - if (argc != 5) - return CMD_RET_USAGE; - - if (strcmp(argv[2], "GPA") == 0) - port = IO_PORT_A; - else if (strcmp(argv[2], "GPB") == 0) - port = IO_PORT_B; - else - return CMD_RET_USAGE; - - switchaddr = simple_strtoul(argv[1], NULL, 16); - pin = simple_strtoul(argv[3], NULL, 16); - value = simple_strtoul(argv[4], NULL, 16); - - config_switch_bit(switchaddr, port, (1 << pin), IO_PORT_OUTPUT, value); - - return 0; -} - -U_BOOT_CMD( - softswitch_output, 5, 1, do_softswitch, - "switchaddr GPA/GPB pin_offset value", - "" -); diff --git a/cmd/cmd_sound.c b/cmd/cmd_sound.c deleted file mode 100644 index f5dd8bc..0000000 --- a/cmd/cmd_sound.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * Rajeshwari Shinde - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -/* Initilaise sound subsystem */ -static int do_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - int ret; - - ret = sound_init(gd->fdt_blob); - if (ret) { - printf("Initialise Audio driver failed\n"); - return CMD_RET_FAILURE; - } - - return 0; -} - -/* play sound from buffer */ -static int do_play(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - 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 = sound_play(msec, freq); - if (ret) { - printf("play failed"); - return CMD_RET_FAILURE; - } - - return 0; -} - -static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - cmd_tbl_t *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/cmd/cmd_source.c b/cmd/cmd_source.c deleted file mode 100644 index db7ab7e..0000000 --- a/cmd/cmd_source.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * (C) Copyright 2001 - * Kyle Harris, kharris@nexus-tech.net - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#if defined(CONFIG_8xx) -#include -#endif - -int -source (ulong addr, const char *fit_uname) -{ - ulong len; -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - 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 = getenv_yesno ("verify"); - - buf = map_sysmem(addr, 0); - switch (genimg_get_format(buf)) { -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - 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: - if (fit_uname == NULL) { - puts ("No FIT subimage unit name\n"); - return 1; - } - - fit_hdr = buf; - if (!fit_check_format (fit_hdr)) { - puts ("Bad FIT image format\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(cmd_tbl_t *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], 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 = source (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:" -#endif - ""; -#endif - -U_BOOT_CMD( - source, 2, 0, do_source, - "run script from memory", source_help_text -); -#endif diff --git a/cmd/cmd_spi.c b/cmd/cmd_spi.c deleted file mode 100644 index 64c3ffc..0000000 --- a/cmd/cmd_spi.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * (C) Copyright 2002 - * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * SPI Read/Write Utilities - */ - -#include -#include -#include -#include -#include - -/*----------------------------------------------------------------------- - * Definitions - */ - -#ifndef MAX_SPI_BYTES -# define MAX_SPI_BYTES 32 /* Maximum number of bytes we can handle */ -#endif - -#ifndef CONFIG_DEFAULT_SPI_BUS -# define CONFIG_DEFAULT_SPI_BUS 0 -#endif -#ifndef CONFIG_DEFAULT_SPI_MODE -# define CONFIG_DEFAULT_SPI_MODE SPI_MODE_0 -#endif - -/* - * Values from last command. - */ -static unsigned int bus; -static unsigned int cs; -static unsigned int mode; -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; - -#ifdef CONFIG_DM_SPI - char name[30], *str; - struct udevice *dev; - - snprintf(name, sizeof(name), "generic_%d:%d", bus, cs); - str = strdup(name); - ret = spi_get_bus_and_cs(bus, cs, 1000000, mode, "spi_generic_drv", - str, &dev, &slave); - if (ret) - return ret; -#else - slave = spi_setup_slave(bus, cs, 1000000, 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); -#ifndef CONFIG_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); -#ifndef CONFIG_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 (cmd_tbl_t *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 ((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, NULL, 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", - "[:][.] - Send and receive bits\n" - " - Identifies the SPI bus\n" - " - Identifies the chip select\n" - " - Identifies the SPI mode to use\n" - " - Number of bits to send (base 10)\n" - " - Hexadecimal string that gets sent" -); diff --git a/cmd/cmd_spibootldr.c b/cmd/cmd_spibootldr.c deleted file mode 100644 index ca76dde..0000000 --- a/cmd/cmd_spibootldr.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * U-boot - spibootldr.c - * - * Copyright (c) 2005-2008 Analog Devices Inc. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include - -#include -#include - -int do_spibootldr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - s32 addr; - - /* Get the address */ - if (argc < 2) - addr = 0; - else - addr = simple_strtoul(argv[1], NULL, 16); - - printf("## Booting ldr image at SPI offset 0x%x ...\n", addr); - - return bfrom_SpiBoot(addr, BFLAG_PERIPHERAL | 4, 0, NULL); -} - -U_BOOT_CMD( - spibootldr, 2, 0, do_spibootldr, - "boot ldr image from spi", - "[offset]\n" - " - boot ldr image stored at offset into spi\n"); diff --git a/cmd/cmd_spl.c b/cmd/cmd_spl.c deleted file mode 100644 index 057764a..0000000 --- a/cmd/cmd_spl.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2011 - * Corscience GmbH & Co. KG - Simon Schwarz - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - const cmd_tbl_t *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) && ((int)c->cmd <= SPL_EXPORT_LAST)) { - argc -= 2; - argv += 2; - if (call_bootm(argc, argv, subcmd_list[(int)c->cmd])) - return -1; - switch ((int)c->cmd) { -#ifdef CONFIG_OF_LIBFDT - case SPL_EXPORT_FDT: - printf("Argument image is now in RAM: 0x%p\n", - (void *)images.ft_addr); - 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 cmd_tbl_t cmd_spl_sub[] = { - U_BOOT_CMD_MKENT(export, 0, 1, (void *)SPL_EXPORT, "", ""), -}; - -static int do_spl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - const cmd_tbl_t *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 = (int)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 [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/cmd/cmd_strings.c b/cmd/cmd_strings.c deleted file mode 100644 index 41b1665..0000000 --- a/cmd/cmd_strings.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * cmd_strings.c - just like `strings` command - * - * Copyright (c) 2008 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include - -static char *start_addr, *last_addr; - -int do_strings(cmd_tbl_t *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", - " [byte count]\n" - " - display strings at for at least [byte count] or first double NUL" -); diff --git a/cmd/cmd_terminal.c b/cmd/cmd_terminal.c deleted file mode 100644 index 4b9c0b3..0000000 --- a/cmd/cmd_terminal.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * (C) Copyright 2007 OpenMoko, Inc. - * Written by Harald Welte - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Boot support - */ -#include -#include -#include -#include - -int do_terminal(cmd_tbl_t * 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; - - 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()) { - c = stdio_devices[0]->getc(); - if (last_tilde == 1) { - if (c == '.') { - putc(c); - putc('\n'); - break; - } else { - last_tilde = 0; - /* write the delayed tilde */ - dev->putc('~'); - /* fall-through to print current - * character */ - } - } - if (c == '~') { - last_tilde = 1; - puts("[u-boot]"); - putc(c); - } - dev->putc(c); - } - - /* read from serial port and display on console */ - if (dev->tstc()) { - c = dev->getc(); - putc(c); - } - } - return 0; -} - - -/***************************************************/ - -U_BOOT_CMD( - terminal, 3, 1, do_terminal, - "start terminal emulator", - "" -); diff --git a/cmd/cmd_test.c b/cmd/cmd_test.c deleted file mode 100644 index 7285f75..0000000 --- a/cmd/cmd_test.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2000-2009 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -#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(cmd_tbl_t *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, 10) == - simple_strtol(ap[2], NULL, 10); - break; - case OP_INT_NEQ: - expr = simple_strtol(ap[0], NULL, 10) != - simple_strtol(ap[2], NULL, 10); - break; - case OP_INT_LT: - expr = simple_strtol(ap[0], NULL, 10) < - simple_strtol(ap[2], NULL, 10); - break; - case OP_INT_LE: - expr = simple_strtol(ap[0], NULL, 10) <= - simple_strtol(ap[2], NULL, 10); - break; - case OP_INT_GT: - expr = simple_strtol(ap[0], NULL, 10) > - simple_strtol(ap[2], NULL, 10); - break; - case OP_INT_GE: - expr = simple_strtol(ap[0], NULL, 10) >= - simple_strtol(ap[2], NULL, 10); - 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(cmd_tbl_t *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(cmd_tbl_t *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/cmd/cmd_thordown.c b/cmd/cmd_thordown.c deleted file mode 100644 index 436b7f5..0000000 --- a/cmd/cmd_thordown.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * cmd_thordown.c -- USB TIZEN "THOR" Downloader gadget - * - * Copyright (C) 2013 Lukasz Majewski - * All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -int do_thor_down(cmd_tbl_t *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 = board_usb_init(controller_index, USB_INIT_DEVICE); - if (ret) { - error("USB init failed: %d", ret); - ret = CMD_RET_FAILURE; - goto exit; - } - - g_dnl_register("usb_dnl_thor"); - - ret = thor_init(); - if (ret) { - error("THOR DOWNLOAD failed: %d", ret); - ret = CMD_RET_FAILURE; - goto exit; - } - - ret = thor_handle(); - if (ret) { - error("THOR failed: %d", ret); - ret = CMD_RET_FAILURE; - goto exit; - } - -exit: - g_dnl_unregister(); - board_usb_cleanup(controller_index, USB_INIT_DEVICE); -done: - dfu_free_entities(); - - return ret; -} - -U_BOOT_CMD(thordown, CONFIG_SYS_MAXARGS, 1, do_thor_down, - "TIZEN \"THOR\" downloader", - " \n" - " - device software upgrade via LTHOR TIZEN dowload\n" - " program via on device ,\n" - " attached to interface \n" -); diff --git a/cmd/cmd_time.c b/cmd/cmd_time.c deleted file mode 100644 index de57e3b..0000000 --- a/cmd/cmd_time.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - ulong cycles = 0; - int retval = 0; - int repeatable; - - 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/cmd/cmd_tpm.c b/cmd/cmd_tpm.c deleted file mode 100644 index add6bfb..0000000 --- a/cmd/cmd_tpm.c +++ /dev/null @@ -1,802 +0,0 @@ -/* - * Copyright (c) 2013 The Chromium OS Authors. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Useful constants */ -enum { - DIGEST_LENGTH = 20, - /* max lengths, valid for RSA keys <= 2048 bits */ - TPM_PUBKEY_MAX_LENGTH = 288, -}; - -/** - * 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 - */ -static void print_byte_string(uint8_t *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 - */ -static void *parse_byte_string(char *bytes, uint8_t *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] = (uint8_t)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 - */ -static 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 - */ -static 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. - */ -static 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 - */ -static void *type_string_alloc(const char *type_str, uint32_t *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 - */ -static int type_string_pack(const char *type_str, char * const values[], - uint8_t *data) -{ - size_t offset; - uint32_t 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 - */ -static int type_string_write_vars(const char *type_str, uint8_t *data, - char * const vars[]) -{ - size_t offset; - uint32_t 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 (setenv_ulong(*vars, value)) - return -1; - } - - return 0; -} - -static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - enum tpm_startup_type mode; - - 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(mode)); -} - -static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t index, perm, size; - - 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(tpm_nv_define_space(index, perm, size)); -} - -static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t index, count, rc; - void *data; - - 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(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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t index, rc; - size_t count; - void *data; - - 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(index, data, count); - free(data); - - return report_return_code(rc); -} - -static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t index, rc; - uint8_t in_digest[20], out_digest[20]; - - 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_extend(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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t index, count, rc; - void *data; - - 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(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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint16_t presence; - - if (argc != 2) - return CMD_RET_USAGE; - presence = (uint16_t)simple_strtoul(argv[1], NULL, 0); - - return report_return_code(tpm_tsc_physical_presence(presence)); -} - -static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t count, rc; - void *data; - - 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(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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint8_t state; - - if (argc != 2) - return CMD_RET_USAGE; - state = (uint8_t)simple_strtoul(argv[1], NULL, 0); - - return report_return_code(tpm_physical_set_deactivated(state)); -} - -static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t cap_area, sub_cap, rc; - void *cap; - size_t count; - - 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(cap_area, sub_cap, cap, count); - if (!rc) { - puts("capability information:\n"); - print_byte_string(cap, count); - } - - return report_return_code(rc); -} - -#define TPM_COMMAND_NO_ARG(cmd) \ -static int do_##cmd(cmd_tbl_t *cmdtp, int flag, \ - int argc, char * const argv[]) \ -{ \ - if (argc != 1) \ - return CMD_RET_USAGE; \ - return report_return_code(cmd()); \ -} - -TPM_COMMAND_NO_ARG(tpm_init) -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 int get_tpm(struct udevice **devp) -{ - int rc; - - rc = uclass_first_device(UCLASS_TPM, devp); - if (rc) { - printf("Could not find TPM (ret=%d)\n", rc); - return CMD_RET_FAILURE; - } - - return 0; -} - -static int do_tpm_info(cmd_tbl_t *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; -} - -static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - struct udevice *dev; - void *command; - uint8_t response[1024]; - size_t count, response_length = sizeof(response); - uint32_t 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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t index, perm, size; - - 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(tpm_nv_define_space(index, perm, size)); -} - -static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t index, count, err; - void *data; - - 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(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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t index, count, err; - void *data; - - 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(index, data, count); - free(data); - - return report_return_code(err); -} - -#ifdef CONFIG_TPM_AUTH_SESSIONS - -static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t auth_handle, err; - - err = tpm_oiap(&auth_handle); - - return report_return_code(err); -} - -static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t parent_handle, key_len, key_handle, err; - uint8_t usage_auth[DIGEST_LENGTH]; - void *key; - - 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 = tpm_load_key2_oiap(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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - uint32_t key_handle, err; - uint8_t usage_auth[DIGEST_LENGTH]; - uint8_t pub_key_buffer[TPM_PUBKEY_MAX_LENGTH]; - size_t pub_key_len = sizeof(pub_key_buffer); - - 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 = tpm_get_pub_key_oiap(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(tpm_end_oiap) - -#endif /* CONFIG_TPM_AUTH_SESSIONS */ - -#define MAKE_TPM_CMD_ENTRY(cmd) \ - U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "") - -static cmd_tbl_t tpm_commands[] = { - 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_tpm_end_oiap, "", ""), - U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1, - do_tpm_load_key2_oiap, "", ""), - U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1, - do_tpm_get_pub_key_oiap, "", ""), -#endif /* CONFIG_TPM_AUTH_SESSIONS */ -}; - -static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *tpm_cmd; - - if (argc < 2) - return CMD_RET_USAGE; - tpm_cmd = find_cmd_tbl(argv[1], tpm_commands, ARRAY_SIZE(tpm_commands)); - if (!tpm_cmd) - return CMD_RET_USAGE; - - return tpm_cmd->cmd(cmdtp, flag, argc - 1, argv + 1); -} - -U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, -"Issue a TPM command", -"cmd args...\n" -" - Issue TPM command with arguments .\n" -"Admin Startup and State Commands:\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. 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 .\n" -"The Capability Commands:\n" -" get_capability cap_area sub_cap addr count\n" -" - Read bytes of TPM capability indexed by and\n" -" to memory address .\n" -#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 , bytes\n" -" into TPM using the parent key with authorization\n" -" (20 bytes hex string).\n" -" get_pub_key_oiap key_handle usage_auth\n" -" - get the public key portion of a loaded key using\n" -" authorization (20 bytes hex string)\n" -#endif /* CONFIG_TPM_AUTH_SESSIONS */ -"Endorsement Key Handling Commands:\n" -" read_pubek addr count\n" -" - Read bytes of the public endorsement key to memory\n" -" address \n" -"Integrity Collection and Reporting Commands:\n" -" extend index digest_hex_string\n" -" - Add a new measurement to a PCR. Update PCR with the 20-bytes\n" -" \n" -" pcr_read index addr count\n" -" - Read bytes from PCR to memory address .\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 with of bytes.\n" -" nv_read_value index addr count\n" -" - Read bytes from space to memory address .\n" -" nv_write_value index addr count\n" -" - Write bytes from memory address to space .\n" -"Miscellaneous helper functions:\n" -" raw_transfer byte_string\n" -" - Send a 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 with permission .\n" -" nv_read types_string index vars...\n" -" - Read from space to environment variables .\n" -" nv_write types_string index values...\n" -" - Write to space from values .\n" -); diff --git a/cmd/cmd_tpm_test.c b/cmd/cmd_tpm_test.c deleted file mode 100644 index 65332d1..0000000 --- a/cmd/cmd_tpm_test.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - * Copyright (c) 2015 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include - -/* 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(void) -{ - uint32_t result = tpm_startup(TPM_ST_CLEAR); - - return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result; -} - -static int test_timer(void) -{ - printf("get_timer(0) = %lu\n", get_timer(0)); - return 0; -} - -static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated, - uint8_t *nvlocked) -{ - struct tpm_permanent_flags pflags; - uint32_t result; - - result = tpm_get_permanent_flags(&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_set_global_lock(void) -{ - uint32_t x; - - debug("TPM: Set global lock\n"); - return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0); -} - -static uint32_t tpm_nv_write_value_lock(uint32_t index) -{ - debug("TPM: Write lock 0x%x\n", index); - - return tpm_nv_write_value(index, NULL, 0); -} - -static uint32_t tpm_nv_set_locked(void) -{ - debug("TPM: Set NV locked\n"); - - return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0); -} - -static int tpm_is_owned(void) -{ - uint8_t response[TPM_PUBEK_SIZE]; - uint32_t result; - - result = tpm_read_pubek(response, sizeof(response)); - - return result != TPM_SUCCESS; -} - -static int test_early_extend(void) -{ - uint8_t value_in[20]; - uint8_t value_out[20]; - - printf("Testing earlyextend ..."); - tpm_init(); - TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); - TPM_CHECK(tpm_continue_self_test()); - TPM_CHECK(tpm_extend(1, value_in, value_out)); - printf("done\n"); - return 0; -} - -static int test_early_nvram(void) -{ - uint32_t x; - - printf("Testing earlynvram ..."); - tpm_init(); - TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); - TPM_CHECK(tpm_continue_self_test()); - TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); - TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); - printf("done\n"); - return 0; -} - -static int test_early_nvram2(void) -{ - uint32_t x; - - printf("Testing earlynvram2 ..."); - tpm_init(); - TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); - TPM_CHECK(tpm_continue_self_test()); - TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); - TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x))); - printf("done\n"); - return 0; -} - -static int test_enable(void) -{ - uint8_t disable = 0, deactivated = 0; - - printf("Testing enable ...\n"); - tpm_init(); - TPM_CHECK(TlclStartupIfNeeded()); - TPM_CHECK(tpm_self_test_full()); - TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); - TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); - printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); - TPM_CHECK(tpm_physical_enable()); - TPM_CHECK(tpm_physical_set_deactivated(0)); - TPM_CHECK(tpm_get_flags(&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(0); \ -} while (0) - -static int test_fast_enable(void) -{ - uint8_t disable = 0, deactivated = 0; - int i; - - printf("Testing fastenable ...\n"); - tpm_init(); - TPM_CHECK(TlclStartupIfNeeded()); - TPM_CHECK(tpm_self_test_full()); - TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); - TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); - printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); - for (i = 0; i < 2; i++) { - TPM_CHECK(tpm_force_clear()); - TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); - printf("\tdisable is %d, deactivated is %d\n", disable, - deactivated); - assert(disable == 1 && deactivated == 1); - TPM_CHECK(tpm_physical_enable()); - TPM_CHECK(tpm_physical_set_deactivated(0)); - TPM_CHECK(tpm_get_flags(&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(void) -{ - uint32_t zero = 0; - uint32_t result; - uint32_t x; - - printf("Testing globallock ...\n"); - tpm_init(); - TPM_CHECK(TlclStartupIfNeeded()); - TPM_CHECK(tpm_self_test_full()); - TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); - TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); - TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero, - sizeof(uint32_t))); - TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); - TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero, - sizeof(uint32_t))); - TPM_CHECK(tpm_set_global_lock()); - /* Verifies that write to index0 fails */ - x = 1; - result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)); - assert(result == TPM_AREA_LOCKED); - TPM_CHECK(tpm_nv_read_value(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(INDEX1, (uint8_t *)&x, sizeof(x))); - TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); - assert(x == 2); - /* Turns off PP */ - tpm_tsc_physical_presence(PHYS_PRESENCE); - /* Verifies that write to index1 fails */ - x = 3; - result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)); - assert(result == TPM_BAD_PRESENCE); - TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); - assert(x == 2); - printf("\tdone\n"); - return 0; -} - -static int test_lock(void) -{ - printf("Testing lock ...\n"); - tpm_init(); - tpm_startup(TPM_ST_CLEAR); - tpm_self_test_full(); - tpm_tsc_physical_presence(PRESENCE); - tpm_nv_write_value_lock(INDEX0); - printf("\tLocked 0x%x\n", INDEX0); - printf("\tdone\n"); - return 0; -} - -static void initialise_spaces(void) -{ - uint32_t zero = 0; - uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; - - printf("\tInitialising spaces\n"); - tpm_nv_set_locked(); /* useful only the first time */ - tpm_nv_define_space(INDEX0, perm, 4); - tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4); - tpm_nv_define_space(INDEX1, perm, 4); - tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4); - tpm_nv_define_space(INDEX2, perm, 4); - tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4); - tpm_nv_define_space(INDEX3, perm, 4); - tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4); - perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR | - TPM_NV_PER_PPWRITE; - tpm_nv_define_space(INDEX_INITIALISED, perm, 1); -} - -static int test_readonly(void) -{ - uint8_t c; - uint32_t index_0, index_1, index_2, index_3; - int read0, read1, read2, read3; - - printf("Testing readonly ...\n"); - tpm_init(); - tpm_startup(TPM_ST_CLEAR); - tpm_self_test_full(); - tpm_tsc_physical_presence(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(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) { - /* The initialisation did not complete */ - initialise_spaces(); - } - - /* Checks if spaces are OK or messed up */ - read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)); - read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1)); - read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2)); - read3 = tpm_nv_read_value(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(INDEX0, (uint8_t *)&index_0, sizeof(index_0) != - TPM_SUCCESS)) { - error("\tcould not write index 0\n"); - } - tpm_nv_write_value_lock(INDEX0); - if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) == - TPM_SUCCESS) - error("\tindex 0 is not locked\n"); - - printf("\tdone\n"); - return 0; -} - -static int test_redefine_unowned(void) -{ - uint32_t perm; - uint32_t result; - uint32_t x; - - printf("Testing redefine_unowned ..."); - tpm_init(); - TPM_CHECK(TlclStartupIfNeeded()); - TPM_CHECK(tpm_self_test_full()); - TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); - assert(!tpm_is_owned()); - - /* Ensures spaces exist. */ - TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); - TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); - - /* Redefines spaces a couple of times. */ - perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK; - TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t))); - TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t))); - perm = TPM_NV_PER_PPWRITE; - TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); - TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); - - /* Sets the global lock */ - tpm_set_global_lock(); - - /* Verifies that index0 cannot be redefined */ - result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); - assert(result == TPM_AREA_LOCKED); - - /* Checks that index1 can */ - TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); - TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); - - /* Turns off PP */ - tpm_tsc_physical_presence(PHYS_PRESENCE); - - /* Verifies that neither index0 nor index1 can be redefined */ - result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); - assert(result == TPM_BAD_PRESENCE); - result = tpm_nv_define_space(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(void) -{ - uint32_t perm; - - printf("Testing spaceperm ..."); - tpm_init(); - TPM_CHECK(TlclStartupIfNeeded()); - TPM_CHECK(tpm_continue_self_test()); - TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); - TPM_CHECK(tpm_get_permissions(INDEX0, &perm)); - assert((perm & PERMPPGL) == PERMPPGL); - TPM_CHECK(tpm_get_permissions(INDEX1, &perm)); - assert((perm & PERMPP) == PERMPP); - printf("done\n"); - return 0; -} - -static int test_startup(void) -{ - uint32_t result; - printf("Testing startup ...\n"); - - tpm_init(); - result = tpm_startup(TPM_ST_CLEAR); - if (result != 0 && result != TPM_INVALID_POSTINIT) - printf("\ttpm startup failed with 0x%x\n", result); - result = tpm_get_flags(NULL, NULL, NULL); - if (result != 0) - printf("\ttpm getflags failed with 0x%x\n", result); - printf("\texecuting SelfTestFull\n"); - tpm_self_test_full(); - result = tpm_get_flags(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(void) -{ - uint32_t x; - uint8_t in[20], out[20]; - - printf("Testing timing ..."); - tpm_init(); - TTPM_CHECK(TlclStartupIfNeeded(), 50); - TTPM_CHECK(tpm_continue_self_test(), 100); - TTPM_CHECK(tpm_self_test_full(), 1000); - TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100); - TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); - TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); - TTPM_CHECK(tpm_extend(0, in, out), 200); - TTPM_CHECK(tpm_set_global_lock(), 50); - TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100); - printf("done\n"); - return 0; -} - -#define TPM_MAX_NV_WRITES_NOOWNER 64 - -static int test_write_limit(void) -{ - printf("Testing writelimit ...\n"); - int i; - uint32_t result; - - tpm_init(); - TPM_CHECK(TlclStartupIfNeeded()); - TPM_CHECK(tpm_self_test_full()); - TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); - TPM_CHECK(tpm_force_clear()); - TPM_CHECK(tpm_physical_enable()); - TPM_CHECK(tpm_physical_set_deactivated(0)); - - for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) { - printf("\twriting %d\n", i); - result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)); - switch (result) { - case TPM_SUCCESS: - break; - case TPM_MAXNVWRITES: - assert(i >= TPM_MAX_NV_WRITES_NOOWNER); - default: - error("\tunexpected error code %d (0x%x)\n", - result, result); - } - } - - /* Reset write count */ - TPM_CHECK(tpm_force_clear()); - TPM_CHECK(tpm_physical_enable()); - TPM_CHECK(tpm_physical_set_deactivated(0)); - - /* Try writing again. */ - TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i))); - printf("\tdone\n"); - return 0; -} - -#define VOIDTEST(XFUNC) \ - int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \ - char * const argv[]) \ - { \ - return test_##XFUNC(); \ - } - -#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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - cmd_tbl_t *c; - - printf("argc = %d, argv = ", argc); - do { - int i = 0; - - for (i = 0; i < argc; i++) - printf(" %s", argv[i]); - printf("\n------\n"); - } while (0); - 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/cmd/cmd_trace.c b/cmd/cmd_trace.c deleted file mode 100644 index 1e62a1a..0000000 --- a/cmd/cmd_trace.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -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 = getenv_ulong("profsize", 16, 0); - *buff = map_sysmem(getenv_ulong("profbase", 16, 0), - *buff_size); - *buff_ptr = getenv_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, used; - unsigned int needed; - 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 (%#x bytes needed)\n", needed); - used = min(avail, needed); - printf("Function trace dumped to %08lx, size %#zx\n", - (ulong)map_to_sysmem(buff + buff_ptr), used); - setenv_hex("profbase", map_to_sysmem(buff)); - setenv_hex("profsize", buff_size); - setenv_hex("profoffset", buff_ptr + used); - - return 0; -} - -static int create_call_list(int argc, char * const argv[]) -{ - size_t buff_size, avail, buff_ptr, used; - unsigned int needed; - 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 (%#x bytes needed)\n", needed); - used = min(avail, needed); - printf("Call list dumped to %08lx, size %#zx\n", - (ulong)map_to_sysmem(buff + buff_ptr), used); - - setenv_hex("profbase", map_to_sysmem(buff)); - setenv_hex("profsize", buff_size); - setenv_hex("profoffset", buff_ptr + used); - - return 0; -} - -int do_trace(cmd_tbl_t *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 [ ] - dump function list into buffer\n" - "trace calls [ ] " - "- dump function call trace into buffer" -); diff --git a/cmd/cmd_tsi148.c b/cmd/cmd_tsi148.c deleted file mode 100644 index ea96d0f..0000000 --- a/cmd/cmd_tsi148.c +++ /dev/null @@ -1,472 +0,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 - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -#include - -#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(cmd_tbl_t *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/cmd/cmd_ubi.c b/cmd/cmd_ubi.c deleted file mode 100644 index 753a4db..0000000 --- a/cmd/cmd_ubi.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Unsorted Block Image commands - * - * Copyright (C) 2008 Samsung Electronics - * Kyungmin Park - * - * Copyright 2008-2009 Stefan Roese , 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef ubi_msg -#define ubi_msg(fmt, ...) printf("UBI: " fmt "\n", ##__VA_ARGS__) - -#define DEV_TYPE_NONE 0 -#define DEV_TYPE_NAND 1 -#define DEV_TYPE_ONENAND 2 -#define DEV_TYPE_NOR 3 - -/* Private own data */ -static struct ubi_device *ubi; -static char buffer[80]; -static int ubi_initialized; - -struct selected_dev { - char part_name[80]; - int selected; - int nr; - struct mtd_info *mtd_info; -}; - -static struct selected_dev ubi_dev; - -#ifdef CONFIG_CMD_UBIFS -int ubifs_is_mounted(void); -void cmd_ubifs_umount(void); -#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) -{ - 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 = UBI_VOL_NUM_AUTO; - req.alignment = 1; - req.bytes = size; - - strcpy(req.name, volume); - req.name_len = strlen(volume); - req.name[req.name_len] = '\0'; - req.padding1 = 0; - /* 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_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 < 0 || 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; - - 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; - } - - 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; - 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); - - free(tbuf); - return err; -} - -static int ubi_dev_scan(struct mtd_info *info, char *ubidev, - const char *vid_header_offset) -{ - struct mtd_device *dev; - struct part_info *part; - struct mtd_partition mtd_part; - char ubi_mtd_param_buffer[80]; - u8 pnum; - int err; - - if (find_dev_and_part(ubidev, &dev, &pnum, &part) != 0) - return 1; - - sprintf(buffer, "mtd=%d", pnum); - memset(&mtd_part, 0, sizeof(mtd_part)); - mtd_part.name = buffer; - mtd_part.size = part->size; - mtd_part.offset = part->offset; - add_mtd_partitions(info, &mtd_part, 1); - - strcpy(ubi_mtd_param_buffer, buffer); - if (vid_header_offset) - sprintf(ubi_mtd_param_buffer, "mtd=%d,%s", pnum, - vid_header_offset); - err = ubi_mtd_param_parse(ubi_mtd_param_buffer, NULL); - if (err) { - del_mtd_partitions(info); - return -err; - } - - err = ubi_init(); - if (err) { - del_mtd_partitions(info); - return -err; - } - - ubi_initialized = 1; - - return 0; -} - -int ubi_part(char *part_name, const char *vid_header_offset) -{ - int err = 0; - char mtd_dev[16]; - struct mtd_device *dev; - struct part_info *part; - u8 pnum; - - if (mtdparts_init() != 0) { - printf("Error initializing mtdparts!\n"); - return 1; - } - -#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 - - /* todo: get dev number for NAND... */ - ubi_dev.nr = 0; - - /* - * Call ubi_exit() before re-initializing the UBI subsystem - */ - if (ubi_initialized) { - ubi_exit(); - del_mtd_partitions(ubi_dev.mtd_info); - } - - /* - * Search the mtd device number where this partition - * is located - */ - if (find_dev_and_part(part_name, &dev, &pnum, &part)) { - printf("Partition %s not found!\n", part_name); - return 1; - } - sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num); - ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev); - if (IS_ERR(ubi_dev.mtd_info)) { - printf("Partition %s not found on device %s!\n", part_name, - mtd_dev); - return 1; - } - - ubi_dev.selected = 1; - - strcpy(ubi_dev.part_name, part_name); - err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name, - vid_header_offset); - if (err) { - printf("UBI init error %d\n", err); - ubi_dev.selected = 0; - return err; - } - - ubi = ubi_devices[0]; - - return 0; -} - -static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int64_t size = 0; - ulong addr = 0; - - if (argc < 2) - return CMD_RET_USAGE; - - if (strcmp(argv[1], "part") == 0) { - const char *vid_header_offset = NULL; - - /* Print current partition */ - if (argc == 2) { - if (!ubi_dev.selected) { - printf("Error, no UBI device/partition selected!\n"); - return 1; - } - - printf("Device %d: %s, partition %s\n", - ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_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_dev.selected)) { - printf("Error, no UBI device/partition 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 */ - - /* Use maximum available size */ - size = 0; - - /* 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) { - 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); - } - - if (strncmp(argv[1], "remove", 6) == 0) { - /* E.g., remove volume */ - if (argc == 3) - return ubi_remove_vol(argv[2]); - } - - 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) { - printf("Read %lld bytes from volume %s to %lx\n", size, - argv[3], addr); - - return ubi_volume_read(argv[3], (char *)addr, size); - } - } - - printf("Please see usage\n"); - return 1; -} - -U_BOOT_CMD( - ubi, 6, 1, do_ubi, - "ubi commands", - "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]" - " - create volume name with 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" - "[Legends]\n" - " volume: character name\n" - " size: specified in bytes\n" - " type: s[tatic] or d[ynamic] (default=dynamic)" -); diff --git a/cmd/cmd_ubifs.c b/cmd/cmd_ubifs.c deleted file mode 100644 index 5e9d357..0000000 --- a/cmd/cmd_ubifs.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * (C) Copyright 2008 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - - -/* - * UBIFS command support - */ - -#undef DEBUG - -#include -#include -#include -#include - -static int ubifs_initialized; -static int ubifs_mounted; - -static int do_ubifs_mount(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - char *vol_name; - int ret; - - if (argc != 2) - return CMD_RET_USAGE; - - vol_name = argv[1]; - 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 0; -} - -int ubifs_is_mounted(void) -{ - return ubifs_mounted; -} - -void cmd_ubifs_umount(void) -{ - uboot_ubifs_umount(); - ubifs_mounted = 0; - ubifs_initialized = 0; -} - -static int do_ubifs_umount(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) -{ - if (argc != 1) - return CMD_RET_USAGE; - - if (ubifs_initialized == 0) { - printf("No UBIFS volume mounted!\n"); - return -1; - } - - cmd_ubifs_umount(); - - return 0; -} - -static int do_ubifs_ls(cmd_tbl_t *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(cmd_tbl_t *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", - "\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", - " [bytes]\n" - " - load file 'filename' to address 'addr'" -); diff --git a/cmd/cmd_universe.c b/cmd/cmd_universe.c deleted file mode 100644 index c931036..0000000 --- a/cmd/cmd_universe.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -#include - -#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(cmd_tbl_t *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/cmd/cmd_unzip.c b/cmd/cmd_unzip.c deleted file mode 100644 index 0686be6..0000000 --- a/cmd/cmd_unzip.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -static int do_unzip(cmd_tbl_t *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: %ld = 0x%lX\n", src_len, src_len); - setenv_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(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) -{ - block_dev_desc_t *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 = get_device(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", - " 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/cmd/cmd_usb.c b/cmd/cmd_usb.c deleted file mode 100644 index c7b642c..0000000 --- a/cmd/cmd_usb.c +++ /dev/null @@ -1,853 +0,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. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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) -{ - 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)); - } - printf(" - PacketSize: %d Configurations: %d\n", - dev->descriptor.bMaxPacketSize0, - 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 char *portspeed(int speed) -{ - char *speed_str; - - switch (speed) { - case USB_SPEED_SUPER: - speed_str = "5 Gb/s"; - break; - case USB_SPEED_HIGH: - speed_str = "480 Mb/s"; - break; - case USB_SPEED_LOW: - speed_str = "1.5 Mb/s"; - break; - default: - speed_str = "12 Mb/s"; - break; - } - - return speed_str; -} - -/* 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); -#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, we only want real devices */ - if (device_get_uclass_id(child) != UCLASS_USB_EMUL) { - 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]); -} - -void usb_show_tree(void) -{ -#ifdef CONFIG_DM_USB - struct udevice *bus; - - for (uclass_first_device(UCLASS_USB, &bus); - bus; - uclass_next_device(&bus)) { - struct usb_device *udev; - struct udevice *dev; - - device_find_first_child(bus, &dev); - if (dev && device_active(dev)) { - udev = dev_get_parent_priv(dev); - usb_show_subtree(udev); - } - } -#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(cmd_tbl_t *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) -{ -#ifdef 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 */ -#ifndef CONFIG_DM_USB -# ifdef CONFIG_USB_STORAGE - /* try to recognize storage devices immediately */ - usb_stor_curr_dev = usb_stor_scan(1); -# endif -# 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 show_info(struct udevice *dev) -{ - struct udevice *child; - struct usb_device *udev; - - udev = dev_get_parent_priv(dev); - usb_display_desc(udev); - usb_display_config(udev); - for (device_find_first_child(dev, &child); - child; - device_find_next_child(&child)) { - if (device_active(child)) - show_info(child); - } -} - -static int usb_device_info(void) -{ - struct udevice *bus; - - for (uclass_first_device(UCLASS_USB, &bus); - bus; - uclass_next_device(&bus)) { - struct udevice *hub; - - device_find_first_child(bus, &hub); - if (device_get_uclass_id(hub) == UCLASS_USB_HUB && - device_active(hub)) { - show_info(hub); - } - } - - return 0; -} -#endif - -/****************************************************************************** - * usb command intepreter - */ -static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - struct usb_device *udev = NULL; - int i; - extern char usb_started; -#ifdef CONFIG_USB_STORAGE - block_dev_desc_t *stor_dev; -#endif - - 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_device_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(); - - if (strncmp(argv[1], "part", 4) == 0) { - int devno, ok = 0; - if (argc == 2) { - for (devno = 0; ; ++devno) { - stor_dev = usb_stor_get_dev(devno); - if (stor_dev == NULL) - break; - if (stor_dev->type != DEV_TYPE_UNKNOWN) { - ok++; - if (devno) - printf("\n"); - debug("print_part of %x\n", devno); - print_part(stor_dev); - } - } - } else { - devno = simple_strtoul(argv[2], NULL, 16); - stor_dev = usb_stor_get_dev(devno); - if (stor_dev != NULL && - stor_dev->type != DEV_TYPE_UNKNOWN) { - ok++; - debug("print_part of %x\n", devno); - print_part(stor_dev); - } - } - if (!ok) { - printf("\nno USB devices available\n"); - return 1; - } - return 0; - } - if (strcmp(argv[1], "read") == 0) { - if (usb_stor_curr_dev < 0) { - printf("no current device selected\n"); - return 1; - } - if (argc == 5) { - unsigned long addr = simple_strtoul(argv[2], NULL, 16); - unsigned long blk = simple_strtoul(argv[3], NULL, 16); - unsigned long cnt = simple_strtoul(argv[4], NULL, 16); - unsigned long n; - printf("\nUSB read: device %d block # %ld, count %ld" - " ... ", usb_stor_curr_dev, blk, cnt); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); - n = stor_dev->block_read(stor_dev, blk, cnt, - (ulong *)addr); - printf("%ld blocks read: %s\n", n, - (n == cnt) ? "OK" : "ERROR"); - if (n == cnt) - return 0; - return 1; - } - } - if (strcmp(argv[1], "write") == 0) { - if (usb_stor_curr_dev < 0) { - printf("no current device selected\n"); - return 1; - } - if (argc == 5) { - unsigned long addr = simple_strtoul(argv[2], NULL, 16); - unsigned long blk = simple_strtoul(argv[3], NULL, 16); - unsigned long cnt = simple_strtoul(argv[4], NULL, 16); - unsigned long n; - printf("\nUSB write: device %d block # %ld, count %ld" - " ... ", usb_stor_curr_dev, blk, cnt); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); - n = stor_dev->block_write(stor_dev, blk, cnt, - (ulong *)addr); - printf("%ld blocks write: %s\n", n, - (n == cnt) ? "OK" : "ERROR"); - if (n == cnt) - return 0; - return 1; - } - } - if (strncmp(argv[1], "dev", 3) == 0) { - if (argc == 3) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - printf("\nUSB device %d: ", dev); - stor_dev = usb_stor_get_dev(dev); - if (stor_dev == NULL) { - printf("unknown device\n"); - return 1; - } - printf("\n Device %d: ", dev); - dev_print(stor_dev); - if (stor_dev->type == DEV_TYPE_UNKNOWN) - return 1; - usb_stor_curr_dev = dev; - printf("... is now current device\n"); - return 0; - } else { - printf("\nUSB device %d: ", usb_stor_curr_dev); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); - dev_print(stor_dev); - if (stor_dev->type == DEV_TYPE_UNKNOWN) - return 1; - return 0; - } - return 0; - } -#endif /* CONFIG_USB_STORAGE */ - return CMD_RET_USAGE; -} - -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/cmd/cmd_usb_mass_storage.c b/cmd/cmd_usb_mass_storage.c deleted file mode 100644 index 0415591..0000000 --- a/cmd/cmd_usb_mass_storage.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (C) 2011 Samsung Electronics - * Lukasz Majewski - * - * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static int ums_read_sector(struct ums *ums_dev, - ulong start, lbaint_t blkcnt, void *buf) -{ - block_dev_desc_t *block_dev = &ums_dev->block_dev; - lbaint_t blkstart = start + ums_dev->start_sector; - - return block_dev->block_read(block_dev, blkstart, blkcnt, buf); -} - -static int ums_write_sector(struct ums *ums_dev, - ulong start, lbaint_t blkcnt, const void *buf) -{ - block_dev_desc_t *block_dev = &ums_dev->block_dev; - lbaint_t blkstart = start + ums_dev->start_sector; - - return block_dev->block_write(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 = 0; - ums_count = 0; -} - -#define UMS_NAME_LEN 16 - -static int ums_init(const char *devtype, const char *devnums) -{ - char *s, *t, *devnum, *name; - block_dev_desc_t *block_dev; - int ret; - struct ums *ums_new; - - s = strdup(devnums); - if (!s) - return -1; - - t = s; - ums_count = 0; - - for (;;) { - devnum = strsep(&t, ","); - if (!devnum) - break; - - ret = get_device(devtype, devnum, &block_dev); - if (ret < 0) - goto cleanup; - - /* f_mass_storage.c assumes SECTOR_SIZE sectors */ - if (block_dev->blksz != SECTOR_SIZE) { - ret = -1; - goto cleanup; - } - - ums_new = realloc(ums, (ums_count + 1) * sizeof(*ums)); - if (!ums_new) { - ret = -1; - goto cleanup; - } - ums = ums_new; - - ums[ums_count].read_sector = ums_read_sector; - ums[ums_count].write_sector = ums_write_sector; - ums[ums_count].start_sector = 0; - ums[ums_count].num_sectors = block_dev->lba; - name = malloc(UMS_NAME_LEN); - if (!name) { - ret = -1; - 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 %d, hwpart %d, sector %#x, count %#x\n", - ums_count, ums[ums_count].block_dev.dev, - ums[ums_count].block_dev.hwpart, - ums[ums_count].start_sector, - ums[ums_count].num_sectors); - - ums_count++; - } - - if (!ums_count) - ret = -1; - else - ret = 0; - -cleanup: - free(s); - - if (ret < 0) - ums_fini(); - - return ret; -} - -int do_usb_mass_storage(cmd_tbl_t *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 (board_usb_init(controller_index, USB_INIT_DEVICE)) { - error("Couldn't init USB controller."); - rc = CMD_RET_FAILURE; - goto cleanup_ums_init; - } - - rc = fsg_init(ums, ums_count); - if (rc) { - error("fsg_init failed"); - rc = CMD_RET_FAILURE; - goto cleanup_board; - } - - rc = g_dnl_register("usb_dnl_ums"); - if (rc) { - error("g_dnl_register failed"); - 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; - } - } - -cleanup_register: - g_dnl_unregister(); -cleanup_board: - board_usb_cleanup(controller_index, USB_INIT_DEVICE); -cleanup_ums_init: - ums_fini(); - - return rc; -} - -U_BOOT_CMD(ums, 4, 1, do_usb_mass_storage, - "Use the UMS [USB Mass Storage]", - " [] e.g. ums 0 mmc 0\n" - " devtype defaults to mmc" -); diff --git a/cmd/cmd_version.c b/cmd/cmd_version.c deleted file mode 100644 index 1be0667..0000000 --- a/cmd/cmd_version.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2000-2009 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#ifdef CONFIG_SYS_COREBOOT -#include -#endif - -const char __weak version_string[] = U_BOOT_VERSION_STRING; - -static int do_version(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - printf("\n%s\n", version_string); -#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/cmd/cmd_ximg.c b/cmd/cmd_ximg.c deleted file mode 100644 index d033c15..0000000 --- a/cmd/cmd_ximg.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * (C) Copyright 2000-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2003 - * Kai-Uwe Bloem, Auerswald GmbH & Co KG, - * - * SPDX-License-Identifier: GPL-2.0+ - */ - - -/* - * Multi Image extract - */ -#include -#include -#include -#include -#include -#if defined(CONFIG_BZIP2) -#include -#endif -#include -#include - -#ifndef CONFIG_SYS_XIMG_LEN -/* use 8MByte as default max gunzip size */ -#define CONFIG_SYS_XIMG_LEN 0x800000 -#endif - -static int -do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) -{ - ulong addr = load_addr; - ulong dest = 0; - ulong data, len; - int verify; - int part = 0; -#if defined(CONFIG_IMAGE_FORMAT_LEGACY) - 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 = getenv_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_IMAGE_FORMAT_LEGACY) - 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)) { - 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 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; - } - - 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_IMAGE_FORMAT_LEGACY) - 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, len); - - setenv_hex("fileaddr", data); - setenv_hex("filesize", len); - - return 0; -} - -#ifdef CONFIG_SYS_LONGHELP -static char imgextract_help_text[] = - "addr part [dest]\n" - " - extract from legacy image at and copy to " -#if defined(CONFIG_FIT) - "\n" - "addr uname [dest]\n" - " - extract subimage from FIT image at and copy to " -#endif - ""; -#endif - -U_BOOT_CMD( - imxtract, 4, 1, do_imgextract, - "extract a part of a multi-image", imgextract_help_text -); diff --git a/cmd/cmd_yaffs2.c b/cmd/cmd_yaffs2.c deleted file mode 100644 index 9244606..0000000 --- a/cmd/cmd_yaffs2.c +++ /dev/null @@ -1,326 +0,0 @@ -/* 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 - -#include -#include - -#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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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/cmd/cmd_zfs.c b/cmd/cmd_zfs.c deleted file mode 100644 index 0aed29e..0000000 --- a/cmd/cmd_zfs.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * - * ZFS filesystem porting to Uboot by - * Jorgen Lundman - * - * zfsfs support - * made from existing GRUB Sources by Sun, GNU and others. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) -#include -#endif - -#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *filename = NULL; - int dev; - int part; - ulong addr = 0; - disk_partition_t info; - block_dev_desc_t *dev_desc; - char buf[12]; - 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 = getenv("bootfile"); - switch (argc) { - case 3: - addr_str = getenv("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 = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); - if (part < 0) - return 1; - - dev = dev_desc->dev; - 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 */ - load_addr = addr; - - printf("%llu bytes read\n", zfile.size); - setenv_hex("filesize", zfile.size); - - return 0; -} - - -int zfs_print(const char *entry, const struct zfs_dirhook_info *data) -{ - printf("%s %s\n", - data->dir ? " " : " ", - entry); - return 0; /* 0 continue, 1 stop */ -} - - - -static int do_zfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - const char *filename = "/"; - int part; - block_dev_desc_t *dev_desc; - disk_partition_t info; - struct device_s vdev; - - if (argc < 2) - return cmd_usage(cmdtp); - - if (argc == 4) - filename = argv[3]; - - part = get_device_and_partition(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 /)", - " [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", - " [addr] [filename] [bytes]\n" - " - load binary file '/DATASET/@/$dir/$file' from 'dev' on 'interface'\n" - " to address 'addr' from ZFS filesystem"); diff --git a/cmd/cmd_zip.c b/cmd/cmd_zip.c deleted file mode 100644 index 7fcd9d5..0000000 --- a/cmd/cmd_zip.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * (C) Copyright 2012 - * Lei Wen , Marvell Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -static int do_zip(cmd_tbl_t *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: %ld = 0x%lX\n", dst_len, dst_len); - setenv_hex("filesize", dst_len); - - return 0; -} - -U_BOOT_CMD( - zip, 5, 1, do_zip, - "zip a memory region", - "srcaddr srcsize dstaddr [dstsize]" -); diff --git a/cmd/console.c b/cmd/console.c new file mode 100644 index 0000000..9a356ec --- /dev/null +++ b/cmd/console.c @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Boot support + */ +#include +#include +#include + +extern void _do_coninfo (void); +static int do_coninfo(cmd_tbl_t *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/cmd/cplbinfo.c b/cmd/cplbinfo.c new file mode 100644 index 0000000..ab5b3b5 --- /dev/null +++ b/cmd/cplbinfo.c @@ -0,0 +1,60 @@ +/* + * cmd_cplbinfo.c - dump the instruction/data cplb tables + * + * Copyright (c) 2007-2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include + +/* + * Translate the PAGE_SIZE bits into a human string + */ +static const char *cplb_page_size(uint32_t data) +{ + static const char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" }; + return page_size_string_table[(data & PAGE_SIZE_MASK) >> PAGE_SIZE_SHIFT]; +} + +/* + * show a hardware cplb table + */ +static void show_cplb_table(uint32_t *addr, uint32_t *data) +{ + int i; + printf(" Address Data Size Valid Locked\n"); + for (i = 1; i <= 16; ++i) { + printf(" %2i 0x%p 0x%05X %s %c %c\n", + i, (void *)*addr, *data, + cplb_page_size(*data), + (*data & CPLB_VALID ? 'Y' : 'N'), + (*data & CPLB_LOCK ? 'Y' : 'N')); + ++addr; + ++data; + } +} + +/* + * display current instruction and data cplb tables + */ +int do_cplbinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + printf("%s CPLB table [%08x]:\n", "Instruction", *(uint32_t *)DMEM_CONTROL); + show_cplb_table((uint32_t *)ICPLB_ADDR0, (uint32_t *)ICPLB_DATA0); + + printf("%s CPLB table [%08x]:\n", "Data", *(uint32_t *)IMEM_CONTROL); + show_cplb_table((uint32_t *)DCPLB_ADDR0, (uint32_t *)DCPLB_DATA0); + + return 0; +} + +U_BOOT_CMD( + cplbinfo, 1, 0, do_cplbinfo, + "display current CPLB tables", + "" +); diff --git a/cmd/cpu.c b/cmd/cpu.c new file mode 100644 index 0000000..b4af64f --- /dev/null +++ b/cmd/cpu.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015 Google, Inc + * Written by Simon Glass + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +static const char *cpu_feature_name[CPU_FEAT_COUNT] = { + "L1 cache", + "MMU", +}; + +static int print_cpu_list(bool detail) +{ + struct udevice *dev; + struct uclass *uc; + char buf[100]; + int ret; + + ret = uclass_get(UCLASS_CPU, &uc); + if (ret) { + printf("Cannot find CPU uclass\n"); + return ret; + } + uclass_foreach_dev(dev, uc) { + struct cpu_platdata *plat = dev_get_parent_platdata(dev); + struct cpu_info info; + bool first; + int i; + + ret = cpu_get_desc(dev, buf, sizeof(buf)); + printf("%3d: %-10s %s\n", dev->seq, dev->name, + ret ? "" : buf); + if (!detail) + continue; + ret = cpu_get_info(dev, &info); + if (ret) { + printf("\t(no detail available"); + if (ret != -ENOSYS) + printf(": err=%d\n", ret); + printf(")\n"); + continue; + } + printf("\tID = %d, freq = ", plat->cpu_id); + print_freq(info.cpu_freq, ""); + first = true; + 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"); + } + + return 0; +} + +static int do_cpu_list(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + if (print_cpu_list(false)) + return CMD_RET_FAILURE; + + return 0; +} + +static int do_cpu_detail(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (print_cpu_list(true)) + return CMD_RET_FAILURE; + + return 0; +} + +static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *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/cmd/cramfs.c b/cmd/cramfs.c new file mode 100644 index 0000000..1d31326 --- /dev/null +++ b/cmd/cramfs.c @@ -0,0 +1,207 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + * + * based on: cmd_jffs2.c + * + * Add support for a CRAMFS located in RAM + */ + + +/* + * CRAMFS support + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 + +#ifdef CONFIG_CRAMFS_CMDLINE +#include + +#ifdef CONFIG_SYS_NO_FLASH +# define OFFSET_ADJUSTMENT 0 +#else +# define OFFSET_ADJUSTMENT (flash_info[id.num].start[0]) +#endif + +#ifndef CONFIG_CMD_JFFS2 +#include +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_CMD_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *filename; + int size; + ulong offset = load_addr; + + struct part_info part; + struct mtd_device dev; + struct mtdids id; + + ulong addr; + addr = simple_strtoul(getenv("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 = addr - OFFSET_ADJUSTMENT; + + /* pre-set Boot file name */ + if ((filename = getenv("bootfile")) == NULL) { + filename = "uImage"; + } + + if (argc == 2) { + filename = argv[1]; + } + if (argc == 3) { + offset = simple_strtoul(argv[1], NULL, 0); + load_addr = offset; + filename = argv[2]; + } + + size = 0; + if (cramfs_check(&part)) + size = cramfs_load ((char *) offset, &part, filename); + + if (size > 0) { + printf("### CRAMFS load complete: %d bytes loaded to 0x%lx\n", + size, offset); + setenv_hex("filesize", size); + } else { + printf("### CRAMFS LOAD ERROR<%x> for %s!\n", size, filename); + } + + 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(cmd_tbl_t *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(getenv("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 = addr - OFFSET_ADJUSTMENT; + + if (argc == 2) + filename = argv[1]; + + ret = 0; + if (cramfs_check(&part)) + ret = cramfs_ls (&part, filename); + + 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" +); + +#endif /* #ifdef CONFIG_CRAMFS_CMDLINE */ + +/***************************************************/ diff --git a/cmd/dataflash_mmc_mux.c b/cmd/dataflash_mmc_mux.c new file mode 100644 index 0000000..3832248 --- /dev/null +++ b/cmd/dataflash_mmc_mux.c @@ -0,0 +1,48 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +static int mmc_nspi (const char *); + +int do_dataflash_mmc_mux (cmd_tbl_t *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/cmd/date.c b/cmd/date.c new file mode 100644 index 0000000..8714699 --- /dev/null +++ b/cmd/date.c @@ -0,0 +1,250 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * RTC, Date & Time support: get and set date & time + */ +#include +#include +#include +#include +#include + +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(cmd_tbl_t *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++ = '\0'; + if ((len - (ptr - datestr)) != 2) + return (-1); + + len = strlen (datestr); + + 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, ¢ury) || + 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/cmd/dcr.c b/cmd/dcr.c new file mode 100644 index 0000000..cc77250 --- /dev/null +++ b/cmd/dcr.c @@ -0,0 +1,222 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * AMCC 4XX DCR Functions + */ + +#include +#include +#include +#include +#include + +unsigned long get_dcr (unsigned short); +unsigned long set_dcr (unsigned short, unsigned long); + +/* ======================================================================= + * Interpreter command to retrieve an AMCC PPC 4xx Device Control Register + * ======================================================================= + */ +int do_getdcr ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] ) +{ + unsigned short dcrn; /* Device Control Register Num */ + unsigned long value; /* DCR's value */ + + unsigned long get_dcr (unsigned short); + + /* Validate arguments */ + if (argc < 2) + return CMD_RET_USAGE; + + /* Get a DCR */ + dcrn = (unsigned short) simple_strtoul (argv[1], NULL, 16); + value = get_dcr (dcrn); + + printf ("%04x: %08lx\n", dcrn, value); + + return 0; +} + + +/* ====================================================================== + * Interpreter command to set an AMCC PPC 4xx Device Control Register + * ====================================================================== +*/ +int do_setdcr (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned short dcrn; /* Device Control Register Num */ + unsigned long value; + + /* DCR's value */ + int nbytes; + + /* Validate arguments */ + if (argc < 2) + return CMD_RET_USAGE; + + /* Set a DCR */ + dcrn = (unsigned short) simple_strtoul (argv[1], NULL, 16); + do { + value = get_dcr (dcrn); + printf ("%04x: %08lx", dcrn, value); + nbytes = cli_readline(" ? "); + if (nbytes == 0) { + /* + * pressed as only input, don't modify current + * location and exit command. + */ + nbytes = 1; + return 0; + } else { + unsigned long i; + char *endp; + + i = simple_strtoul (console_buffer, &endp, 16); + nbytes = endp - console_buffer; + if (nbytes) + set_dcr (dcrn, i); + } + } while (nbytes); + + return 0; +} + +/* ======================================================================= + * Interpreter command to retrieve an register value through AMCC PPC 4xx + * Device Control Register inderect addressing. + * ======================================================================= + */ +int do_getidcr (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned short adr_dcrn; /* Device Control Register Num for Address */ + unsigned short dat_dcrn; /* Device Control Register Num for Data */ + unsigned short offset; /* Register's offset */ + unsigned long value; /* Register's value */ + char *ptr = NULL; + char buf[80]; + + /* Validate arguments */ + if (argc < 3) + return CMD_RET_USAGE; + + /* Find out whether ther is '.' (dot) symbol in the first parameter. */ + strncpy (buf, argv[1], sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; /* will guarantee zero-end string */ + ptr = strchr (buf, '.'); + + if (ptr != NULL) { + /* First parameter has format adr_dcrn.dat_dcrn */ + *ptr++ = 0; /* erase '.', create zero-end string */ + adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16); + dat_dcrn = (unsigned short) simple_strtoul (ptr, NULL, 16); + } else { + /* + * First parameter has format adr_dcrn; dat_dcrn will be + * calculated as adr_dcrn+1. + */ + adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16); + dat_dcrn = adr_dcrn+1; + } + + /* Register's offset */ + offset = (unsigned short) simple_strtoul (argv[2], NULL, 16); + + /* Disable interrupts */ + disable_interrupts (); + /* Set offset */ + set_dcr (adr_dcrn, offset); + /* get data */ + value = get_dcr (dat_dcrn); + /* Enable interrupts */ + enable_interrupts (); + + printf ("%04x.%04x-%04x Read %08lx\n", adr_dcrn, dat_dcrn, offset, value); + + return 0; +} + +/* ======================================================================= + * Interpreter command to update an register value through AMCC PPC 4xx + * Device Control Register inderect addressing. + * ======================================================================= + */ +int do_setidcr (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned short adr_dcrn; /* Device Control Register Num for Address */ + unsigned short dat_dcrn; /* Device Control Register Num for Data */ + unsigned short offset; /* Register's offset */ + unsigned long value; /* Register's value */ + char *ptr = NULL; + char buf[80]; + + /* Validate arguments */ + if (argc < 4) + return CMD_RET_USAGE; + + /* Find out whether ther is '.' (dot) symbol in the first parameter. */ + strncpy (buf, argv[1], sizeof(buf)-1); + buf[sizeof(buf)-1] = 0; /* will guarantee zero-end string */ + ptr = strchr (buf, '.'); + + if (ptr != NULL) { + /* First parameter has format adr_dcrn.dat_dcrn */ + *ptr++ = 0; /* erase '.', create zero-end string */ + adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16); + dat_dcrn = (unsigned short) simple_strtoul (ptr, NULL, 16); + } else { + /* + * First parameter has format adr_dcrn; dat_dcrn will be + * calculated as adr_dcrn+1. + */ + adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16); + dat_dcrn = adr_dcrn+1; + } + + /* Register's offset */ + offset = (unsigned short) simple_strtoul (argv[2], NULL, 16); + /* New value */ + value = (unsigned long) simple_strtoul (argv[3], NULL, 16); + + /* Disable interrupts */ + disable_interrupts (); + /* Set offset */ + set_dcr (adr_dcrn, offset); + /* set data */ + set_dcr (dat_dcrn, value); + /* Enable interrupts */ + enable_interrupts (); + + printf ("%04x.%04x-%04x Write %08lx\n", adr_dcrn, dat_dcrn, offset, value); + + return 0; +} + +/***************************************************/ + +U_BOOT_CMD( + getdcr, 2, 1, do_getdcr, + "Get an AMCC PPC 4xx DCR's value", + "dcrn - return a DCR's value." +); +U_BOOT_CMD( + setdcr, 2, 1, do_setdcr, + "Set an AMCC PPC 4xx DCR's value", + "dcrn - set a DCR's value." +); + +U_BOOT_CMD( + getidcr, 3, 1, do_getidcr, + "Get a register value via indirect DCR addressing", + "adr_dcrn[.dat_dcrn] offset - write offset to adr_dcrn, read value from dat_dcrn." +); + +U_BOOT_CMD( + setidcr, 4, 1, do_setidcr, + "Set a register value via indirect DCR addressing", + "adr_dcrn[.dat_dcrn] offset value - write offset to adr_dcrn, write value to dat_dcrn." +); diff --git a/cmd/demo.c b/cmd/demo.c new file mode 100644 index 0000000..209dc4a --- /dev/null +++ b/cmd/demo.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013 Google, Inc + * + * (C) Copyright 2012 + * Pavel Herrmann + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +struct udevice *demo_dev; + +static int do_demo_hello(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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, platdata %08x\n", + i++, map_to_sysmem(dev), + map_to_sysmem(dev->driver->ops), + map_to_sysmem(dev_get_platdata(dev))); + } + + return cmd_process_error(cmdtp, ret); +} + +static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *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 [] Say hello\n" + "demo light [] Set or get the lights\n" + "demo status Get demo device status\n" + "demo list List available demo devices" +); diff --git a/cmd/dfu.c b/cmd/dfu.c new file mode 100644 index 0000000..6d95ce9 --- /dev/null +++ b/cmd/dfu.c @@ -0,0 +1,113 @@ +/* + * cmd_dfu.c -- dfu command + * + * Copyright (C) 2015 + * Lukasz Majewski + * + * Copyright (C) 2012 Samsung Electronics + * authors: Andrzej Pietrasiewicz + * Lukasz Majewski + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + bool dfu_reset = false; + + if (argc < 4) + return CMD_RET_USAGE; + + char *usb_controller = argv[1]; + char *interface = argv[2]; + char *devstring = argv[3]; + + int ret, i = 0; +#ifdef CONFIG_DFU_TFTP + unsigned long addr = 0; + if (!strcmp(argv[1], "tftp")) { + if (argc == 5) + addr = simple_strtoul(argv[4], NULL, 0); + + return update_tftp(addr, interface, devstring); + } +#endif + + ret = dfu_init_env_entities(interface, devstring); + if (ret) + goto done; + + ret = CMD_RET_SUCCESS; + if (argc > 4 && strcmp(argv[4], "list") == 0) { + dfu_show_entities(); + goto done; + } + + int controller_index = simple_strtoul(usb_controller, NULL, 0); + board_usb_init(controller_index, USB_INIT_DEVICE); + g_dnl_clear_detach(); + g_dnl_register("usb_dnl_dfu"); + while (1) { + if (g_dnl_detach()) { + /* + * Check if USB bus reset is performed after detach, + * which indicates that -R switch has been passed to + * dfu-util. In this case reboot the device + */ + if (dfu_usb_get_reset()) { + dfu_reset = true; + goto exit; + } + + /* + * This extra number of usb_gadget_handle_interrupts() + * calls is necessary to assure correct transmission + * completion with dfu-util + */ + if (++i == 10000) + goto exit; + } + + if (ctrlc()) + goto exit; + + WATCHDOG_RESET(); + usb_gadget_handle_interrupts(controller_index); + } +exit: + g_dnl_unregister(); + board_usb_cleanup(controller_index, USB_INIT_DEVICE); +done: + dfu_free_entities(); + + if (dfu_reset) + run_command("reset", 0); + + g_dnl_clear_detach(); + + return ret; +} + +U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, + "Device Firmware Upgrade", + " [list]\n" + " - device firmware upgrade via \n" + " on device , attached to interface\n" + " \n" + " [list] - list available alt settings\n" +#ifdef CONFIG_DFU_TFTP + "dfu tftp []\n" + " - device firmware upgrade via TFTP\n" + " on device , attached to interface\n" + " \n" + " [] - address where FIT image has been stored\n" +#endif +); diff --git a/cmd/diag.c b/cmd/diag.c new file mode 100644 index 0000000..14ae04f --- /dev/null +++ b/cmd/diag.c @@ -0,0 +1,60 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Diagnostics support + */ +#include +#include +#include + +int do_diag (cmd_tbl_t * 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 [ [ ...]]'" + " to get more info.\n"); + puts ("Use 'diag run [ [ ...]]'" + " 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/cmd/disk.c b/cmd/disk.c new file mode 100644 index 0000000..3025225 --- /dev/null +++ b/cmd/disk.c @@ -0,0 +1,132 @@ +/* + * (C) Copyright 2000-2011 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include + +#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \ + defined(CONFIG_USB_STORAGE) +int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, + char *const argv[]) +{ + int dev, part; + ulong addr = CONFIG_SYS_LOAD_ADDR; + ulong cnt; + disk_partition_t info; +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + image_header_t *hdr; +#endif + block_dev_desc_t *dev_desc; + +#if defined(CONFIG_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 = get_device_and_partition(intf, (argc == 3) ? argv[2] : NULL, + &dev_desc, &info, 1); + if (part < 0) { + bootstage_error(BOOTSTAGE_ID_IDE_TYPE); + return 1; + } + + dev = dev_desc->dev; + 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 (dev_desc->block_read(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_IMAGE_FORMAT_LEGACY) + 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 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_IDE_FORMAT); + puts("** Unknown image type\n"); + return 1; + } + + cnt += info.blksz - 1; + cnt /= info.blksz; + cnt -= 1; + + if (dev_desc->block_read(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 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)) { + bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ); + puts("** Bad FIT image format\n"); + return 1; + } + bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK); + fit_print_contents(fit_hdr); + } +#endif + + flush_cache(addr, (cnt+1)*info.blksz); + + /* Loading ok, update default load address */ + load_addr = addr; + + return bootm_maybe_autostart(cmdtp, argv[0]); +} +#endif diff --git a/cmd/display.c b/cmd/display.c new file mode 100644 index 0000000..bc1b1eb --- /dev/null +++ b/cmd/display.c @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#undef DEBUG_DISP + +int do_display (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int i; + + /* Clear display */ + display_set(DISPLAY_CLEAR | DISPLAY_HOME); + + if (argc < 2) + return (0); + + for (i = 1; i < argc; i++) { + char *p = argv[i]; + + if (i > 1) { /* Insert a space between strings */ + display_putc(' '); + } + + while ((*p)) { +#ifdef DEBUG_DISP + putc(*p); +#endif + display_putc(*p++); + } + } + +#ifdef DEBUG_DISP + putc('\n'); +#endif + + return (0); +} + +/***************************************************/ + +U_BOOT_CMD( + display, CONFIG_SYS_MAXARGS, 1, do_display, + "display string on dot matrix display", + "[]\n" + " - with argument: display on dot matrix display\n" + " - without arguments: clear dot matrix display" +); diff --git a/cmd/dtt.c b/cmd/dtt.c new file mode 100644 index 0000000..f2e750f --- /dev/null +++ b/cmd/dtt.c @@ -0,0 +1,119 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include +#include +#include + +#if defined CONFIG_DTT_SENSORS +static unsigned long sensor_initialized; + +static void _initialize_dtt(void) +{ + int i; + unsigned char sensors[] = CONFIG_DTT_SENSORS; + + for (i = 0; i < sizeof(sensors); i++) { + if ((sensor_initialized & (1 << i)) == 0) { + if (dtt_init_one(sensors[i]) != 0) { + printf("DTT%d: Failed init!\n", i); + continue; + } + sensor_initialized |= (1 << i); + } + } +} + +void dtt_init(void) +{ + int old_bus; + + /* switch to correct I2C bus */ + old_bus = I2C_GET_BUS(); + I2C_SET_BUS(CONFIG_SYS_DTT_BUS_NUM); + + _initialize_dtt(); + + /* switch back to original I2C bus */ + I2C_SET_BUS(old_bus); +} +#endif + +int dtt_i2c(void) +{ +#if defined CONFIG_DTT_SENSORS + int i; + unsigned char sensors[] = CONFIG_DTT_SENSORS; + int old_bus; + + /* Force a compilation error, if there are more then 32 sensors */ + BUILD_BUG_ON(sizeof(sensors) > 32); + /* switch to correct I2C bus */ +#ifdef CONFIG_SYS_I2C + old_bus = i2c_get_bus_num(); + i2c_set_bus_num(CONFIG_SYS_DTT_BUS_NUM); +#else + old_bus = I2C_GET_BUS(); + I2C_SET_BUS(CONFIG_SYS_DTT_BUS_NUM); +#endif + + _initialize_dtt(); + + /* + * Loop through sensors, read + * temperature, and output it. + */ + for (i = 0; i < sizeof(sensors); i++) + printf("DTT%d: %i C\n", i + 1, dtt_get_temp(sensors[i])); + + /* switch back to original I2C bus */ +#ifdef CONFIG_SYS_I2C + i2c_set_bus_num(old_bus); +#else + I2C_SET_BUS(old_bus); +#endif +#endif + + return 0; +} + +int dtt_tmu(void) +{ +#if defined CONFIG_TMU_CMD_DTT + int cur_temp; + + /* Sense and return latest thermal info */ + if (tmu_monitor(&cur_temp) == TMU_STATUS_INIT) { + puts("TMU is in unknown state, temperature is invalid\n"); + return -1; + } + printf("Current temperature: %u degrees Celsius\n", cur_temp); +#endif + return 0; +} + +int do_dtt(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int err = 0; + + err |= dtt_i2c(); + err |= dtt_tmu(); + + return err; +} /* do_dtt() */ + +/***************************************************/ + +U_BOOT_CMD( + dtt, 1, 1, do_dtt, + "Read temperature from Digital Thermometer and Thermostat", + "" +); diff --git a/cmd/echo.c b/cmd/echo.c new file mode 100644 index 0000000..3dc3a63 --- /dev/null +++ b/cmd/echo.c @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +static int do_echo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int i; + int putnl = 1; + + for (i = 1; i < argc; i++) { + char *p = argv[i]; + char *nls; /* new-line suppression */ + + if (i > 1) + putc(' '); + + nls = strstr(p, "\\c"); + if (nls) { + char *prenls = p; + + putnl = 0; + /* + * be paranoid and guess that someone might + * say \c more than once + */ + while (nls) { + *nls = '\0'; + puts(prenls); + *nls = '\\'; + prenls = nls + 2; + nls = strstr(prenls, "\\c"); + } + puts(prenls); + } else { + puts(p); + } + } + + if (putnl) + putc('\n'); + + return 0; +} + +U_BOOT_CMD( + echo, CONFIG_SYS_MAXARGS, 1, do_echo, + "echo args to console", + "[args..]\n" + " - echo args to console; \\c suppresses newline" +); diff --git a/cmd/eeprom.c b/cmd/eeprom.c new file mode 100644 index 0000000..571240a --- /dev/null +++ b/cmd/eeprom.c @@ -0,0 +1,265 @@ +/* + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * 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 +#include +#include +#include + +#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 + +#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 + +__weak int eeprom_write_enable(unsigned dev_addr, int state) +{ + return 0; +} + +void eeprom_init(int bus) +{ + /* SPI EEPROM */ +#if defined(CONFIG_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) + spi_init_f(); +#endif + + /* I2C EEPROM */ +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C_SOFT) +#if defined(CONFIG_SYS_I2C) + if (bus >= 0) + i2c_set_bus_num(bus); +#endif + 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 ccessed 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; + + /* SPI */ +#if defined(CONFIG_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C) + if (read) + spi_read(addr, alen, buffer, len); + else + spi_write(addr, alen, buffer, len); +#else /* I2C */ + +#if defined(CONFIG_SYS_I2C_EEPROM_BUS) + i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS); +#endif + + if (read) + ret = i2c_read(addr[0], offset, alen - 1, buffer, len); + else + ret = i2c_write(addr[0], offset, alen - 1, buffer, len); + + if (ret) + ret = 1; +#endif + 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]; + + 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 do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const char *const fmt = + "\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... "; + char * const *args = &argv[2]; + int rcode; + ulong dev_addr, addr, off, cnt; + int bus_addr; + + switch (argc) { +#ifdef CONFIG_SYS_DEF_EEPROM_ADDR + case 5: + bus_addr = -1; + dev_addr = CONFIG_SYS_DEF_EEPROM_ADDR; + break; +#endif + case 6: + bus_addr = -1; + dev_addr = simple_strtoul(*args++, NULL, 16); + break; + case 7: + bus_addr = simple_strtoul(*args++, NULL, 16); + dev_addr = simple_strtoul(*args++, NULL, 16); + break; + default: + return CMD_RET_USAGE; + } + + addr = simple_strtoul(*args++, NULL, 16); + off = simple_strtoul(*args++, NULL, 16); + cnt = simple_strtoul(*args++, NULL, 16); + + eeprom_init(bus_addr); + + if (strcmp(argv[1], "read") == 0) { + printf(fmt, dev_addr, argv[1], addr, off, cnt); + + rcode = eeprom_read(dev_addr, off, (uchar *)addr, cnt); + + puts("done\n"); + return rcode; + } else if (strcmp(argv[1], "write") == 0) { + printf(fmt, dev_addr, argv[1], addr, off, cnt); + + rcode = eeprom_write(dev_addr, off, (uchar *)addr, cnt); + + puts("done\n"); + return rcode; + } + + return CMD_RET_USAGE; +} + +U_BOOT_CMD( + eeprom, 7, 1, do_eeprom, + "EEPROM sub-system", + "read addr off cnt\n" + "eeprom write addr off cnt\n" + " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'" +) diff --git a/cmd/efi.c b/cmd/efi.c new file mode 100644 index 0000000..c76296e --- /dev/null +++ b/cmd/efi.c @@ -0,0 +1,257 @@ +/* + * (C) Copyright 2015 Google, Inc + * Written by Simon Glass + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +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 { + int shift; + const char *name; +} mem_attr[] = { + { EFI_MEMORY_UC_SHIFT, "uncached" }, + { EFI_MEMORY_WC_SHIFT, "write-coalescing" }, + { EFI_MEMORY_WT_SHIFT, "write-through" }, + { EFI_MEMORY_WB_SHIFT, "write-back" }, + { EFI_MEMORY_UCE_SHIFT, "uncached & exported" }, + { EFI_MEMORY_WP_SHIFT, "write-protect" }, + { EFI_MEMORY_RP_SHIFT, "read-protect" }, + { EFI_MEMORY_XP_SHIFT, "execute-protect" }, + { EFI_MEMORY_RUNTIME_SHIFT, "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; +} + +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 = base + count; + for (desc = base; desc < end; desc = efi_get_next_mem_desc(map, desc)) { + bool merge = true; + int type = desc->type; + + 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_TABLE_END; + + 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_TABLE_END; + 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", "", + addr, "", desc->physical_start - addr); + } + size = desc->num_pages << EFI_PAGE_SHIFT; + + name = desc->type < ARRAY_SIZE(type_name) ? + type_name[desc->type] : ""; + 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 & (1ULL << mem_attr[j].shift)) { + 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(cmd_tbl_t *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 cmd_tbl_t efi_commands[] = { + U_BOOT_CMD_MKENT(mem, 1, 1, do_efi_mem, "", ""), +}; + +static int do_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *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/cmd/elf.c b/cmd/elf.c new file mode 100644 index 0000000..5190cc6 --- /dev/null +++ b/cmd/elf.c @@ -0,0 +1,410 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#ifdef CONFIG_X86 +#include +#include +#endif + +/* + * A very simple elf loader, assumes the image is valid, returns the + * entry point address. + */ +static unsigned long load_elf_image_phdr(unsigned long addr) +{ + Elf32_Ehdr *ehdr; /* Elf header structure pointer */ + Elf32_Phdr *phdr; /* Program header structure pointer */ + int i; + + ehdr = (Elf32_Ehdr *)addr; + phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); + + /* Load each program header */ + for (i = 0; i < ehdr->e_phnum; ++i) { + void *dst = (void *)(uintptr_t)phdr->p_paddr; + void *src = (void *)addr + phdr->p_offset; + debug("Loading phdr %i to 0x%p (%i bytes)\n", + i, dst, phdr->p_filesz); + if (phdr->p_filesz) + memcpy(dst, src, phdr->p_filesz); + if (phdr->p_filesz != phdr->p_memsz) + memset(dst + phdr->p_filesz, 0x00, + phdr->p_memsz - phdr->p_filesz); + flush_cache((unsigned long)dst, phdr->p_filesz); + ++phdr; + } + + return ehdr->e_entry; +} + +static unsigned long load_elf_image_shdr(unsigned long addr) +{ + Elf32_Ehdr *ehdr; /* Elf header structure pointer */ + Elf32_Shdr *shdr; /* Section header structure pointer */ + unsigned char *strtab = 0; /* String table pointer */ + unsigned char *image; /* Binary image pointer */ + int i; /* Loop counter */ + + ehdr = (Elf32_Ehdr *)addr; + + /* Find the section header string table for output info */ + shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + + (ehdr->e_shstrndx * sizeof(Elf32_Shdr))); + + if (shdr->sh_type == SHT_STRTAB) + strtab = (unsigned char *)(addr + shdr->sh_offset); + + /* Load each appropriate section */ + for (i = 0; i < ehdr->e_shnum; ++i) { + shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + + (i * sizeof(Elf32_Shdr))); + + if (!(shdr->sh_flags & SHF_ALLOC) || + shdr->sh_addr == 0 || shdr->sh_size == 0) { + continue; + } + + if (strtab) { + debug("%sing %s @ 0x%08lx (%ld bytes)\n", + (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", + &strtab[shdr->sh_name], + (unsigned long)shdr->sh_addr, + (long)shdr->sh_size); + } + + if (shdr->sh_type == SHT_NOBITS) { + memset((void *)(uintptr_t)shdr->sh_addr, 0, + shdr->sh_size); + } else { + image = (unsigned char *)addr + shdr->sh_offset; + memcpy((void *)(uintptr_t)shdr->sh_addr, + (const void *)image, shdr->sh_size); + } + flush_cache(shdr->sh_addr, shdr->sh_size); + } + + return ehdr->e_entry; +} + +/* 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; + + /* + * QNX images require the data cache is disabled. + * Data cache is already flushed, so just turn it off. + */ + int dcache = dcache_status(); + if (dcache) + dcache_disable(); + + /* + * pass address parameter as argv[0] (aka command name), + * and all remaining args + */ + ret = entry(argc, argv); + + if (dcache) + dcache_enable(); + + return ret; +} + +/* + * Determine if a valid ELF image exists at the given memory location. + * First look at the ELF header magic field, then make sure that it is + * executable. + */ +int valid_elf_image(unsigned long addr) +{ + Elf32_Ehdr *ehdr; /* Elf header structure pointer */ + + ehdr = (Elf32_Ehdr *)addr; + + if (!IS_ELF(*ehdr)) { + printf("## No elf image at address 0x%08lx\n", addr); + return 0; + } + + if (ehdr->e_type != ET_EXEC) { + printf("## Not a 32-bit elf image at address 0x%08lx\n", addr); + return 0; + } + + return 1; +} + +/* Interpreter command to boot an arbitrary ELF image from memory */ +int do_bootelf(cmd_tbl_t *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, *saddr; + const char *ep = getenv("autostart"); + + int rcode = 0; + + sload = saddr = NULL; + if (argc == 3) { + sload = argv[1]; + saddr = argv[2]; + } else if (argc == 2) { + if (argv[1][0] == '-') + sload = argv[1]; + else + saddr = argv[1]; + } + + if (saddr) + addr = simple_strtoul(saddr, NULL, 16); + else + addr = 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 - 1, argv + 1); + 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned long addr; /* Address of image */ + unsigned long bootaddr; /* 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 + struct e820info *info; + struct e820entry *data; +#endif + + /* + * Check the loadaddr variable. + * If we don't know where the image is then we're done. + */ + if (argc < 2) + addr = 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_WALNUT) + tmp = (char *)CONFIG_SYS_NVRAM_BASE_ADDR + 0x500; + eth_getenv_enetaddr("ethaddr", (uchar *)build_buf); + memcpy(tmp, &build_buf[3], 3); +#elif defined(CONFIG_SYS_VXWORKS_MAC_PTR) + tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR; + eth_getenv_enetaddr("ethaddr", (uchar *)build_buf); + memcpy(tmp, build_buf, 6); +#else + puts("## Ethernet MAC address not copied to NV RAM\n"); +#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 = getenv("bootaddr"); + if (!tmp) { + printf("## VxWorks bootline address not specified\n"); + } else { + 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 = getenv("bootargs"); + if (bootline) { + memcpy((void *)bootaddr, bootline, + max(strlen(bootline), (size_t)255)); + flush_cache(bootaddr, max(strlen(bootline), + (size_t)255)); + } else { + tmp = getenv("bootdev"); + if (tmp) { + strcpy(build_buf, tmp); + ptr = strlen(tmp); + } else + printf("## VxWorks boot device not specified\n"); + + tmp = getenv("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 = getenv("ipaddr"); + if (tmp) { + ptr += sprintf(build_buf + ptr, "e=%s", tmp); + tmp = getenv("netmask"); + if (tmp) { + u32 mask = getenv_ip("netmask").s_addr; + ptr += sprintf(build_buf + ptr, + ":%08x ", ntohl(mask)); + } else { + ptr += sprintf(build_buf + ptr, " "); + } + } + + tmp = getenv("serverip"); + if (tmp) + ptr += sprintf(build_buf + ptr, "h=%s ", tmp); + + tmp = getenv("gatewayip"); + if (tmp) + ptr += sprintf(build_buf + ptr, "g=%s ", tmp); + + tmp = getenv("hostname"); + if (tmp) + ptr += sprintf(build_buf + ptr, "tn=%s ", tmp); + + tmp = getenv("othbootargs"); + if (tmp) { + strcpy(build_buf + ptr, tmp); + ptr += strlen(tmp); + } + + memcpy((void *)bootaddr, build_buf, + max(strlen(build_buf), (size_t)255)); + flush_cache(bootaddr, max(strlen(build_buf), + (size_t)255)); + } + + printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, + (char *)bootaddr); + } + +#ifdef CONFIG_X86 + /* + * Since E820 information is critical to the kernel, if we don't + * specify these in the environments, use a default one. + */ + tmp = getenv("e820data"); + if (tmp) + data = (struct e820entry *)simple_strtoul(tmp, NULL, 16); + else + data = (struct e820entry *)VXWORKS_E820_DATA_ADDR; + tmp = getenv("e820info"); + if (tmp) + info = (struct e820info *)simple_strtoul(tmp, NULL, 16); + else + info = (struct e820info *)VXWORKS_E820_INFO_ADDR; + + memset(info, 0, sizeof(struct e820info)); + info->sign = E820_SIGNATURE; + info->entries = install_e820_map(E820MAX, data); + info->addr = (info->entries - 1) * sizeof(struct e820entry) + + VXWORKS_E820_DATA_ADDR; +#endif + + /* + * 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_shdr(addr); + else + puts("## Not an ELF image, assuming binary\n"); + + printf("## Starting vxWorks at 0x%08lx ...\n", addr); + + dcache_disable(); +#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, 3, 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/cmd/ethsw.c b/cmd/ethsw.c new file mode 100644 index 0000000..8e452e9 --- /dev/null +++ b/cmd/ethsw.c @@ -0,0 +1,1027 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Ethernet Switch commands + */ + +#include +#include +#include +#include +#include + +static const char *ethsw_name; + +#define ETHSW_PORT_STATS_HELP "ethsw [port ] 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 ] 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 ] [vlan ] fdb " \ +"{ [help] | show | flush | { add | del } } " \ +"- Add/delete a mac entry in FDB; use show to see FDB entries; " \ +"if vlan 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 ] " \ +"pvid { [help] | show | } " \ +"- 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 ] vlan " \ +"{ [help] | show | add | del } " \ +"- 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 ] untagged " \ +"{ [help] | show | all | none | pvid } " \ +" - set egress tagging mod 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 ] 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 ] 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; +} + +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 = ðsw_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 = ðsw_learn_help_key_func, + }, { + .cmd_keyword = { + ethsw_id_learning, + ethsw_id_help, + ethsw_id_key_end, + }, + .cmd_func_offset = -1, + .keyword_function = ðsw_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 = ðsw_fdb_help_key_func, + }, { + .cmd_keyword = { + ethsw_id_fdb, + ethsw_id_help, + ethsw_id_key_end, + }, + .cmd_func_offset = -1, + .keyword_function = ðsw_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 = ðsw_pvid_help_key_func, + }, { + .cmd_keyword = { + ethsw_id_pvid, + ethsw_id_help, + ethsw_id_key_end, + }, + .cmd_func_offset = -1, + .keyword_function = ðsw_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 = ðsw_vlan_help_key_func, + }, { + .cmd_keyword = { + ethsw_id_vlan, + ethsw_id_help, + ethsw_id_key_end, + }, + .cmd_func_offset = -1, + .keyword_function = ðsw_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 = ðsw_port_untag_help_key_func, + }, { + .cmd_keyword = { + ethsw_id_untagged, + ethsw_id_help, + ethsw_id_key_end, + }, + .cmd_func_offset = -1, + .keyword_function = ðsw_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 = ðsw_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 = ðsw_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 = ðsw_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 = ðsw_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 = ðsw_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 = ðsw_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, + }, +}; + +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); + +/* + * 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, + }, +}; + +/* + * 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; + } + + eth_parse_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; +} + +/* 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(ethsw_cmd_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 = ðsw_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->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(cmd_tbl_t *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 ] { enable | disable | show } " \ +"- enable/disable a port; show shows 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" +); diff --git a/cmd/exit.c b/cmd/exit.c new file mode 100644 index 0000000..c789233 --- /dev/null +++ b/cmd/exit.c @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +static int do_exit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int r; + + r = 0; + if (argc > 1) + r = simple_strtoul(argv[1], NULL, 10); + + return -r - 2; +} + +U_BOOT_CMD( + exit, 2, 1, do_exit, + "exit script", + "" +); diff --git a/cmd/ext2.c b/cmd/ext2.c new file mode 100644 index 0000000..6657ef5 --- /dev/null +++ b/cmd/ext2.c @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar + * Manjunatha C Achar + + * (C) Copyright 2004 + * esd gmbh + * Reinhard Arlt + * + * made from cmd_reiserfs by + * + * (C) Copyright 2003 - 2004 + * Sysgo Real-Time Solutions, AG + * Pavel Bartusek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Ext2fs support + */ +#include + +static int do_ext2ls(cmd_tbl_t *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(cmd_tbl_t *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 /)", + " [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", + " [ [addr [filename [bytes [pos]]]]]\n" + " - load binary file 'filename' from 'dev' on 'interface'\n" + " to address 'addr' from ext2 filesystem." +) diff --git a/cmd/ext4.c b/cmd/ext4.c new file mode 100644 index 0000000..19423d1 --- /dev/null +++ b/cmd/ext4.c @@ -0,0 +1,94 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar + * Manjunatha C Achar + * + * Ext4fs support + * made from existing cmd_ext2.c file of Uboot + * + * (C) Copyright 2004 + * esd gmbh + * Reinhard Arlt + * + * made from cmd_reiserfs by + * + * (C) Copyright 2003 - 2004 + * Sysgo Real-Time Solutions, AG + * Pavel Bartusek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) +#include +#endif + +int do_ext4_size(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + return do_size(cmdtp, flag, argc, argv, FS_TYPE_EXT); +} + +int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + return do_load(cmdtp, flag, argc, argv, FS_TYPE_EXT); +} + +int do_ext4_ls(cmd_tbl_t *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(cmd_tbl_t *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", + " \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", + " \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 /)", + " [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", + " [ [addr [filename [bytes [pos]]]]]\n" + " - load binary file 'filename' from 'dev' on 'interface'\n" + " to address 'addr' from ext4 filesystem"); diff --git a/cmd/fastboot.c b/cmd/fastboot.c new file mode 100644 index 0000000..488822a --- /dev/null +++ b/cmd/fastboot.c @@ -0,0 +1,69 @@ +/* + * Copyright 2008 - 2009 Windriver, + * Author: Tom Rix + * + * (C) Copyright 2014 Linaro, Ltd. + * Rob Herring + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include + +static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int controller_index; + char *usb_controller; + int ret; + + if (argc < 2) + return CMD_RET_USAGE; + + usb_controller = argv[1]; + controller_index = simple_strtoul(usb_controller, NULL, 0); + + ret = board_usb_init(controller_index, USB_INIT_DEVICE); + if (ret) { + error("USB init failed: %d", 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; + usb_gadget_handle_interrupts(controller_index); + } + + ret = CMD_RET_SUCCESS; + +exit: + g_dnl_unregister(); + g_dnl_clear_detach(); + board_usb_cleanup(controller_index, USB_INIT_DEVICE); + + return ret; +} + +U_BOOT_CMD( + fastboot, 2, 1, do_fastboot, + "use USB Fastboot protocol", + "\n" + " - run as a fastboot usb device" +); diff --git a/cmd/fat.c b/cmd/fat.c new file mode 100644 index 0000000..aae993d --- /dev/null +++ b/cmd/fat.c @@ -0,0 +1,152 @@ +/* + * (C) Copyright 2002 + * Richard Jones, rjones@nexus-tech.net + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Boot support + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int do_fat_size(cmd_tbl_t *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", + " \n" + " - Find file 'filename' from 'dev' on 'interface'\n" + " and determine its size." +); + +int do_fat_fsload (cmd_tbl_t *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", + " [ [ [ [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(cmd_tbl_t *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 /)", + " [] [directory]\n" + " - list files from 'dev' on 'interface' in a 'directory'" +); + +static int do_fat_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int dev, part; + block_dev_desc_t *dev_desc; + disk_partition_t info; + + if (argc < 2) { + printf("usage: fatinfo []\n"); + return 0; + } + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) + return 1; + + dev = dev_desc->dev; + 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", + " []\n" + " - print information about filesystem from 'dev' on 'interface'" +); + +#ifdef CONFIG_FAT_WRITE +static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + loff_t size; + int ret; + unsigned long addr; + unsigned long count; + block_dev_desc_t *dev_desc = NULL; + disk_partition_t info; + int dev = 0; + int part = 1; + void *buf; + + if (argc < 5) + return cmd_usage(cmdtp); + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) + return 1; + + dev = dev_desc->dev; + + if (fat_set_blk_dev(dev_desc, &info) != 0) { + printf("\n** Unable to use %s %d:%d for fatwrite **\n", + argv[1], dev, part); + return 1; + } + addr = simple_strtoul(argv[3], NULL, 16); + count = simple_strtoul(argv[5], NULL, 16); + + buf = map_sysmem(addr, count); + ret = file_fat_write(argv[4], buf, 0, count, &size); + unmap_sysmem(buf); + if (ret < 0) { + printf("\n** Unable to write \"%s\" from %s %d:%d **\n", + argv[4], argv[1], dev, part); + return 1; + } + + printf("%llu bytes written\n", size); + + return 0; +} + +U_BOOT_CMD( + fatwrite, 6, 0, do_fat_fswrite, + "write file into a dos filesystem", + " \n" + " - write file 'filename' from the address 'addr' in RAM\n" + " to 'dev' on 'interface'" +); +#endif diff --git a/cmd/fdc.c b/cmd/fdc.c new file mode 100644 index 0000000..5766b56 --- /dev/null +++ b/cmd/fdc.c @@ -0,0 +1,752 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG, d.peter@mpl.ch. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +/* + * Floppy Disk support + */ + +#include +#include +#include +#include + + +#undef FDC_DEBUG + +#ifdef FDC_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/*#if defined(CONFIG_CMD_DATE) */ +/*#include */ +/*#endif */ + +typedef struct { + int flags; /* connected drives ect */ + unsigned long blnr; /* Logical block nr */ + uchar drive; /* drive no */ + uchar cmdlen; /* cmd length */ + uchar cmd[16]; /* cmd desc */ + uchar dma; /* if > 0 dma enabled */ + uchar result[11]; /* status information */ + uchar resultlen; /* lenght of result */ +} FDC_COMMAND_STRUCT; + +/* flags: only the lower 8bit used: + * bit 0 if set drive 0 is present + * bit 1 if set drive 1 is present + * bit 2 if set drive 2 is present + * bit 3 if set drive 3 is present + * bit 4 if set disk in drive 0 is inserted + * bit 5 if set disk in drive 1 is inserted + * bit 6 if set disk in drive 2 is inserted + * bit 7 if set disk in drive 4 is inserted + */ + +/* cmd indexes */ +#define COMMAND 0 +#define DRIVE 1 +#define CONFIG0 1 +#define SPEC_HUTSRT 1 +#define TRACK 2 +#define CONFIG1 2 +#define SPEC_HLT 2 +#define HEAD 3 +#define CONFIG2 3 +#define SECTOR 4 +#define SECTOR_SIZE 5 +#define LAST_TRACK 6 +#define GAP 7 +#define DTL 8 +/* result indexes */ +#define STATUS_0 0 +#define STATUS_PCN 1 +#define STATUS_1 1 +#define STATUS_2 2 +#define STATUS_TRACK 3 +#define STATUS_HEAD 4 +#define STATUS_SECT 5 +#define STATUS_SECT_SIZE 6 + + +/* Register addresses */ +#define FDC_BASE 0x3F0 +#define FDC_SRA FDC_BASE + 0 /* Status Register A */ +#define FDC_SRB FDC_BASE + 1 /* Status Register B */ +#define FDC_DOR FDC_BASE + 2 /* Digital Output Register */ +#define FDC_TDR FDC_BASE + 3 /* Tape Drive Register */ +#define FDC_DSR FDC_BASE + 4 /* Data rate Register */ +#define FDC_MSR FDC_BASE + 4 /* Main Status Register */ +#define FDC_FIFO FDC_BASE + 5 /* FIFO */ +#define FDC_DIR FDC_BASE + 6 /* Digital Input Register */ +#define FDC_CCR FDC_BASE + 7 /* Configuration Control */ +/* Commands */ +#define FDC_CMD_SENSE_INT 0x08 +#define FDC_CMD_CONFIGURE 0x13 +#define FDC_CMD_SPECIFY 0x03 +#define FDC_CMD_RECALIBRATE 0x07 +#define FDC_CMD_READ 0x06 +#define FDC_CMD_READ_TRACK 0x02 +#define FDC_CMD_READ_ID 0x0A +#define FDC_CMD_DUMP_REG 0x0E +#define FDC_CMD_SEEK 0x0F + +#define FDC_CMD_SENSE_INT_LEN 0x01 +#define FDC_CMD_CONFIGURE_LEN 0x04 +#define FDC_CMD_SPECIFY_LEN 0x03 +#define FDC_CMD_RECALIBRATE_LEN 0x02 +#define FDC_CMD_READ_LEN 0x09 +#define FDC_CMD_READ_TRACK_LEN 0x09 +#define FDC_CMD_READ_ID_LEN 0x02 +#define FDC_CMD_DUMP_REG_LEN 0x01 +#define FDC_CMD_SEEK_LEN 0x03 + +#define FDC_FIFO_THR 0x0C +#define FDC_FIFO_DIS 0x00 +#define FDC_IMPLIED_SEEK 0x01 +#define FDC_POLL_DIS 0x00 +#define FDC_PRE_TRK 0x00 +#define FDC_CONFIGURE FDC_FIFO_THR | (FDC_POLL_DIS<<4) | (FDC_FIFO_DIS<<5) | (FDC_IMPLIED_SEEK << 6) +#define FDC_MFM_MODE 0x01 /* MFM enable */ +#define FDC_SKIP_MODE 0x00 /* skip enable */ + +#define FDC_TIME_OUT 100000 /* time out */ +#define FDC_RW_RETRIES 3 /* read write retries */ +#define FDC_CAL_RETRIES 3 /* calibration and seek retries */ + + +/* Disk structure */ +typedef struct { + unsigned int size; /* nr of sectors total */ + unsigned int sect; /* sectors per track */ + unsigned int head; /* nr of heads */ + unsigned int track; /* nr of tracks */ + unsigned int stretch; /* !=0 means double track steps */ + unsigned char gap; /* gap1 size */ + unsigned char rate; /* data rate. |= 0x40 for perpendicular */ + unsigned char spec1; /* stepping rate, head unload time */ + unsigned char fmt_gap;/* gap2 size */ + unsigned char hlt; /* head load time */ + unsigned char sect_code;/* Sector Size code */ + const char * name; /* used only for predefined formats */ +} FD_GEO_STRUCT; + + +/* supported Floppy types (currently only one) */ +const static FD_GEO_STRUCT floppy_type[2] = { + { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,16,2,"H1440" }, /* 7 1.44MB 3.5" */ + { 0, 0,0, 0,0,0x00,0x00,0x00,0x00, 0,0,NULL }, /* end of table */ +}; + +static FDC_COMMAND_STRUCT cmd; /* global command struct */ + +/* If the boot drive number is undefined, we assume it's drive 0 */ +#ifndef CONFIG_SYS_FDC_DRIVE_NUMBER +#define CONFIG_SYS_FDC_DRIVE_NUMBER 0 +#endif + +/* Hardware access */ +#ifndef CONFIG_SYS_ISA_IO_STRIDE +#define CONFIG_SYS_ISA_IO_STRIDE 1 +#endif + +#ifndef CONFIG_SYS_ISA_IO_OFFSET +#define CONFIG_SYS_ISA_IO_OFFSET 0 +#endif + +/* Supporting Functions */ +/* reads a Register of the FDC */ +unsigned char read_fdc_reg(unsigned int addr) +{ + volatile unsigned char *val = + (volatile unsigned char *)(CONFIG_SYS_ISA_IO_BASE_ADDRESS + + (addr * CONFIG_SYS_ISA_IO_STRIDE) + + CONFIG_SYS_ISA_IO_OFFSET); + + return val [0]; +} + +/* writes a Register of the FDC */ +void write_fdc_reg(unsigned int addr, unsigned char val) +{ + volatile unsigned char *tmp = + (volatile unsigned char *)(CONFIG_SYS_ISA_IO_BASE_ADDRESS + + (addr * CONFIG_SYS_ISA_IO_STRIDE) + + CONFIG_SYS_ISA_IO_OFFSET); + tmp[0]=val; +} + +/* waits for an interrupt (polling) */ +int wait_for_fdc_int(void) +{ + unsigned long timeout; + timeout = FDC_TIME_OUT; + while((read_fdc_reg(FDC_SRA)&0x80)==0) { + timeout--; + udelay(10); + if(timeout==0) /* timeout occured */ + return false; + } + return true; +} + +/* reads a byte from the FIFO of the FDC and checks direction and RQM bit + of the MSR. returns -1 if timeout, or byte if ok */ +int read_fdc_byte(void) +{ + unsigned long timeout; + timeout = FDC_TIME_OUT; + while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) { + /* direction out and ready */ + udelay(10); + timeout--; + if(timeout==0) /* timeout occured */ + return -1; + } + return read_fdc_reg(FDC_FIFO); +} + +/* if the direction of the FIFO is wrong, this routine is used to + empty the FIFO. Should _not_ be used */ +int fdc_need_more_output(void) +{ + unsigned char c; + while((read_fdc_reg(FDC_MSR)&0xC0)==0xC0) { + c=(unsigned char)read_fdc_byte(); + printf("Error: more output: %x\n",c); + } + return true; +} + + +/* writes a byte to the FIFO of the FDC and checks direction and RQM bit + of the MSR */ +int write_fdc_byte(unsigned char val) +{ + unsigned long timeout; + timeout = FDC_TIME_OUT; + while((read_fdc_reg(FDC_MSR)&0xC0)!=0x80) { + /* direction in and ready for byte */ + timeout--; + udelay(10); + fdc_need_more_output(); + if(timeout==0) /* timeout occured */ + return false; + } + write_fdc_reg(FDC_FIFO,val); + return true; +} + +/* sets up all FDC commands and issues it to the FDC. If + the command causes direct results (no Execution Phase) + the result is be read as well. */ + +int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG) +{ + int i; + unsigned long head,track,sect,timeout; + track = pCMD->blnr / (pFG->sect * pFG->head); /* track nr */ + sect = pCMD->blnr % (pFG->sect * pFG->head); /* remaining blocks */ + head = sect / pFG->sect; /* head nr */ + sect = sect % pFG->sect; /* remaining blocks */ + sect++; /* sectors are 1 based */ + PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n", + pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr); + + if(head|=0) { /* max heads = 2 */ + pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */ + pCMD->cmd[HEAD]=(unsigned char) head; /* head register */ + } + else { + pCMD->cmd[DRIVE]=pCMD->drive; /* head 0 */ + pCMD->cmd[HEAD]=(unsigned char) head; /* head register */ + } + pCMD->cmd[TRACK]=(unsigned char) track; /* track */ + switch (pCMD->cmd[COMMAND]) { + case FDC_CMD_READ: + pCMD->cmd[SECTOR]=(unsigned char) sect; /* sector */ + pCMD->cmd[SECTOR_SIZE]=pFG->sect_code; /* sector size code */ + pCMD->cmd[LAST_TRACK]=pFG->sect; /* End of track */ + pCMD->cmd[GAP]=pFG->gap; /* gap */ + pCMD->cmd[DTL]=0xFF; /* DTL */ + pCMD->cmdlen=FDC_CMD_READ_LEN; + pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */ + pCMD->cmd[COMMAND]|=(FDC_SKIP_MODE<<5); /* set Skip bit */ + pCMD->resultlen=0; /* result only after execution */ + break; + case FDC_CMD_SEEK: + pCMD->cmdlen=FDC_CMD_SEEK_LEN; + pCMD->resultlen=0; /* no result */ + break; + case FDC_CMD_CONFIGURE: + pCMD->cmd[CONFIG0]=0; + pCMD->cmd[CONFIG1]=FDC_CONFIGURE; /* FIFO Threshold, Poll, Enable FIFO */ + pCMD->cmd[CONFIG2]=FDC_PRE_TRK; /* Precompensation Track */ + pCMD->cmdlen=FDC_CMD_CONFIGURE_LEN; + pCMD->resultlen=0; /* no result */ + break; + case FDC_CMD_SPECIFY: + pCMD->cmd[SPEC_HUTSRT]=pFG->spec1; + pCMD->cmd[SPEC_HLT]=(pFG->hlt)<<1; /* head load time */ + if(pCMD->dma==0) + pCMD->cmd[SPEC_HLT]|=0x1; /* no dma */ + pCMD->cmdlen=FDC_CMD_SPECIFY_LEN; + pCMD->resultlen=0; /* no result */ + break; + case FDC_CMD_DUMP_REG: + pCMD->cmdlen=FDC_CMD_DUMP_REG_LEN; + pCMD->resultlen=10; /* 10 byte result */ + break; + case FDC_CMD_READ_ID: + pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */ + pCMD->cmdlen=FDC_CMD_READ_ID_LEN; + pCMD->resultlen=7; /* 7 byte result */ + break; + case FDC_CMD_RECALIBRATE: + pCMD->cmd[DRIVE]&=0x03; /* don't set the head bit */ + pCMD->cmdlen=FDC_CMD_RECALIBRATE_LEN; + pCMD->resultlen=0; /* no result */ + break; + break; + case FDC_CMD_SENSE_INT: + pCMD->cmdlen=FDC_CMD_SENSE_INT_LEN; + pCMD->resultlen=2; + break; + } + for(i=0;icmdlen;i++) { + /* PRINTF("write cmd%d = 0x%02X\n",i,pCMD->cmd[i]); */ + if (write_fdc_byte(pCMD->cmd[i]) == false) { + PRINTF("Error: timeout while issue cmd%d\n",i); + return false; + } + } + timeout=FDC_TIME_OUT; + for(i=0;iresultlen;i++) { + while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) { + timeout--; + if(timeout==0) { + PRINTF(" timeout while reading result%d MSR=0x%02X\n",i,read_fdc_reg(FDC_MSR)); + return false; + } + } + pCMD->result[i]=(unsigned char)read_fdc_byte(); + } + return true; +} + +/* selects the drive assigned in the cmd structur and + switches on the Motor */ +void select_fdc_drive(FDC_COMMAND_STRUCT *pCMD) +{ + unsigned char val; + + val=(1<<(4+pCMD->drive))|pCMD->drive|0xC; /* set reset, dma gate and motor bits */ + if((read_fdc_reg(FDC_DOR)&val)!=val) { + write_fdc_reg(FDC_DOR,val); + for(val=0;val<255;val++) + udelay(500); /* wait some time to start motor */ + } +} + +/* switches off the Motor of the specified drive */ +void stop_fdc_drive(FDC_COMMAND_STRUCT *pCMD) +{ + unsigned char val; + + val=(1<<(4+pCMD->drive))|pCMD->drive; /* sets motor bits */ + write_fdc_reg(FDC_DOR,(read_fdc_reg(FDC_DOR)&~val)); +} + +/* issues a recalibrate command, waits for interrupt and + * issues a sense_interrupt */ +int fdc_recalibrate(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG) +{ + pCMD->cmd[COMMAND]=FDC_CMD_RECALIBRATE; + if (fdc_issue_cmd(pCMD, pFG) == false) + return false; + while (wait_for_fdc_int() != true); + + pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT; + return(fdc_issue_cmd(pCMD,pFG)); +} + +/* issues a recalibrate command, waits for interrupt and + * issues a sense_interrupt */ +int fdc_seek(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG) +{ + pCMD->cmd[COMMAND]=FDC_CMD_SEEK; + if (fdc_issue_cmd(pCMD, pFG) == false) + return false; + while (wait_for_fdc_int() != true); + + pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT; + return(fdc_issue_cmd(pCMD,pFG)); +} + +/* terminates current command, by not servicing the FIFO + * waits for interrupt and fills in the result bytes */ +int fdc_terminate(FDC_COMMAND_STRUCT *pCMD) +{ + int i; + for(i=0;i<100;i++) + udelay(500); /* wait 500usec for fifo overrun */ + while((read_fdc_reg(FDC_SRA)&0x80)==0x00); /* wait as long as no int has occured */ + for(i=0;i<7;i++) { + pCMD->result[i]=(unsigned char)read_fdc_byte(); + } + return true; +} + +/* reads data from FDC, seek commands are issued automatic */ +int fdc_read_data(unsigned char *buffer, unsigned long blocks,FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG) +{ + /* first seek to start address */ + unsigned long len,readblk,i,timeout,ii,offset; + unsigned char c,retriesrw,retriescal; + unsigned char *bufferw; /* working buffer */ + int sect_size; + int flags; + + flags=disable_interrupts(); /* switch off all Interrupts */ + select_fdc_drive(pCMD); /* switch on drive */ + sect_size=0x080<sect_code; + retriesrw=0; + retriescal=0; + offset=0; + if (fdc_seek(pCMD, pFG) == false) { + stop_fdc_drive(pCMD); + if (flags) + enable_interrupts(); + return false; + } + if((pCMD->result[STATUS_0]&0x20)!=0x20) { + printf("Seek error Status: %02X\n",pCMD->result[STATUS_0]); + stop_fdc_drive(pCMD); + if (flags) + enable_interrupts(); + return false; + } + /* now determine the next seek point */ + /* lastblk=pCMD->blnr + blocks; */ + /* readblk=(pFG->head*pFG->sect)-(pCMD->blnr%(pFG->head*pFG->sect)); */ + readblk=pFG->sect-(pCMD->blnr%pFG->sect); + PRINTF("1st nr of block possible read %ld start %ld\n",readblk,pCMD->blnr); + if(readblk>blocks) /* is end within 1st track */ + readblk=blocks; /* yes, correct it */ + PRINTF("we read %ld blocks start %ld\n",readblk,pCMD->blnr); + bufferw = &buffer[0]; /* setup working buffer */ + do { +retryrw: + len=sect_size * readblk; + pCMD->cmd[COMMAND]=FDC_CMD_READ; + if (fdc_issue_cmd(pCMD, pFG) == false) { + stop_fdc_drive(pCMD); + if (flags) + enable_interrupts(); + return false; + } + for (i=0;i6) { + for(ii=0;ii<7;ii++) { + pCMD->result[ii]=bufferw[(i-7+ii)]; + } /* for */ + } + if(retriesrw++>FDC_RW_RETRIES) { + if (retriescal++>FDC_CAL_RETRIES) { + stop_fdc_drive(pCMD); + if (flags) + enable_interrupts(); + return false; + } + else { + PRINTF(" trying to recalibrate Try %d\n",retriescal); + if (fdc_recalibrate(pCMD, pFG) == false) { + stop_fdc_drive(pCMD); + if (flags) + enable_interrupts(); + return false; + } + retriesrw=0; + goto retrycal; + } /* else >FDC_CAL_RETRIES */ + } + else { + PRINTF("Read retry %d\n",retriesrw); + goto retryrw; + } /* else >FDC_RW_RETRIES */ + }/* if output */ + timeout--; + } while (true); + } /* for len */ + /* the last sector of a track or all data has been read, + * we need to get the results */ + fdc_terminate(pCMD); + offset+=(sect_size*readblk); /* set up buffer pointer */ + bufferw = &buffer[offset]; + pCMD->blnr+=readblk; /* update current block nr */ + blocks-=readblk; /* update blocks */ + if(blocks==0) + break; /* we are finish */ + /* setup new read blocks */ + /* readblk=pFG->head*pFG->sect; */ + readblk=pFG->sect; + if(readblk>blocks) + readblk=blocks; +retrycal: + /* a seek is necessary */ + if (fdc_seek(pCMD, pFG) == false) { + stop_fdc_drive(pCMD); + if (flags) + enable_interrupts(); + return false; + } + if((pCMD->result[STATUS_0]&0x20)!=0x20) { + PRINTF("Seek error Status: %02X\n",pCMD->result[STATUS_0]); + stop_fdc_drive(pCMD); + return false; + } + } while (true); /* start over */ + stop_fdc_drive(pCMD); /* switch off drive */ + if (flags) + enable_interrupts(); + return true; +} + +/* Scan all drives and check if drive is present and disk is inserted */ +int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG) +{ + int i,drives,state; + /* OK procedure of data book is satisfied. + * trying to get some information over the drives */ + state=0; /* no drives, no disks */ + for(drives=0;drives<4;drives++) { + pCMD->drive=drives; + select_fdc_drive(pCMD); + pCMD->blnr=0; /* set to the 1st block */ + if (fdc_recalibrate(pCMD, pFG) == false) + continue; + if((pCMD->result[STATUS_0]&0x10)==0x10) + continue; + /* ok drive connected check for disk */ + state|=(1<blnr=pFG->size; /* set to the last block */ + if (fdc_seek(pCMD, pFG) == false) + continue; + pCMD->blnr=0; /* set to the 1st block */ + if (fdc_recalibrate(pCMD, pFG) == false) + continue; + pCMD->cmd[COMMAND]=FDC_CMD_READ_ID; + if (fdc_issue_cmd(pCMD, pFG) == false) + continue; + state|=(0x10<name : ""); + } + pCMD->flags=state; + return true; +} + + +/************************************************************************** +* int fdc_setup +* setup the fdc according the datasheet +* assuming in PS2 Mode +*/ +int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG) +{ + int i; + +#ifdef CONFIG_SYS_FDC_HW_INIT + fdc_hw_init (); +#endif + /* first, we reset the FDC via the DOR */ + write_fdc_reg(FDC_DOR,0x00); + for(i=0; i<255; i++) /* then we wait some time */ + udelay(500); + /* then, we clear the reset in the DOR */ + pCMD->drive=drive; + select_fdc_drive(pCMD); + /* initialize the CCR */ + write_fdc_reg(FDC_CCR,pFG->rate); + /* then initialize the DSR */ + write_fdc_reg(FDC_DSR,pFG->rate); + if (wait_for_fdc_int() == false) { + PRINTF("Time Out after writing CCR\n"); + return false; + } + /* now issue sense Interrupt and status command + * assuming only one drive present (drive 0) */ + pCMD->dma=0; /* we don't use any dma at all */ + for(i=0;i<4;i++) { + /* issue sense interrupt for all 4 possible drives */ + pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT; + if (fdc_issue_cmd(pCMD, pFG) == false) { + PRINTF("Sense Interrupt for drive %d failed\n",i); + } + } + /* issue the configure command */ + pCMD->drive=drive; + select_fdc_drive(pCMD); + pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE; + if (fdc_issue_cmd(pCMD, pFG) == false) { + PRINTF(" configure timeout\n"); + stop_fdc_drive(pCMD); + return false; + } + /* issue specify command */ + pCMD->cmd[COMMAND]=FDC_CMD_SPECIFY; + if (fdc_issue_cmd(pCMD, pFG) == false) { + PRINTF(" specify timeout\n"); + stop_fdc_drive(pCMD); + return false; + + } + /* then, we clear the reset in the DOR */ + /* fdc_check_drive(pCMD,pFG); */ + /* write_fdc_reg(FDC_DOR,0x04); */ + + return true; +} + +/**************************************************************************** + * main routine do_fdcboot + */ +int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type; + FDC_COMMAND_STRUCT *pCMD = &cmd; + unsigned long addr,imsize; +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + image_header_t *hdr; /* used for fdc boot */ +#endif + unsigned char boot_drive; + int i,nrofblk; +#if defined(CONFIG_FIT) + const void *fit_hdr = NULL; +#endif + + switch (argc) { + case 1: + addr = CONFIG_SYS_LOAD_ADDR; + boot_drive=CONFIG_SYS_FDC_DRIVE_NUMBER; + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + boot_drive=CONFIG_SYS_FDC_DRIVE_NUMBER; + break; + case 3: + addr = simple_strtoul(argv[1], NULL, 16); + boot_drive=simple_strtoul(argv[2], NULL, 10); + break; + default: + return CMD_RET_USAGE; + } + /* setup FDC and scan for drives */ + if (fdc_setup(boot_drive, pCMD, pFG) == false) { + printf("\n** Error in setup FDC **\n"); + return 1; + } + if (fdc_check_drive(pCMD, pFG) == false) { + printf("\n** Error in check_drives **\n"); + return 1; + } + if((pCMD->flags&(1<flags&(0x10<drive=boot_drive; + /* read first block */ + pCMD->blnr=0; + if (fdc_read_data((unsigned char *)addr, 1, pCMD, pFG) == false) { + printf("\nRead error:"); + for(i=0;i<7;i++) + printf("result%d: 0x%02X\n",i,pCMD->result[i]); + return 1; + } + + switch (genimg_get_format ((void *)addr)) { +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; + image_print_contents (hdr); + + imsize = 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"); + + imsize = fit_get_size (fit_hdr); + break; +#endif + default: + puts ("** Unknown image type\n"); + return 1; + } + + nrofblk=imsize/512; + if((imsize%512)>0) + nrofblk++; + printf("Loading %ld Bytes (%d blocks) at 0x%08lx..\n",imsize,nrofblk,addr); + pCMD->blnr=0; + if (fdc_read_data((unsigned char *)addr, nrofblk, pCMD, pFG) == false) { + /* read image block */ + printf("\nRead error:"); + for(i=0;i<7;i++) + printf("result%d: 0x%02X\n",i,pCMD->result[i]); + return 1; + } + printf("OK %ld Bytes loaded.\n",imsize); + + flush_cache (addr, imsize); + +#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)) { + puts ("** Bad FIT image format\n"); + return 1; + } + fit_print_contents (fit_hdr); + } +#endif + + /* Loading ok, update default load address */ + load_addr = addr; + + return bootm_maybe_autostart(cmdtp, argv[0]); +} + +U_BOOT_CMD( + fdcboot, 3, 1, do_fdcboot, + "boot from floppy device", + "loadAddr drive" +); diff --git a/cmd/fdt.c b/cmd/fdt.c new file mode 100644 index 0000000..4c18962 --- /dev/null +++ b/cmd/fdt.c @@ -0,0 +1,1065 @@ +/* + * (C) Copyright 2007 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com + * Based on code written by: + * Pantelis Antoniou and + * Matthew McClintock + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_LEVEL 32 /* how deeply nested we will go */ +#define SCRATCHPAD 1024 /* bytes of scratchpad memory */ +#ifndef CONFIG_CMD_FDT_MAX_DUMP +#define CONFIG_CMD_FDT_MAX_DUMP 64 +#endif + +/* + * Global data (for the gd->bd) + */ +DECLARE_GLOBAL_DATA_PTR; + +static int fdt_valid(struct fdt_header **blobp); +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; + setenv_hex("fdtaddr", addr); +} + +/* + * Get a value from the fdt and format it to be set in the environment + */ +static int fdt_value_setenv(const void *nodep, int len, const char *var) +{ + if (is_printable_string(nodep, len)) + setenv(var, (void *)nodep); + else if (len == 4) { + char buf[11]; + + sprintf(buf, "0x%08X", *(uint32_t *)nodep); + setenv(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)); + setenv(var, buf); + } else { + printf("error: unprintable value\n"); + return 1; + } + return 0; +} + +/* + * Flattened Device Tree command, see the help for parameter definitions. + */ +static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc < 2) + return CMD_RET_USAGE; + + /* + * Set the address of the fdt + */ + if (argv[1][0] == 'a') { + 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) : + getenv_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
\" 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; + } + working_fdt = newaddr; + + /* + * 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 (argv[1][0] == 's') { + char *pathp; /* path */ + char *prop; /* property */ + int nodeoffset; /* node offset from libfdt */ + static char data[SCRATCHPAD]; /* storage for the property */ + 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]; + if (argc == 4) { + len = 0; + } else { + ret = fdt_parse_prop(&argv[4], argc - 4, data, &len); + if (ret != 0) + return ret; + } + + 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; + } + + 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 *nodeName = fdt_get_name( + working_fdt, nextNodeOffset, NULL); + + setenv(var, (char *)nodeName); + 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 */ + setenv_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 */ + setenv(var, ""); + return 0; + } else if (len > 0) { + if (subcmd[0] == 'v') { + int ret; + + ret = fdt_value_setenv(nodep, len, var); + if (ret != 0) + return ret; + } else if (subcmd[0] == 'a') { + /* Get address */ + char buf[11]; + + sprintf(buf, "0x%p", nodep); + setenv(var, buf); + } else if (subcmd[0] == 's') { + /* Get size */ + char buf[11]; + + sprintf(buf, "0x%08X", len); + setenv(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') { + 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; + } + } +#endif +#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 + /* 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 + + } + /* resize the fdt */ + else if (strncmp(argv[1], "re", 2) == 0) { + fdt_shrink_to_minimum(working_fdt); + } + else { + /* Unrecognized command */ + return CMD_RET_USAGE; + } + + return 0; +} + +/****************************************************************************/ + +/** + * fdt_valid() - Check if an FDT is valid. If not, change it to NULL + * + * @blobp: Pointer to FDT pointer + * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL) + */ +static int fdt_valid(struct fdt_header **blobp) +{ + const void *blob = *blobp; + int err; + + if (blob == NULL) { + printf ("The address of the fdt is invalid (NULL).\n"); + return 0; + } + + err = fdt_check_header(blob); + if (err == 0) + return 1; /* valid */ + + if (err < 0) { + printf("libfdt fdt_check_header(): %s", fdt_strerror(err)); + /* + * Be more informative on bad version. + */ + if (err == -FDT_ERR_BADVERSION) { + if (fdt_version(blob) < + FDT_FIRST_SUPPORTED_VERSION) { + printf (" - too old, fdt %d < %d", + fdt_version(blob), + FDT_FIRST_SUPPORTED_VERSION); + } + if (fdt_last_comp_version(blob) > + FDT_LAST_SUPPORTED_VERSION) { + printf (" - too new, fdt %d > %d", + fdt_version(blob), + FDT_LAST_SUPPORTED_VERSION); + } + } + printf("\n"); + *blobp = NULL; + return 0; + } + return 1; +} + +/****************************************************************************/ + +/* + * 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); + *(__be32 *)data = __cpu_to_be32(tmp); + 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; + + /* no data, don't print */ + if (len == 0) + return; + + /* + * 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 > CONFIG_CMD_FDT_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 > CONFIG_CMD_FDT_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 (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] [] - Set the [control] fdt location to \n" +#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 - Copy the fdt to and make it active\n" + "fdt resize - Resize fdt to size + padding to 4k addr\n" + "fdt print [] - Recursive print starting at \n" + "fdt list [] - Print one level starting at \n" + "fdt get value - Get and store in \n" + "fdt get name - Get name of node and store in \n" + "fdt get addr - Get start address of and store in \n" + "fdt get size [] - Get size of [] or num nodes and store in \n" + "fdt set [] - Set [to ]\n" + "fdt mknode - Create a new node after \n" + "fdt rm [] - Delete the node or \n" + "fdt header - Display header info\n" + "fdt bootcpu - Set boot cpuid\n" + "fdt memory - Add/Update memory node\n" + "fdt rsvmem print - Show current mem reserves\n" + "fdt rsvmem add - Add a mem reserve\n" + "fdt rsvmem delete - Delete a mem reserves\n" + "fdt chosen [ ] - Add/update the /chosen branch in the tree\n" + " / - initrd start/end addr\n" +#if defined(CONFIG_FIT_SIGNATURE) + "fdt checksign [] - check FIT signature\n" + " - addr of key blob\n" + " default gd->fdt_blob\n" +#endif + "NOTE: Dereference aliases by omiting 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/cmd/fitupd.c b/cmd/fitupd.c new file mode 100644 index 0000000..78b8747 --- /dev/null +++ b/cmd/fitupd.c @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2011 + * Andreas Pretzsch, carpe noctem engineering, apr@cn-eng.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#if !defined(CONFIG_UPDATE_TFTP) +#error "CONFIG_UPDATE_TFTP required" +#endif + +static int do_fitupd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + ulong addr = 0UL; + + if (argc > 2) + return CMD_RET_USAGE; + + if (argc == 2) + addr = simple_strtoul(argv[1], NULL, 16); + + return update_tftp(addr, NULL, NULL); +} + +U_BOOT_CMD(fitupd, 2, 0, do_fitupd, + "update from FIT image", + "[addr]\n" + "\t- run update from FIT image at addr\n" + "\t or from tftp 'updatefile'" +); diff --git a/cmd/flash.c b/cmd/flash.c new file mode 100644 index 0000000..85d18bb --- /dev/null +++ b/cmd/flash.c @@ -0,0 +1,729 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * FLASH support + */ +#include +#include + +#ifdef CONFIG_HAS_DATAFLASH +#include +#endif + +#if defined(CONFIG_CMD_MTDPARTS) +#include + +/* 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 + +#ifndef CONFIG_SYS_NO_FLASH +#include +#include +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. start end - operate on <'start', 'end') + * 2. 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_SYS_NO_FLASH */ + +static int do_flinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +#ifndef CONFIG_SYS_NO_FLASH + ulong bank; +#endif + +#ifdef CONFIG_HAS_DATAFLASH + dataflash_print_info(); +#endif + +#ifndef CONFIG_SYS_NO_FLASH + if (argc == 1) { /* print info for all FLASH banks */ + for (bank=0; 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_SYS_NO_FLASH */ + return 0; +} + +static int do_flerase(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +#ifndef CONFIG_SYS_NO_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, §_first, §_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 - 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_SYS_NO_FLASH */ +} + +#ifndef CONFIG_SYS_NO_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_SYS_NO_FLASH */ + +static int do_protect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int rcode = 0; +#ifndef CONFIG_SYS_NO_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_SYS_NO_FLASH */ +#ifdef CONFIG_HAS_DATAFLASH + int status; +#endif +#if !defined(CONFIG_SYS_NO_FLASH) || defined(CONFIG_HAS_DATAFLASH) + int p; + ulong addr_first, addr_last; +#endif + + if (argc < 3) + return CMD_RET_USAGE; + +#if !defined(CONFIG_SYS_NO_FLASH) || defined(CONFIG_HAS_DATAFLASH) + 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_HAS_DATAFLASH + if ((strcmp(argv[2], "all") != 0) && (strcmp(argv[2], "bank") != 0)) { + addr_first = simple_strtoul(argv[2], NULL, 16); + addr_last = simple_strtoul(argv[3], NULL, 16); + + if (addr_dataflash(addr_first) && addr_dataflash(addr_last)) { + status = dataflash_real_protect(p,addr_first,addr_last); + if (status < 0){ + puts ("Bad DataFlash sector specification\n"); + return 1; + } + printf("%sProtect %d DataFlash Sectors\n", + p ? "" : "Un-", status); + return 0; + } + } +#endif + +#ifndef CONFIG_SYS_NO_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; isector_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, §_first, §_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 */ + 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; isector_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_SYS_NO_FLASH */ + return rcode; +} + +#ifndef CONFIG_SYS_NO_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_SYS_NO_FLASH */ + + +/**************************************************/ +#if defined(CONFIG_CMD_MTDPARTS) +# define TMP_ERASE "erase \n - erase partition\n" +# define TMP_PROT_ON "protect on \n - protect partition\n" +# define TMP_PROT_OFF "protect off \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/cmd/fpga.c b/cmd/fpga.c new file mode 100644 index 0000000..7f99aab --- /dev/null +++ b/cmd/fpga.c @@ -0,0 +1,376 @@ +/* + * (C) Copyright 2000, 2001 + * Rich Ireland, Enterasys Networks, rireland@enterasys.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * FPGA support + */ +#include +#include +#include +#include +#include + +/* Local functions */ +static int fpga_get_op(char *opstr); + +/* Local defines */ +#define FPGA_NONE -1 +#define FPGA_INFO 0 +#define FPGA_LOAD 1 +#define FPGA_LOADB 2 +#define FPGA_DUMP 3 +#define FPGA_LOADMK 4 +#define FPGA_LOADP 5 +#define FPGA_LOADBP 6 +#define FPGA_LOADFS 7 + +/* ------------------------------------------------------------------------- */ +/* command form: + * fpga + * where op is 'load', 'dump', or 'info' + * If there is no device number field, the fpga environment variable is used. + * If there is no data addr field, the fpgadata environment variable is used. + * The info command requires no data address field. + */ +int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int op, dev = FPGA_INVALID_DEVICE; + size_t data_size = 0; + void *fpga_data = NULL; + char *devstr = getenv("fpga"); + char *datastr = getenv("fpgadata"); + int rc = FPGA_FAIL; + int wrong_parms = 0; +#if defined(CONFIG_FIT) + const char *fit_uname = NULL; + ulong fit_addr; +#endif +#if defined(CONFIG_CMD_FPGA_LOADFS) + fpga_fs_info fpga_fsinfo; + fpga_fsinfo.fstype = FS_TYPE_ANY; +#endif + + if (devstr) + dev = (int) simple_strtoul(devstr, NULL, 16); + if (datastr) + fpga_data = (void *)simple_strtoul(datastr, NULL, 16); + + switch (argc) { +#if defined(CONFIG_CMD_FPGA_LOADFS) + case 9: + fpga_fsinfo.blocksize = (unsigned int) + simple_strtoul(argv[5], NULL, 16); + fpga_fsinfo.interface = argv[6]; + fpga_fsinfo.dev_part = argv[7]; + fpga_fsinfo.filename = argv[8]; +#endif + case 5: /* fpga */ + data_size = simple_strtoul(argv[4], NULL, 16); + + case 4: /* fpga */ +#if defined(CONFIG_FIT) + if (fit_parse_subimage(argv[3], (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(argv[3], NULL, 16); + debug("* fpga: cmdline image address = 0x%08lx\n", + (ulong)fpga_data); + } + debug("%s: fpga_data = 0x%x\n", __func__, (uint)fpga_data); + + case 3: /* fpga */ + dev = (int)simple_strtoul(argv[2], NULL, 16); + debug("%s: device = %d\n", __func__, dev); + /* FIXME - this is a really weak test */ + if ((argc == 3) && (dev > fpga_count())) { + /* must be buffer ptr */ + debug("%s: Assuming buffer pointer in arg 3\n", + __func__); + +#if defined(CONFIG_FIT) + if (fit_parse_subimage(argv[2], (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 *)dev; + debug("* fpga: cmdline image addr = 0x%08lx\n", + (ulong)fpga_data); + } + + debug("%s: fpga_data = 0x%x\n", + __func__, (uint)fpga_data); + dev = FPGA_INVALID_DEVICE; /* reset device num */ + } + + case 2: /* fpga */ + op = (int)fpga_get_op(argv[1]); + break; + + default: + debug("%s: Too many or too few args (%d)\n", __func__, argc); + op = FPGA_NONE; /* force usage display */ + break; + } + + if (dev == FPGA_INVALID_DEVICE) { + puts("FPGA device not specified\n"); + op = FPGA_NONE; + } + + switch (op) { + case FPGA_NONE: + case FPGA_INFO: + break; +#if defined(CONFIG_CMD_FPGA_LOADFS) + case FPGA_LOADFS: + /* Blocksize can be zero */ + if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part || + !fpga_fsinfo.filename) + wrong_parms = 1; +#endif + case FPGA_LOAD: + case FPGA_LOADP: + case FPGA_LOADB: + case FPGA_LOADBP: + case FPGA_DUMP: + if (!fpga_data || !data_size) + wrong_parms = 1; + break; +#if defined(CONFIG_CMD_FPGA_LOADMK) + case FPGA_LOADMK: + if (!fpga_data) + wrong_parms = 1; + break; +#endif + } + + if (wrong_parms) { + puts("Wrong parameters for FPGA request\n"); + op = FPGA_NONE; + } + + switch (op) { + case FPGA_NONE: + return CMD_RET_USAGE; + + case FPGA_INFO: + rc = fpga_info(dev); + break; + + case FPGA_LOAD: + rc = fpga_load(dev, fpga_data, data_size, BIT_FULL); + break; + +#if defined(CONFIG_CMD_FPGA_LOADP) + case FPGA_LOADP: + rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL); + break; +#endif + + case FPGA_LOADB: + rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL); + break; + +#if defined(CONFIG_CMD_FPGA_LOADBP) + case FPGA_LOADBP: + rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL); + break; +#endif + +#if defined(CONFIG_CMD_FPGA_LOADFS) + case FPGA_LOADFS: + rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo); + break; +#endif + +#if defined(CONFIG_CMD_FPGA_LOADMK) + case FPGA_LOADMK: + switch (genimg_get_format(fpga_data)) { +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + case IMAGE_FORMAT_LEGACY: + { + image_header_t *hdr = + (image_header_t *)fpga_data; + ulong data; + uint8_t comp; + + comp = image_get_comp(hdr); + if (comp == IH_COMP_GZIP) { +#if defined(CONFIG_GZIP) + ulong image_buf = image_get_data(hdr); + data = image_get_load(hdr); + ulong image_size = ~0UL; + + if (gunzip((void *)data, ~0UL, + (void *)image_buf, + &image_size) != 0) { + puts("GUNZIP: error\n"); + return 1; + } + 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); + } + rc = fpga_load(dev, (void *)data, data_size, + BIT_FULL); + } + break; +#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 == NULL) { + puts("No FIT subimage unit name\n"); + return 1; + } + + if (!fit_check_format(fit_hdr)) { + puts("Bad FIT image format\n"); + return 1; + } + + /* 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 1; + } + + /* verify integrity */ + if (!fit_image_verify(fit_hdr, noffset)) { + puts ("Bad Data Hash\n"); + return 1; + } + + /* get fpga subimage data address and length */ + if (fit_image_get_data(fit_hdr, noffset, + &fit_data, &data_size)) { + puts("Fpga subimage data not found\n"); + return 1; + } + + rc = fpga_load(dev, fit_data, data_size, + BIT_FULL); + } + break; +#endif + default: + puts("** Unknown image type\n"); + rc = FPGA_FAIL; + break; + } + break; +#endif + + case FPGA_DUMP: + rc = fpga_dump(dev, fpga_data, data_size); + break; + + default: + printf("Unknown operation\n"); + return CMD_RET_USAGE; + } + return rc; +} + +/* + * Map op to supported operations. We don't use a table since we + * would just have to relocate it from flash anyway. + */ +static int fpga_get_op(char *opstr) +{ + int op = FPGA_NONE; + + if (!strcmp("info", opstr)) + op = FPGA_INFO; + else if (!strcmp("loadb", opstr)) + op = FPGA_LOADB; + else if (!strcmp("load", opstr)) + op = FPGA_LOAD; +#if defined(CONFIG_CMD_FPGA_LOADP) + else if (!strcmp("loadp", opstr)) + op = FPGA_LOADP; +#endif +#if defined(CONFIG_CMD_FPGA_LOADBP) + else if (!strcmp("loadbp", opstr)) + op = FPGA_LOADBP; +#endif +#if defined(CONFIG_CMD_FPGA_LOADFS) + else if (!strcmp("loadfs", opstr)) + op = FPGA_LOADFS; +#endif +#if defined(CONFIG_CMD_FPGA_LOADMK) + else if (!strcmp("loadmk", opstr)) + op = FPGA_LOADMK; +#endif + else if (!strcmp("dump", opstr)) + op = FPGA_DUMP; + + if (op == FPGA_NONE) + printf("Unknown fpga operation \"%s\"\n", opstr); + + return op; +} + +#if defined(CONFIG_CMD_FPGA_LOADFS) +U_BOOT_CMD(fpga, 9, 1, do_fpga, +#else +U_BOOT_CMD(fpga, 6, 1, do_fpga, +#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] \n" + " [] \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:" +#endif +#endif +); diff --git a/cmd/fpgad.c b/cmd/fpgad.c new file mode 100644 index 0000000..5370c3e --- /dev/null +++ b/cmd/fpgad.c @@ -0,0 +1,101 @@ +/* + * (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. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include + +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(cmd_tbl_t *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/cmd/fs.c b/cmd/fs.c new file mode 100644 index 0000000..8f8f1b2 --- /dev/null +++ b/cmd/fs.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * Inspired by cmd_ext_common.c, cmd_fat.c. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include + +static int do_size_wrapper(cmd_tbl_t *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", + " \n" + " - Find file 'filename' from 'dev' on 'interface'\n" + " and determine its size." +); + +static int do_load_wrapper(cmd_tbl_t *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", + " [ [ [ [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(cmd_tbl_t *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", + " 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(cmd_tbl_t *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 /)", + " [ [directory]]\n" + " - List files in directory 'directory' of partition 'part' on\n" + " device type 'interface' instance 'dev'." +) + +static int do_fstype_wrapper(cmd_tbl_t *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", + " :\n" + "- print filesystem type\n" + "fstype : \n" + "- set environment variable to filesystem type\n" +); diff --git a/cmd/fs_uuid.c b/cmd/fs_uuid.c new file mode 100644 index 0000000..613f3a4 --- /dev/null +++ b/cmd/fs_uuid.c @@ -0,0 +1,26 @@ +/* + * cmd_fs_uuid.c -- fsuuid command + * + * Copyright (C) 2014, Bachmann electronic GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +static int do_fs_uuid_wrapper(cmd_tbl_t *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", + " :\n" + " - print filesystem UUID\n" + "fsuuid : \n" + " - set environment variable to filesystem UUID\n" +); diff --git a/cmd/fuse.c b/cmd/fuse.c new file mode 100644 index 0000000..5998f9b --- /dev/null +++ b/cmd/fuse.c @@ -0,0 +1,146 @@ +/* + * (C) Copyright 2009-2013 ADVANSEE + * Benoît Thébaudeau + * + * Based on the mpc512x iim code: + * Copyright 2008 Silicon Turnkey Express, Inc. + * Martha Marx + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +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? \n"); + + if (confirm_yesno()) + return 1; + + puts("Fuse programming aborted\n"); + return 0; +} + +static int do_fuse(cmd_tbl_t *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 [] - read 1 or 'cnt' fuse words,\n" + " starting at 'word'\n" + "fuse sense [] - sense 1 or 'cnt' fuse words,\n" + " starting at 'word'\n" + "fuse prog [-y] [...] - program 1 or\n" + " several fuse words, starting at 'word' (PERMANENT)\n" + "fuse override [...] - override 1 or\n" + " several fuse words, starting at 'word'" +); diff --git a/cmd/gettime.c b/cmd/gettime.c new file mode 100644 index 0000000..c48baad --- /dev/null +++ b/cmd/gettime.c @@ -0,0 +1,40 @@ +/* + * 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. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Get Timer overflows after 2^32 / CONFIG_SYS_HZ (32Khz) = 131072 sec + */ +#include +#include + +static int do_gettime(cmd_tbl_t *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/cmd/gpio.c b/cmd/gpio.c new file mode 100644 index 0000000..2b78b16 --- /dev/null +++ b/cmd/gpio.c @@ -0,0 +1,220 @@ +/* + * Control GPIO pins on the fly + * + * Copyright (c) 2008-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include + +__weak int name_to_gpio(const char *name) +{ + return simple_strtoul(name, NULL, 10); +} + +enum gpio_cmd { + GPIO_INPUT, + GPIO_SET, + GPIO_CLEAR, + GPIO_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) +{ + char buf[80]; + int ret; + + ret = gpio_get_function(dev, offset, NULL); + if (ret < 0) + goto err; + if (!(*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 || + !strncmp(gpio_name, bank_name, banklen)) { + const char *p = NULL; + int offset; + + p = gpio_name + banklen; + if (gpio_name && *p) { + offset = simple_strtoul(p, NULL, 10); + gpio_get_description(dev, bank_name, offset, + &flags); + } else { + for (offset = 0; offset < num_bits; offset++) { + gpio_get_description(dev, bank_name, + offset, &flags); + } + } + } + /* Add a newline between bank names */ + if (!(flags & FLAG_SHOW_BANK)) + flags |= FLAG_SHOW_NEWLINE; + } + + return ret; +} +#endif + +static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned int gpio; + enum gpio_cmd sub_cmd; + ulong 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", 1)) { + /* 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 = GPIO_INPUT; break; + case 's': sub_cmd = GPIO_SET; break; + case 'c': sub_cmd = GPIO_CLEAR; break; + case 't': sub_cmd = GPIO_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 == GPIO_INPUT) { + gpio_direction_input(gpio); + value = gpio_get_value(gpio); + } else { + switch (sub_cmd) { + case GPIO_SET: value = 1; break; + case GPIO_CLEAR: value = 0; break; + case GPIO_TOGGLE: value = !gpio_get_value(gpio); break; + default: goto show_usage; + } + gpio_direction_output(gpio, value); + } + printf("gpio: pin %s (gpio %i) value is %lu\n", + str_gpio, gpio, value); + + if (ret != -EBUSY) + gpio_free(gpio); + + return value; +} + +U_BOOT_CMD(gpio, 4, 0, do_gpio, + "query and control gpio pins", + " \n" + " - input/set/clear/toggle the specified pin\n" + "gpio status [-a] [ | ] - show [all/claimed] GPIOs"); diff --git a/cmd/gpt.c b/cmd/gpt.c new file mode 100644 index 0000000..d94d553 --- /dev/null +++ b/cmd/gpt.c @@ -0,0 +1,456 @@ +/* + * cmd_gpt.c -- GPT (GUID Partition Table) handling command + * + * Copyright (C) 2015 + * Lukasz Majewski + * + * Copyright (C) 2012 Samsung Electronics + * author: Lukasz Majewski + * author: Piotr Wilczek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_PARTITION_UUIDS +#error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled +#endif + +/** + * 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 = getenv(s); + if (e == NULL) { +#ifdef CONFIG_RANDOM_UUID + debug("%s unset. ", str); + gen_rand_uuid_str(uuid_str, UUID_STR_FORMAT_STD); + setenv(s, uuid_str); + + e = getenv(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; +} + +/** + * 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(block_dev_desc_t *dev_desc, + const char *str_part, + char **str_disk_guid, + disk_partition_t **partitions, + u8 *parts_count) +{ + char *tok, *str, *s; + int i; + char *val, *p; + int p_count; + disk_partition_t *parts; + int errno = 0; + uint64_t size_ll, start_ll; + + 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); + + /* 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); + 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 (strlen(s) == 0) + return -3; + + 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(disk_partition_t), p_count); + + /* 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 (strlen(p) >= sizeof(parts[i].uuid)) { + printf("Wrong uuid format for partition %d\n", i); + errno = -4; + goto err; + } + strcpy((char *)parts[i].uuid, p); + 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 (strlen(p) >= sizeof(parts[i].type_guid)) { + printf("Wrong type guid format for partition %d\n", + i); + errno = -4; + goto err; + } + strcpy((char *)parts[i].type_guid, p); + 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 (strlen(p) >= sizeof(parts[i].name)) { + errno = -4; + goto err; + } + strcpy((char *)parts[i].name, p); + free(val); + + /* size */ + val = extract_val(tok, "size"); + if (!val) { /* 'size' is mandatory */ + errno = -4; + goto err; + } + if (extract_env(val, &p)) + p = val; + 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); + } + + /* bootable */ + if (found_key(tok, "bootable")) + parts[i].bootable = 1; + } + + *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(block_dev_desc_t *blk_dev_desc, const char *str_part) +{ + int ret; + char *str_disk_guid; + u8 part_count = 0; + disk_partition_t *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(block_dev_desc_t *blk_dev_desc, const char *str_part) +{ + ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, + blk_dev_desc->blksz); + disk_partition_t *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; +} + +/** + * 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int ret = CMD_RET_SUCCESS; + int dev = 0; + char *ep; + block_dev_desc_t *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 = 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 { + 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", + " \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" + " gpt verify mmc 0 $partitions\n" +); diff --git a/cmd/hash.c b/cmd/hash.c new file mode 100644 index 0000000..704d21e --- /dev/null +++ b/cmd/hash.c @@ -0,0 +1,56 @@ +/* + * 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. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static int do_hash(cmd_tbl_t *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/cmd/help.c b/cmd/help.c new file mode 100644 index 0000000..6ff494d --- /dev/null +++ b/cmd/help.c @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +static int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *start = ll_entry_start(cmd_tbl_t, cmd); + const int len = ll_entry_count(cmd_tbl_t, cmd); + return _do_help(start, len, cmdtp, flag, argc, argv); +} + +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'" +); + +/* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */ +ll_entry_declare(cmd_tbl_t, question_mark, cmd) = { + "?", CONFIG_SYS_MAXARGS, 1, do_help, + "alias for 'help'", +#ifdef CONFIG_SYS_LONGHELP + "" +#endif /* CONFIG_SYS_LONGHELP */ +}; diff --git a/cmd/host.c b/cmd/host.c new file mode 100644 index 0000000..ba1460e --- /dev/null +++ b/cmd/host.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2012, Google Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +static int host_curr_device = -1; + +static int do_host_load(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_load(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); +} + +static int do_host_ls(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); +} + +static int do_host_save(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); +} + +static int do_host_bind(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + if (argc < 2 || argc > 3) + return CMD_RET_USAGE; + char *ep; + char *dev_str = argv[1]; + char *file = argc >= 3 ? argv[2] : NULL; + int dev = simple_strtoul(dev_str, &ep, 16); + if (*ep) { + printf("** Bad device specification %s **\n", dev_str); + return CMD_RET_USAGE; + } + return host_dev_bind(dev, file); +} + +static int do_host_info(cmd_tbl_t *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++) { + block_dev_desc_t *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 = blk_dev->priv; + printf("%12lu %s\n", (unsigned long)blk_dev->lba, + host_dev->filename); + } + return 0; +} + +static int do_host_dev(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int dev; + char *ep; + block_dev_desc_t *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 cmd_tbl_t 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(bind, 3, 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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *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( + sb, 8, 1, do_host, + "Deprecated: use 'host' command instead.", "" +); + +U_BOOT_CMD( + host, 8, 1, do_host, + "Miscellaneous host commands", + "load hostfs - [ ] - " + "load a file from host\n" + "host ls hostfs - - list files on host\n" + "host save hostfs - [] - " + "save a file to host\n" + "host bind [] - bind \"host\" device to file\n" + "host info [] - show device binding & info\n" + "host 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/cmd/i2c.c b/cmd/i2c.c new file mode 100644 index 0000000..b3bb644 --- /dev/null +++ b/cmd/i2c.c @@ -0,0 +1,2030 @@ +/* + * (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. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * 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: A0 00 A1 ... + * i2c md 50 100 10 display 16 bytes starting at 0x100 + * On the bus: A2 00 A3 ... + * i2c md 50 210 10 display 16 bytes starting at 0x210 + * On the bus: A4 10 A5 ... + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* 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. + */ +#ifdef CONFIG_DM_I2C +#define DEFAULT_ADDR_LEN (-1) +#else +#define DEFAULT_ADDR_LEN 1 +#endif + +#ifdef CONFIG_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) +{ + 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 overriden 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) && !defined(CONFIG_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 ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uint chip; + uint devaddr, length; + int alen; + u_char *memaddr; + int ret; +#ifdef CONFIG_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); + +#ifdef CONFIG_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uint chip; + uint devaddr, length; + int alen; + u_char *memaddr; + int ret; +#ifdef CONFIG_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); + +#ifdef CONFIG_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_platdata(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. + */ +#ifdef CONFIG_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 separate + * write transactions of one byte each + */ + while (length-- > 0) { +#ifdef CONFIG_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; +} + +#ifdef CONFIG_DM_I2C +static int do_i2c_flags(cmd_tbl_t *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(cmd_tbl_t *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 ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uint chip; + uint addr, length; + int alen; + int j, nbytes, linebytes; + int ret; +#ifdef CONFIG_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); + } + +#ifdef CONFIG_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; + +#ifdef CONFIG_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 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 ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uint chip; + ulong addr; + int alen; + uchar byte; + int count; + int ret; +#ifdef CONFIG_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; + +#ifdef CONFIG_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) { +#ifdef CONFIG_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 (cmd_tbl_t *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; +#ifdef CONFIG_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; + +#ifdef CONFIG_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) { +#ifdef CONFIG_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(cmd_tbl_t *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; +#ifdef CONFIG_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; + } + +#ifdef CONFIG_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); +#ifdef CONFIG_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) { + /* + * 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(); +#ifdef CONFIG_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 (cmd_tbl_t *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; +#ifdef CONFIG_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 +#ifdef CONFIG_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uint chip; + int alen; + uint addr; + uint length; + u_char bytes[16]; + int delay; + int ret; +#ifdef CONFIG_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; +#ifdef CONFIG_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) { +#ifdef CONFIG_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 (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + enum { unknown, EDO, SDRAM, DDR2 } type; + + uint chip; + u_char data[128]; + u_char cksum; + int j; + + 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 (i2c_read (chip, 0, 1, data, sizeof (data)) != 0) { + 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 8: + type = DDR2; + puts ("DDR2\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(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + uint chip; + struct edid1_info edid; + int ret; +#ifdef CONFIG_DM_I2C + struct udevice *dev; +#endif + + if (argc < 2) { + cmd_usage(cmdtp); + return 1; + } + + chip = simple_strtoul(argv[1], NULL, 16); +#ifdef CONFIG_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 */ + +#ifdef CONFIG_DM_I2C +static void show_bus(struct udevice *bus) +{ + struct udevice *dev; + + printf("Bus %d:\t%s", bus->req_seq, bus->name); + if (device_active(bus)) + printf(" (active %d)", bus->seq); + printf("\n"); + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + struct dm_i2c_chip *chip = dev_get_parent_platdata(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) || defined(CONFIG_DM_I2C) +static int do_i2c_show_bus(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + if (argc == 1) { + /* show all busses */ +#ifdef CONFIG_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); +#ifdef CONFIG_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) || \ + defined(CONFIG_DM_I2C) +static int do_i2c_bus_num(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int ret = 0; + int bus_no; + + if (argc == 1) { + /* querying current setting */ +#ifdef CONFIG_DM_I2C + struct udevice *bus; + + if (!i2c_get_cur_bus(&bus)) + bus_no = bus->seq; + 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); +#ifdef CONFIG_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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + int speed, ret=0; + +#ifdef CONFIG_DM_I2C + struct udevice *bus; + + if (i2c_get_cur_bus(&bus)) + return 1; +#endif + if (argc == 1) { +#ifdef CONFIG_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); +#ifdef CONFIG_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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ +#if defined(CONFIG_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 cmd_tbl_t cmd_i2c_sub[] = { +#if defined(CONFIG_SYS_I2C) || defined(CONFIG_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) || defined(CONFIG_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, "", ""), +#ifdef CONFIG_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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *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) || defined(CONFIG_DM_I2C) + "bus [muxtype:muxaddr:muxchannel] - show I2C bus info\n" +#endif + "crc32 chip address[.0, .1, .2] count - compute CRC32 checksum\n" +#if defined(CONFIG_SYS_I2C) || \ + defined(CONFIG_I2C_MULTI_BUS) || defined(CONFIG_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" +#ifdef CONFIG_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/cmd/ide.c b/cmd/ide.c new file mode 100644 index 0000000..f19a7ce --- /dev/null +++ b/cmd/ide.c @@ -0,0 +1,1457 @@ +/* + * (C) Copyright 2000-2011 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * IDE support + */ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA) +# include +#endif + +#include +#include + +#ifdef CONFIG_STATUS_LED +# include +#endif + +#ifdef __PPC__ +# define EIEIO __asm__ volatile ("eieio") +# define SYNC __asm__ volatile ("sync") +#else +# define EIEIO /* nothing */ +# define SYNC /* nothing */ +#endif + +/* ------------------------------------------------------------------------- */ + +/* Current I/O Device */ +static int curr_device = -1; + +/* Current offset for IDE0 / IDE1 bus access */ +ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = { +#if defined(CONFIG_SYS_ATA_IDE0_OFFSET) + CONFIG_SYS_ATA_IDE0_OFFSET, +#endif +#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1) + CONFIG_SYS_ATA_IDE1_OFFSET, +#endif +}; + +static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; + +block_dev_desc_t ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_IDE_RESET +static void ide_reset (void); +#else +#define ide_reset() /* dummy */ +#endif + +static void ide_ident (block_dev_desc_t *dev_desc); +static uchar ide_wait (int dev, ulong t); + +#define IDE_TIME_OUT 2000 /* 2 sec timeout */ + +#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */ + +#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ + +static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); + +#ifndef CONFIG_SYS_ATA_PORT_ADDR +#define CONFIG_SYS_ATA_PORT_ADDR(port) (port) +#endif + +#ifdef CONFIG_ATAPI +static void atapi_inquiry(block_dev_desc_t *dev_desc); +static ulong atapi_read(block_dev_desc_t *block_dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer); +#endif + + +/* ------------------------------------------------------------------------- */ + +int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int rcode = 0; + + switch (argc) { + case 0: + case 1: + return CMD_RET_USAGE; + case 2: + if (strncmp(argv[1], "res", 3) == 0) { + puts("\nReset IDE" +#ifdef CONFIG_IDE_8xx_DIRECT + " on PCMCIA " PCMCIA_SLOT_MSG +#endif + ": "); + + ide_init(); + return 0; + } else if (strncmp(argv[1], "inf", 3) == 0) { + int i; + + putc('\n'); + + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { + if (ide_dev_desc[i].type == DEV_TYPE_UNKNOWN) + continue; /* list only known devices */ + printf("IDE device %d: ", i); + dev_print(&ide_dev_desc[i]); + } + return 0; + + } else if (strncmp(argv[1], "dev", 3) == 0) { + if ((curr_device < 0) + || (curr_device >= CONFIG_SYS_IDE_MAXDEVICE)) { + puts("\nno IDE devices available\n"); + return 1; + } + printf("\nIDE device %d: ", curr_device); + dev_print(&ide_dev_desc[curr_device]); + return 0; + } else if (strncmp(argv[1], "part", 4) == 0) { + int dev, ok; + + for (ok = 0, dev = 0; + dev < CONFIG_SYS_IDE_MAXDEVICE; + ++dev) { + if (ide_dev_desc[dev].part_type != + PART_TYPE_UNKNOWN) { + ++ok; + if (dev) + putc('\n'); + print_part(&ide_dev_desc[dev]); + } + } + if (!ok) { + puts("\nno IDE devices available\n"); + rcode++; + } + return rcode; + } + return CMD_RET_USAGE; + case 3: + if (strncmp(argv[1], "dev", 3) == 0) { + int dev = (int) simple_strtoul(argv[2], NULL, 10); + + printf("\nIDE device %d: ", dev); + if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { + puts("unknown device\n"); + return 1; + } + dev_print(&ide_dev_desc[dev]); + /*ide_print (dev); */ + + if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) + return 1; + + curr_device = dev; + + puts("... is now current device\n"); + + return 0; + } else if (strncmp(argv[1], "part", 4) == 0) { + int dev = (int) simple_strtoul(argv[2], NULL, 10); + + if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { + print_part(&ide_dev_desc[dev]); + } else { + printf("\nIDE device %d not available\n", + dev); + rcode = 1; + } + return rcode; + } + + return CMD_RET_USAGE; + default: + /* at least 4 args */ + + if (strcmp(argv[1], "read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + block_dev_desc_t *dev_desc; + ulong n; + +#ifdef CONFIG_SYS_64BIT_LBA + lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + + printf("\nIDE read: device %d block # %lld, count %ld ... ", + curr_device, blk, cnt); +#else + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + + printf("\nIDE read: device %d block # %ld, count %ld ... ", + curr_device, blk, cnt); +#endif + + dev_desc = &ide_dev_desc[curr_device]; + n = dev_desc->block_read(dev_desc, blk, cnt, + (ulong *)addr); + /* flush cache after read */ + flush_cache(addr, + cnt * ide_dev_desc[curr_device].blksz); + + printf("%ld blocks read: %s\n", + n, (n == cnt) ? "OK" : "ERROR"); + if (n == cnt) + return 0; + else + return 1; + } else if (strcmp(argv[1], "write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + +#ifdef CONFIG_SYS_64BIT_LBA + lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + + printf("\nIDE write: device %d block # %lld, count %ld ... ", + curr_device, blk, cnt); +#else + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + + printf("\nIDE write: device %d block # %ld, count %ld ... ", + curr_device, blk, cnt); +#endif + n = ide_write(&ide_dev_desc[curr_device], blk, cnt, + (ulong *)addr); + + printf("%ld blocks written: %s\n", + n, (n == cnt) ? "OK" : "ERROR"); + if (n == cnt) + return 0; + else + return 1; + } else { + return CMD_RET_USAGE; + } + + return rcode; + } +} + +int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + return common_diskboot(cmdtp, "ide", argc, argv); +} + +/* ------------------------------------------------------------------------- */ + +__weak void ide_led(uchar led, uchar status) +{ +#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ + static uchar led_buffer; /* Buffer for current LED status */ + + uchar *led_port = LED_PORT; + + if (status) /* switch LED on */ + led_buffer |= led; + else /* switch LED off */ + led_buffer &= ~led; + + *led_port = led_buffer; +#endif +} + +#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ +# define DEVICE_LED(x) 0 +# define LED_IDE1 1 +# define LED_IDE2 2 +#endif + +/* ------------------------------------------------------------------------- */ + +__weak void ide_outb(int dev, int port, unsigned char val) +{ + debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", + dev, port, val, + (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); + +#if defined(CONFIG_IDE_AHB) + if (port) { + /* write command */ + ide_write_register(dev, port, val); + } else { + /* write data */ + outb(val, (ATA_CURR_BASE(dev))); + } +#else + outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif +} + +__weak unsigned char ide_inb(int dev, int port) +{ + uchar val; + +#if defined(CONFIG_IDE_AHB) + val = ide_read_register(dev, port); +#else + val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif + + debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", + dev, port, + (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); + return val; +} + +void ide_init(void) +{ + unsigned char c; + int i, bus; + +#ifdef CONFIG_IDE_8xx_PCCARD + extern int ide_devices_found; /* Initialized in check_ide_device() */ +#endif /* CONFIG_IDE_8xx_PCCARD */ + +#ifdef CONFIG_IDE_PREINIT + WATCHDOG_RESET(); + + if (ide_preinit()) { + puts("ide_preinit failed\n"); + return; + } +#endif /* CONFIG_IDE_PREINIT */ + + WATCHDOG_RESET(); + + /* + * Reset the IDE just to be sure. + * Light LED's to show + */ + ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ + + /* ATAPI Drives seems to need a proper IDE Reset */ + ide_reset(); + +#ifdef CONFIG_IDE_INIT_POSTRESET + WATCHDOG_RESET(); + + if (ide_init_postreset()) { + puts("ide_preinit_postreset failed\n"); + return; + } +#endif /* CONFIG_IDE_INIT_POSTRESET */ + + /* + * Wait for IDE to get ready. + * According to spec, this can take up to 31 seconds! + */ + for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { + int dev = + bus * (CONFIG_SYS_IDE_MAXDEVICE / + CONFIG_SYS_IDE_MAXBUS); + +#ifdef CONFIG_IDE_8xx_PCCARD + /* Skip non-ide devices from probing */ + if ((ide_devices_found & (1 << bus)) == 0) { + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + continue; + } +#endif + printf("Bus %d: ", bus); + + ide_bus_ok[bus] = 0; + + /* Select device + */ + udelay(100000); /* 100 ms */ + ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); + udelay(100000); /* 100 ms */ + i = 0; + do { + udelay(10000); /* 10 ms */ + + c = ide_inb(dev, ATA_STATUS); + i++; + if (i > (ATA_RESET_TIME * 100)) { + puts("** Timeout **\n"); + /* LED's off */ + ide_led((LED_IDE1 | LED_IDE2), 0); + return; + } + if ((i >= 100) && ((i % 100) == 0)) + putc('.'); + + } while (c & ATA_STAT_BUSY); + + if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { + puts("not available "); + debug("Status = 0x%02X ", c); +#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ + } else if ((c & ATA_STAT_READY) == 0) { + puts("not available "); + debug("Status = 0x%02X ", c); +#endif + } else { + puts("OK "); + ide_bus_ok[bus] = 1; + } + WATCHDOG_RESET(); + } + + putc('\n'); + + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + + curr_device = -1; + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { + int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + ide_dev_desc[i].if_type = IF_TYPE_IDE; + ide_dev_desc[i].dev = i; + ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + ide_dev_desc[i].blksz = 0; + ide_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); + ide_dev_desc[i].lba = 0; + ide_dev_desc[i].block_read = ide_read; + ide_dev_desc[i].block_write = ide_write; + if (!ide_bus_ok[IDE_BUS(i)]) + continue; + ide_led(led, 1); /* LED on */ + ide_ident(&ide_dev_desc[i]); + ide_led(led, 0); /* LED off */ + dev_print(&ide_dev_desc[i]); + + if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { + /* initialize partition type */ + init_part(&ide_dev_desc[i]); + if (curr_device < 0) + curr_device = i; + } + } + WATCHDOG_RESET(); +} + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_PARTITIONS +block_dev_desc_t *ide_get_dev(int dev) +{ + return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; +} +#endif + +/* ------------------------------------------------------------------------- */ + +/* We only need to swap data if we are running on a big endian cpu. */ +#if defined(__LITTLE_ENDIAN) +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) +{ + ide_input_data(dev, sect_buf, words); +} +#else +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) +{ + volatile ushort *pbuf = + (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); + ushort *dbuf = (ushort *) sect_buf; + + debug("in input swap data base for read is %lx\n", + (unsigned long) pbuf); + + while (words--) { +#ifdef __MIPS__ + *dbuf++ = swab16p((u16 *) pbuf); + *dbuf++ = swab16p((u16 *) pbuf); +#else + *dbuf++ = ld_le16(pbuf); + *dbuf++ = ld_le16(pbuf); +#endif /* !MIPS */ + } +} +#endif /* __LITTLE_ENDIAN */ + + +#if defined(CONFIG_IDE_SWAP_IO) +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *) sect_buf; + while (words--) { + EIEIO; + *pbuf = *dbuf++; + EIEIO; + *pbuf = *dbuf++; + } +} +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) +{ +#if defined(CONFIG_IDE_AHB) + ide_write_data(dev, sect_buf, words); +#else + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif +} +#endif /* CONFIG_IDE_SWAP_IO */ + +#if defined(CONFIG_IDE_SWAP_IO) +__weak void ide_input_data(int dev, ulong *sect_buf, int words) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *) sect_buf; + + debug("in input data base for read is %lx\n", (unsigned long) pbuf); + + while (words--) { + EIEIO; + *dbuf++ = *pbuf; + EIEIO; + *dbuf++ = *pbuf; + } +} +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_input_data(int dev, ulong *sect_buf, int words) +{ +#if defined(CONFIG_IDE_AHB) + ide_read_data(dev, sect_buf, words); +#else + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif +} + +#endif /* CONFIG_IDE_SWAP_IO */ + +/* ------------------------------------------------------------------------- + */ +static void ide_ident(block_dev_desc_t *dev_desc) +{ + unsigned char c; + hd_driveid_t iop; + +#ifdef CONFIG_ATAPI + int retries = 0; +#endif + int device; + + device = dev_desc->dev; + printf(" Device %d: ", device); + + ide_led(DEVICE_LED(device), 1); /* LED on */ + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + dev_desc->if_type = IF_TYPE_IDE; +#ifdef CONFIG_ATAPI + + retries = 0; + + /* Warning: This will be tricky to read */ + while (retries <= 1) { + /* check signature */ + if ((ide_inb(device, ATA_SECT_CNT) == 0x01) && + (ide_inb(device, ATA_SECT_NUM) == 0x01) && + (ide_inb(device, ATA_CYL_LOW) == 0x14) && + (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) { + /* ATAPI Signature found */ + dev_desc->if_type = IF_TYPE_ATAPI; + /* + * Start Ident Command + */ + ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT); + /* + * Wait for completion - ATAPI devices need more time + * to become ready + */ + c = ide_wait(device, ATAPI_TIME_OUT); + } else +#endif + { + /* + * Start Ident Command + */ + ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT); + + /* + * Wait for completion + */ + c = ide_wait(device, IDE_TIME_OUT); + } + ide_led(DEVICE_LED(device), 0); /* LED off */ + + if (((c & ATA_STAT_DRQ) == 0) || + ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) { +#ifdef CONFIG_ATAPI + { + /* + * Need to soft reset the device + * in case it's an ATAPI... + */ + debug("Retrying...\n"); + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + udelay(100000); + ide_outb(device, ATA_COMMAND, 0x08); + udelay(500000); /* 500 ms */ + } + /* + * Select device + */ + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + retries++; +#else + return; +#endif + } +#ifdef CONFIG_ATAPI + else + break; + } /* see above - ugly to read */ + + if (retries == 2) /* Not found */ + return; +#endif + + ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); + + ident_cpy((unsigned char *) dev_desc->revision, iop.fw_rev, + sizeof(dev_desc->revision)); + ident_cpy((unsigned char *) dev_desc->vendor, iop.model, + sizeof(dev_desc->vendor)); + ident_cpy((unsigned char *) dev_desc->product, iop.serial_no, + sizeof(dev_desc->product)); +#ifdef __LITTLE_ENDIAN + /* + * firmware revision, model, and serial number have Big Endian Byte + * order in Word. Convert all three to little endian. + * + * See CF+ and CompactFlash Specification Revision 2.0: + * 6.2.1.6: Identify Drive, Table 39 for more details + */ + + strswab(dev_desc->revision); + strswab(dev_desc->vendor); + strswab(dev_desc->product); +#endif /* __LITTLE_ENDIAN */ + + if ((iop.config & 0x0080) == 0x0080) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + +#ifdef CONFIG_ATAPI + if (dev_desc->if_type == IF_TYPE_ATAPI) { + atapi_inquiry(dev_desc); + return; + } +#endif /* CONFIG_ATAPI */ + +#ifdef __BIG_ENDIAN + /* swap shorts */ + dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16); +#else /* ! __BIG_ENDIAN */ + /* + * do not swap shorts on little endian + * + * See CF+ and CompactFlash Specification Revision 2.0: + * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details. + */ + dev_desc->lba = iop.lba_capacity; +#endif /* __BIG_ENDIAN */ + +#ifdef CONFIG_LBA48 + if (iop.command_set_2 & 0x0400) { /* LBA 48 support */ + dev_desc->lba48 = 1; + dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] | + ((unsigned long long) iop.lba48_capacity[1] << 16) | + ((unsigned long long) iop.lba48_capacity[2] << 32) | + ((unsigned long long) iop.lba48_capacity[3] << 48); + } else { + dev_desc->lba48 = 0; + } +#endif /* CONFIG_LBA48 */ + /* assuming HD */ + dev_desc->type = DEV_TYPE_HARDDISK; + dev_desc->blksz = ATA_BLOCKSIZE; + dev_desc->log2blksz = LOG2(dev_desc->blksz); + dev_desc->lun = 0; /* just to fill something in... */ + +#if 0 /* only used to test the powersaving mode, + * if enabled, the drive goes after 5 sec + * in standby mode */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait(device, IDE_TIME_OUT); + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, 0); + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, 0xe3); + udelay(50); + c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ +#endif +} + + +/* ------------------------------------------------------------------------- */ + +ulong ide_read(block_dev_desc_t *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +{ + int device = block_dev->dev; + ulong n = 0; + unsigned char c; + unsigned char pwrsave = 0; /* power save */ + +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; + + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif + debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", + device, blknr, blkcnt, (ulong) buffer); + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait(device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; + } + + /* first check if the drive is in Powersaving mode, if yes, + * increase the timeout value */ + ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); + udelay(50); + + c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; + } + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + printf("No Powersaving mode %X\n", c); + } else { + c = ide_inb(device, ATA_SECT_CNT); + debug("Powersaving %02X\n", c); + if (c == 0) + pwrsave = 1; + } + + + while (blkcnt-- > 0) { + + c = ide_wait(device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + break; + } +#ifdef CONFIG_LBA48 + if (lba48) { + /* write high bits */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#endif + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); + +#ifdef CONFIG_LBA48 + if (lba48) { + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT); + + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_READ); + } + + udelay(50); + + if (pwrsave) { + /* may take up to 4 sec */ + c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); + pwrsave = 0; + } else { + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT); + } + + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF ": status " + "%#02x\n", device, blknr, c); + break; + } + + ide_input_data(device, buffer, ATA_SECTORWORDS); + (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ + + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +IDE_READ_E: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return (n); +} + +/* ------------------------------------------------------------------------- */ + + +ulong ide_write(block_dev_desc_t *block_dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +{ + int device = block_dev->dev; + ulong n = 0; + unsigned char c; + +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; + + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + + while (blkcnt-- > 0) { + + c = ide_wait(device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto WR_OUT; + } +#ifdef CONFIG_LBA48 + if (lba48) { + /* write high bits */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#endif + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); + +#ifdef CONFIG_LBA48 + if (lba48) { + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT); + + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); + } + + udelay(50); + + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT); + + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF ": status " + "%#02x\n", device, blknr, c); + goto WR_OUT; + } + + ide_output_data(device, buffer, ATA_SECTORWORDS); + c = ide_inb(device, ATA_STATUS); /* clear IRQ */ + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +WR_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return (n); +} + +/* ------------------------------------------------------------------------- */ + +/* + * copy src to dest, skipping leading and trailing blanks and null + * terminate the string + * "len" is the size of available memory including the terminating '\0' + */ +static void ident_cpy(unsigned char *dst, unsigned char *src, + unsigned int len) +{ + unsigned char *end, *last; + + last = dst; + end = src + len - 1; + + /* reserve space for '\0' */ + if (len < 2) + goto OUT; + + /* skip leading white space */ + while ((*src) && (src < end) && (*src == ' ')) + ++src; + + /* copy string, omitting trailing white space */ + while ((*src) && (src < end)) { + *dst++ = *src; + if (*src++ != ' ') + last = dst; + } +OUT: + *last = '\0'; +} + +/* ------------------------------------------------------------------------- */ + +/* + * Wait until Busy bit is off, or timeout (in ms) + * Return last status + */ +static uchar ide_wait(int dev, ulong t) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { + udelay(100); + if (delay-- == 0) + break; + } + return (c); +} + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_IDE_RESET +extern void ide_set_reset(int idereset); + +static void ide_reset(void) +{ + int i; + + curr_device = -1; + for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) + ide_bus_ok[i] = 0; + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + + ide_set_reset(1); /* assert reset */ + + /* the reset signal shall be asserted for et least 25 us */ + udelay(25); + + WATCHDOG_RESET(); + + /* de-assert RESET signal */ + ide_set_reset(0); + + /* wait 250 ms */ + for (i = 0; i < 250; ++i) + udelay(1000); +} + +#endif /* CONFIG_IDE_RESET */ + +/* ------------------------------------------------------------------------- */ + +#if defined(CONFIG_OF_IDE_FIXUP) +int ide_device_present(int dev) +{ + if (dev >= CONFIG_SYS_IDE_MAXBUS) + return 0; + return (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1); +} +#endif +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_ATAPI +/**************************************************************************** + * ATAPI Support + */ + +#if defined(CONFIG_IDE_SWAP_IO) +/* since ATAPI may use commands with not 4 bytes alligned length + * we have our own transfer functions, 2 bytes alligned */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *) sect_buf; + + debug("in output data shorts base for read is %lx\n", + (unsigned long) pbuf); + + while (shorts--) { + EIEIO; + *pbuf = *dbuf++; + } +} + +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *) sect_buf; + + debug("in input data shorts base for read is %lx\n", + (unsigned long) pbuf); + + while (shorts--) { + EIEIO; + *dbuf++ = *pbuf; + } +} + +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +} + +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +} + +#endif /* CONFIG_IDE_SWAP_IO */ + +/* + * Wait until (Status & mask) == res, or timeout (in ms) + * Return last status + * This is used since some ATAPI CD ROMs clears their Busy Bit first + * and then they set their DRQ Bit + */ +static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + /* prevents to read the status before valid */ + c = ide_inb(dev, ATA_DEV_CTL); + + while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { + /* break if error occurs (doesn't make sense to wait more) */ + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) + break; + udelay(100); + if (delay-- == 0) + break; + } + return (c); +} + +/* + * issue an atapi command + */ +unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char c, err, mask, res; + int n; + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + mask = ATA_STAT_BUSY | ATA_STAT_DRQ; + res = 0; + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + printf("ATAPI_ISSUE: device %d not ready status %X\n", device, + c); + err = 0xFF; + goto AI_OUT; + } + /* write taskfile */ + ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_SECT_NUM, 0); + ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); + ide_outb(device, ATA_CYL_HIGH, + (unsigned char) ((buflen >> 8) & 0xFF)); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + + ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); + udelay(50); + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + + if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ + printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", + device, c); + err = 0xFF; + goto AI_OUT; + } + + /* write command block */ + ide_output_data_shorts(device, (unsigned short *) ccb, ccblen / 2); + + /* ATAPI Command written wait for completition */ + udelay(5000); /* device must set bsy */ + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + /* + * if no data wait for DRQ = 0 BSY = 0 + * if data wait for DRQ = 1 BSY = 0 + */ + res = 0; + if (buflen) + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + if (c & ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG)) >> 4; + debug("atapi_issue 1 returned sense key %X status %02X\n", + err, c); + } else { + printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", + ccb[0], c); + err = 0xFF; + } + goto AI_OUT; + } + n = ide_inb(device, ATA_CYL_HIGH); + n <<= 8; + n += ide_inb(device, ATA_CYL_LOW); + if (n > buflen) { + printf("ERROR, transfer bytes %d requested only %d\n", n, + buflen); + err = 0xff; + goto AI_OUT; + } + if ((n == 0) && (buflen < 0)) { + printf("ERROR, transfer bytes %d requested %d\n", n, buflen); + err = 0xff; + goto AI_OUT; + } + if (n != buflen) { + debug("WARNING, transfer bytes %d not equal with requested %d\n", + n, buflen); + } + if (n != 0) { /* data transfer */ + debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); + /* we transfer shorts */ + n >>= 1; + /* ok now decide if it is an in or output */ + if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { + debug("Write to device\n"); + ide_output_data_shorts(device, + (unsigned short *) buffer, n); + } else { + debug("Read from device @ %p shorts %d\n", buffer, n); + ide_input_data_shorts(device, + (unsigned short *) buffer, n); + } + } + udelay(5000); /* seems that some CD ROMs need this... */ + mask = ATA_STAT_BUSY | ATA_STAT_ERR; + res = 0; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG) >> 4); + debug("atapi_issue 2 returned sense key %X status %X\n", err, + c); + } else { + err = 0; + } +AI_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return (err); +} + +/* + * sending the command to atapi_issue. If an status other than good + * returns, an request_sense will be issued + */ + +#define ATAPI_DRIVE_NOT_READY 100 +#define ATAPI_UNIT_ATTN 10 + +unsigned char atapi_issue_autoreq(int device, + unsigned char *ccb, + int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char sense_data[18], sense_ccb[12]; + unsigned char res, key, asc, ascq; + int notready, unitattn; + + unitattn = ATAPI_UNIT_ATTN; + notready = ATAPI_DRIVE_NOT_READY; + +retry: + res = atapi_issue(device, ccb, ccblen, buffer, buflen); + if (res == 0) + return 0; /* Ok */ + + if (res == 0xFF) + return 0xFF; /* error */ + + debug("(auto_req)atapi_issue returned sense key %X\n", res); + + memset(sense_ccb, 0, sizeof(sense_ccb)); + memset(sense_data, 0, sizeof(sense_data)); + sense_ccb[0] = ATAPI_CMD_REQ_SENSE; + sense_ccb[4] = 18; /* allocation Length */ + + res = atapi_issue(device, sense_ccb, 12, sense_data, 18); + key = (sense_data[2] & 0xF); + asc = (sense_data[12]); + ascq = (sense_data[13]); + + debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); + debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", + sense_data[0], key, asc, ascq); + + if ((key == 0)) + return 0; /* ok device ready */ + + if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ + if (unitattn-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); + goto error; + } + if ((asc == 0x4) && (ascq == 0x1)) { + /* not ready, but will be ready soon */ + if (notready-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Drive not ready, tried %d times\n", + ATAPI_DRIVE_NOT_READY); + goto error; + } + if (asc == 0x3a) { + debug("Media not present\n"); + goto error; + } + + printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, + ascq); +error: + debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); + return (0xFF); +} + + +static void atapi_inquiry(block_dev_desc_t *dev_desc) +{ + unsigned char ccb[12]; /* Command descriptor block */ + unsigned char iobuf[64]; /* temp buf */ + unsigned char c; + int device; + + device = dev_desc->dev; + dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ + dev_desc->block_read = atapi_read; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + + ccb[0] = ATAPI_CMD_INQUIRY; + ccb[4] = 40; /* allocation Legnth */ + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 40); + + debug("ATAPI_CMD_INQUIRY returned %x\n", c); + if (c != 0) + return; + + /* copy device ident strings */ + ident_cpy((unsigned char *) dev_desc->vendor, &iobuf[8], 8); + ident_cpy((unsigned char *) dev_desc->product, &iobuf[16], 16); + ident_cpy((unsigned char *) dev_desc->revision, &iobuf[32], 5); + + dev_desc->lun = 0; + dev_desc->lba = 0; + dev_desc->blksz = 0; + dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); + dev_desc->type = iobuf[0] & 0x1f; + + if ((iobuf[1] & 0x80) == 0x80) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_START_STOP; + ccb[4] = 0x03; /* start */ + + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); + + debug("ATAPI_CMD_START_STOP returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); + + debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_READ_CAP; + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 8); + debug("ATAPI_CMD_READ_CAP returned %x\n", c); + if (c != 0) + return; + + debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", + iobuf[0], iobuf[1], iobuf[2], iobuf[3], + iobuf[4], iobuf[5], iobuf[6], iobuf[7]); + + dev_desc->lba = ((unsigned long) iobuf[0] << 24) + + ((unsigned long) iobuf[1] << 16) + + ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); + dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + + ((unsigned long) iobuf[5] << 16) + + ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); + dev_desc->log2blksz = LOG2(dev_desc->blksz); +#ifdef CONFIG_LBA48 + /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ + dev_desc->lba48 = 0; +#endif + return; +} + + +/* + * atapi_read: + * we transfer only one block per command, since the multiple DRQ per + * command is not yet implemented + */ +#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ +#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ +#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) + +ulong atapi_read(block_dev_desc_t *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +{ + int device = block_dev->dev; + ulong n = 0; + unsigned char ccb[12]; /* Command descriptor block */ + ulong cnt; + + debug("atapi_read dev %d start " LBAF " blocks " LBAF " buffer at %lX\n", + device, blknr, blkcnt, (ulong) buffer); + + do { + if (blkcnt > ATAPI_READ_MAX_BLOCK) + cnt = ATAPI_READ_MAX_BLOCK; + else + cnt = blkcnt; + + ccb[0] = ATAPI_CMD_READ_12; + ccb[1] = 0; /* reserved */ + ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ + ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ + ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; + ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ + ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ + ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; + ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; + ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ + ccb[10] = 0; /* reserved */ + ccb[11] = 0; /* reserved */ + + if (atapi_issue_autoreq(device, ccb, 12, + (unsigned char *) buffer, + cnt * ATAPI_READ_BLOCK_SIZE) + == 0xFF) { + return (n); + } + n += cnt; + blkcnt -= cnt; + blknr += cnt; + buffer += (cnt * ATAPI_READ_BLOCK_SIZE); + } while (blkcnt > 0); + return (n); +} + +/* ------------------------------------------------------------------------- */ + +#endif /* CONFIG_ATAPI */ + +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/cmd/immap.c b/cmd/immap.c new file mode 100644 index 0000000..1414f9a --- /dev/null +++ b/cmd/immap.c @@ -0,0 +1,703 @@ +/* + * (C) Copyright 2000-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * MPC8xx/MPC8260 Internal Memory Map Functions + */ + +#include +#include + +#if defined(CONFIG_8xx) || defined(CONFIG_MPC8260) + +#if defined(CONFIG_8xx) +#include +#include +#include +#elif defined(CONFIG_MPC8260) +#include +#include +#include +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static void +unimplemented ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + printf ("Sorry, but the '%s' command has not been implemented\n", + cmdtp->name); +} + +int +do_siuinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + +#if defined(CONFIG_8xx) + volatile sysconf8xx_t *sc = &immap->im_siu_conf; +#elif defined(CONFIG_MPC8260) + volatile sysconf8260_t *sc = &immap->im_siu_conf; +#endif + + printf ("SIUMCR= %08x SYPCR = %08x\n", sc->sc_siumcr, sc->sc_sypcr); +#if defined(CONFIG_8xx) + printf ("SWT = %08x\n", sc->sc_swt); + printf ("SIPEND= %08x SIMASK= %08x\n", sc->sc_sipend, sc->sc_simask); + printf ("SIEL = %08x SIVEC = %08x\n", sc->sc_siel, sc->sc_sivec); + printf ("TESR = %08x SDCR = %08x\n", sc->sc_tesr, sc->sc_sdcr); +#elif defined(CONFIG_MPC8260) + printf ("BCR = %08x\n", sc->sc_bcr); + printf ("P_ACR = %02x P_ALRH= %08x P_ALRL= %08x\n", + sc->sc_ppc_acr, sc->sc_ppc_alrh, sc->sc_ppc_alrl); + printf ("L_ACR = %02x L_ALRH= %08x L_ALRL= %08x\n", + sc->sc_lcl_acr, sc->sc_lcl_alrh, sc->sc_lcl_alrl); + printf ("PTESR1= %08x PTESR2= %08x\n", sc->sc_tescr1, sc->sc_tescr2); + printf ("LTESR1= %08x LTESR2= %08x\n", sc->sc_ltescr1, sc->sc_ltescr2); + printf ("PDTEA = %08x PDTEM = %02x\n", sc->sc_pdtea, sc->sc_pdtem); + printf ("LDTEA = %08x LDTEM = %02x\n", sc->sc_ldtea, sc->sc_ldtem); +#endif + return 0; +} + +int +do_memcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + +#if defined(CONFIG_8xx) + volatile memctl8xx_t *memctl = &immap->im_memctl; + int nbanks = 8; +#elif defined(CONFIG_MPC8260) + volatile memctl8260_t *memctl = &immap->im_memctl; + int nbanks = 12; +#endif + volatile uint *p = &memctl->memc_br0; + int i; + + for (i = 0; i < nbanks; i++, p += 2) { + if (i < 10) { + printf ("BR%d = %08x OR%d = %08x\n", + i, p[0], i, p[1]); + } else { + printf ("BR%d = %08x OR%d = %08x\n", + i, p[0], i, p[1]); + } + } + + printf ("MAR = %08x", memctl->memc_mar); +#if defined(CONFIG_8xx) + printf (" MCR = %08x\n", memctl->memc_mcr); +#elif defined(CONFIG_MPC8260) + putc ('\n'); +#endif + printf ("MAMR = %08x MBMR = %08x", + memctl->memc_mamr, memctl->memc_mbmr); +#if defined(CONFIG_8xx) + printf ("\nMSTAT = %04x\n", memctl->memc_mstat); +#elif defined(CONFIG_MPC8260) + printf (" MCMR = %08x\n", memctl->memc_mcmr); +#endif + printf ("MPTPR = %04x MDR = %08x\n", + memctl->memc_mptpr, memctl->memc_mdr); +#if defined(CONFIG_MPC8260) + printf ("PSDMR = %08x LSDMR = %08x\n", + memctl->memc_psdmr, memctl->memc_lsdmr); + printf ("PURT = %02x PSRT = %02x\n", + memctl->memc_purt, memctl->memc_psrt); + printf ("LURT = %02x LSRT = %02x\n", + memctl->memc_lurt, memctl->memc_lsrt); + printf ("IMMR = %08x\n", memctl->memc_immr); +#endif + return 0; +} + +int +do_sitinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +#ifdef CONFIG_MPC8260 +int +do_icinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} +#endif + +int +do_carinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + +#if defined(CONFIG_8xx) + volatile car8xx_t *car = &immap->im_clkrst; +#elif defined(CONFIG_MPC8260) + volatile car8260_t *car = &immap->im_clkrst; +#endif + +#if defined(CONFIG_8xx) + printf ("SCCR = %08x\n", car->car_sccr); + printf ("PLPRCR= %08x\n", car->car_plprcr); + printf ("RSR = %08x\n", car->car_rsr); +#elif defined(CONFIG_MPC8260) + printf ("SCCR = %08x\n", car->car_sccr); + printf ("SCMR = %08x\n", car->car_scmr); + printf ("RSR = %08x\n", car->car_rsr); + printf ("RMR = %08x\n", car->car_rmr); +#endif + return 0; +} + +static int counter; + +static void +header(void) +{ + char *data = "\ + -------------------------------- --------------------------------\ + 00000000001111111111222222222233 00000000001111111111222222222233\ + 01234567890123456789012345678901 01234567890123456789012345678901\ + -------------------------------- --------------------------------\ + "; + int i; + + if (counter % 2) + putc('\n'); + counter = 0; + + for (i = 0; i < 4; i++, data += 79) + printf("%.79s\n", data); +} + +static void binary (char *label, uint value, int nbits) +{ + uint mask = 1 << (nbits - 1); + int i, second = (counter++ % 2); + + if (second) + putc (' '); + puts (label); + for (i = 32 + 1; i != nbits; i--) + putc (' '); + + while (mask != 0) { + if (value & mask) + putc ('1'); + else + putc ('0'); + mask >>= 1; + } + + if (second) + putc ('\n'); +} + +#if defined(CONFIG_8xx) +#define PA_NBITS 16 +#define PA_NB_ODR 8 +#define PB_NBITS 18 +#define PB_NB_ODR 16 +#define PC_NBITS 12 +#define PD_NBITS 13 +#elif defined(CONFIG_MPC8260) +#define PA_NBITS 32 +#define PA_NB_ODR 32 +#define PB_NBITS 28 +#define PB_NB_ODR 28 +#define PC_NBITS 32 +#define PD_NBITS 28 +#endif + +int +do_iopinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + +#if defined(CONFIG_8xx) + volatile iop8xx_t *iop = &immap->im_ioport; + volatile ushort *l, *r; +#elif defined(CONFIG_MPC8260) + volatile iop8260_t *iop = &immap->im_ioport; + volatile uint *l, *r; +#endif + volatile uint *R; + + counter = 0; + header (); + + /* + * Ports A & B + */ + +#if defined(CONFIG_8xx) + l = &iop->iop_padir; + R = &immap->im_cpm.cp_pbdir; +#elif defined(CONFIG_MPC8260) + l = &iop->iop_pdira; + R = &iop->iop_pdirb; +#endif + binary ("PA_DIR", *l++, PA_NBITS); + binary ("PB_DIR", *R++, PB_NBITS); + binary ("PA_PAR", *l++, PA_NBITS); + binary ("PB_PAR", *R++, PB_NBITS); +#if defined(CONFIG_MPC8260) + binary ("PA_SOR", *l++, PA_NBITS); + binary ("PB_SOR", *R++, PB_NBITS); +#endif + binary ("PA_ODR", *l++, PA_NB_ODR); + binary ("PB_ODR", *R++, PB_NB_ODR); + binary ("PA_DAT", *l++, PA_NBITS); + binary ("PB_DAT", *R++, PB_NBITS); + + header (); + + /* + * Ports C & D + */ + +#if defined(CONFIG_8xx) + l = &iop->iop_pcdir; + r = &iop->iop_pddir; +#elif defined(CONFIG_MPC8260) + l = &iop->iop_pdirc; + r = &iop->iop_pdird; +#endif + binary ("PC_DIR", *l++, PC_NBITS); + binary ("PD_DIR", *r++, PD_NBITS); + binary ("PC_PAR", *l++, PC_NBITS); + binary ("PD_PAR", *r++, PD_NBITS); +#if defined(CONFIG_8xx) + binary ("PC_SO ", *l++, PC_NBITS); + binary (" ", 0, 0); + r++; +#elif defined(CONFIG_MPC8260) + binary ("PC_SOR", *l++, PC_NBITS); + binary ("PD_SOR", *r++, PD_NBITS); + binary ("PC_ODR", *l++, PC_NBITS); + binary ("PD_ODR", *r++, PD_NBITS); +#endif + binary ("PC_DAT", *l++, PC_NBITS); + binary ("PD_DAT", *r++, PD_NBITS); +#if defined(CONFIG_8xx) + binary ("PC_INT", *l++, PC_NBITS); +#endif + + header (); + return 0; +} + +/* + * set the io pins + * this needs a clean up for smaller tighter code + * use *uint and set the address based on cmd + port + */ +int +do_iopset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uint rcode = 0; + iopin_t iopin; + static uint port = 0; + static uint pin = 0; + static uint value = 0; + static enum { + DIR, + PAR, + SOR, + ODR, + DAT, +#if defined(CONFIG_8xx) + INT +#endif + } cmd = DAT; + + if (argc != 5) { + puts ("iopset PORT PIN CMD VALUE\n"); + return 1; + } + port = argv[1][0] - 'A'; + if (port > 3) + port -= 0x20; + if (port > 3) + rcode = 1; + pin = simple_strtol (argv[2], NULL, 10); + if (pin > 31) + rcode = 1; + + + switch (argv[3][0]) { + case 'd': + if (argv[3][1] == 'a') + cmd = DAT; + else if (argv[3][1] == 'i') + cmd = DIR; + else + rcode = 1; + break; + case 'p': + cmd = PAR; + break; + case 'o': + cmd = ODR; + break; + case 's': + cmd = SOR; + break; +#if defined(CONFIG_8xx) + case 'i': + cmd = INT; + break; +#endif + default: + printf ("iopset: unknown command %s\n", argv[3]); + rcode = 1; + } + if (argv[4][0] == '1') + value = 1; + else if (argv[4][0] == '0') + value = 0; + else + rcode = 1; + if (rcode == 0) { + iopin.port = port; + iopin.pin = pin; + iopin.flag = 0; + switch (cmd) { + case DIR: + if (value) + iopin_set_out (&iopin); + else + iopin_set_in (&iopin); + break; + case PAR: + if (value) + iopin_set_ded (&iopin); + else + iopin_set_gen (&iopin); + break; + case SOR: + if (value) + iopin_set_opt2 (&iopin); + else + iopin_set_opt1 (&iopin); + break; + case ODR: + if (value) + iopin_set_odr (&iopin); + else + iopin_set_act (&iopin); + break; + case DAT: + if (value) + iopin_set_high (&iopin); + else + iopin_set_low (&iopin); + break; +#if defined(CONFIG_8xx) + case INT: + if (value) + iopin_set_falledge (&iopin); + else + iopin_set_anyedge (&iopin); + break; +#endif + } + + } + return rcode; +} + +int +do_dmainfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_fccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +static void prbrg (int n, uint val) +{ + uint extc = (val >> 14) & 3; + uint cd = (val & CPM_BRG_CD_MASK) >> 1; + uint div16 = (val & CPM_BRG_DIV16) != 0; + +#if defined(CONFIG_8xx) + ulong clock = gd->cpu_clk; +#elif defined(CONFIG_MPC8260) + ulong clock = gd->arch.brg_clk; +#endif + + printf ("BRG%d:", n); + + if (val & CPM_BRG_RST) + puts (" RESET"); + else + puts (" "); + + if (val & CPM_BRG_EN) + puts (" ENABLED"); + else + puts (" DISABLED"); + + printf (" EXTC=%d", extc); + + if (val & CPM_BRG_ATB) + puts (" ATB"); + else + puts (" "); + + printf (" DIVIDER=%4d", cd); + if (extc == 0 && cd != 0) { + uint baudrate; + + if (div16) + baudrate = (clock / 16) / (cd + 1); + else + baudrate = clock / (cd + 1); + + printf ("=%6d bps", baudrate); + } else { + puts (" "); + } + + if (val & CPM_BRG_DIV16) + puts (" DIV16"); + else + puts (" "); + + putc ('\n'); +} + +int +do_brginfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + +#if defined(CONFIG_8xx) + volatile cpm8xx_t *cp = &immap->im_cpm; + volatile uint *p = &cp->cp_brgc1; +#elif defined(CONFIG_MPC8260) + volatile uint *p = &immap->im_brgc1; +#endif + int i = 1; + + while (i <= 4) + prbrg (i++, *p++); + +#if defined(CONFIG_MPC8260) + p = &immap->im_brgc5; + while (i <= 8) + prbrg (i++, *p++); +#endif + return 0; +} + +int +do_i2cinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; + +#if defined(CONFIG_8xx) + volatile i2c8xx_t *i2c = &immap->im_i2c; + volatile cpm8xx_t *cp = &immap->im_cpm; + volatile iic_t *iip = (iic_t *) & cp->cp_dparam[PROFF_IIC]; +#elif defined(CONFIG_MPC8260) + volatile i2c8260_t *i2c = &immap->im_i2c; + volatile iic_t *iip; + uint dpaddr; + + dpaddr = immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)]; + if (dpaddr == 0) + iip = NULL; + else + iip = (iic_t *) & immap->im_dprambase[dpaddr]; +#endif + + printf ("I2MOD = %02x I2ADD = %02x\n", i2c->i2c_i2mod, i2c->i2c_i2add); + printf ("I2BRG = %02x I2COM = %02x\n", i2c->i2c_i2brg, i2c->i2c_i2com); + printf ("I2CER = %02x I2CMR = %02x\n", i2c->i2c_i2cer, i2c->i2c_i2cmr); + + if (iip == NULL) + puts ("i2c parameter ram not allocated\n"); + else { + printf ("RBASE = %08x TBASE = %08x\n", + iip->iic_rbase, iip->iic_tbase); + printf ("RFCR = %02x TFCR = %02x\n", + iip->iic_rfcr, iip->iic_tfcr); + printf ("MRBLR = %04x\n", iip->iic_mrblr); + printf ("RSTATE= %08x RDP = %08x\n", + iip->iic_rstate, iip->iic_rdp); + printf ("RBPTR = %04x RBC = %04x\n", + iip->iic_rbptr, iip->iic_rbc); + printf ("RXTMP = %08x\n", iip->iic_rxtmp); + printf ("TSTATE= %08x TDP = %08x\n", + iip->iic_tstate, iip->iic_tdp); + printf ("TBPTR = %04x TBC = %04x\n", + iip->iic_tbptr, iip->iic_tbc); + printf ("TXTMP = %08x\n", iip->iic_txtmp); + } + return 0; +} + +int +do_sccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_smcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_spiinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_muxinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_siinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_mccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +/***************************************************/ + +U_BOOT_CMD( + siuinfo, 1, 1, do_siuinfo, + "print System Interface Unit (SIU) registers", + "" +); + +U_BOOT_CMD( + memcinfo, 1, 1, do_memcinfo, + "print Memory Controller registers", + "" +); + +U_BOOT_CMD( + sitinfo, 1, 1, do_sitinfo, + "print System Integration Timers (SIT) registers", + "" +); + +#ifdef CONFIG_MPC8260 +U_BOOT_CMD( + icinfo, 1, 1, do_icinfo, + "print Interrupt Controller registers", + "" +); +#endif + +U_BOOT_CMD( + carinfo, 1, 1, do_carinfo, + "print Clocks and Reset registers", + "" +); + +U_BOOT_CMD( + iopinfo, 1, 1, do_iopinfo, + "print I/O Port registers", + "" +); + +U_BOOT_CMD( + iopset, 5, 0, do_iopset, + "set I/O Port registers", + "PORT PIN CMD VALUE\nPORT: A-D, PIN: 0-31, CMD: [dat|dir|odr|sor], VALUE: 0|1" +); + +U_BOOT_CMD( + dmainfo, 1, 1, do_dmainfo, + "print SDMA/IDMA registers", + "" +); + +U_BOOT_CMD( + fccinfo, 1, 1, do_fccinfo, + "print FCC registers", + "" +); + +U_BOOT_CMD( + brginfo, 1, 1, do_brginfo, + "print Baud Rate Generator (BRG) registers", + "" +); + +U_BOOT_CMD( + i2cinfo, 1, 1, do_i2cinfo, + "print I2C registers", + "" +); + +U_BOOT_CMD( + sccinfo, 1, 1, do_sccinfo, + "print SCC registers", + "" +); + +U_BOOT_CMD( + smcinfo, 1, 1, do_smcinfo, + "print SMC registers", + "" +); + +U_BOOT_CMD( + spiinfo, 1, 1, do_spiinfo, + "print Serial Peripheral Interface (SPI) registers", + "" +); + +U_BOOT_CMD( + muxinfo, 1, 1, do_muxinfo, + "print CPM Multiplexing registers", + "" +); + +U_BOOT_CMD( + siinfo, 1, 1, do_siinfo, + "print Serial Interface (SI) registers", + "" +); + +U_BOOT_CMD( + mccinfo, 1, 1, do_mccinfo, + "print MCC registers", + "" +); + +#endif diff --git a/cmd/ini.c b/cmd/ini.c new file mode 100644 index 0000000..727fd1c --- /dev/null +++ b/cmd/ini.c @@ -0,0 +1,252 @@ +/* + * inih -- simple .INI file parser + * + * Copyright (c) 2009, Brush Technology + * Copyright (c) 2012: + * Joe Hershberger, National Instruments, joe.hershberger@ni.com + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Go to the project home page for more info: + * http://code.google.com/p/inih/ + */ + +#include +#include +#include +#include +#include + +#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 + setenv(name, value); + printf("ini: Imported %s as %s\n", name, value); + } + + /* success */ + return 1; +} + +static int do_ini(cmd_tbl_t *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 ? getenv("loadaddr") : argv[2], NULL, 16); + file_size = (size_t)simple_strtoul( + argc < 4 ? getenv("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/cmd/io.c b/cmd/io.c new file mode 100644 index 0000000..c59148f --- /dev/null +++ b/cmd/io.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * IO space access commands. + */ + +#include +#include +#include + +/* + * IO Display + * + * Syntax: + * iod{.b, .w, .l} {addr} + */ +int do_io_iod(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + ulong addr; + int size; + + if (argc != 2) + return CMD_RET_USAGE; + + size = cmd_get_data_size(argv[0], 4); + if (size < 0) + return 1; + + addr = simple_strtoul(argv[1], NULL, 16); + + printf("%04x: ", (u16) addr); + + if (size == 4) + printf("%08x\n", inl(addr)); + else if (size == 2) + printf("%04x\n", inw(addr)); + else + printf("%02x\n", inb(addr)); + + return 0; +} + +int do_io_iow(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + ulong addr, size, val; + + 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, 2, 0, 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/cmd/iotrace.c b/cmd/iotrace.c new file mode 100644 index 0000000..f54276d --- /dev/null +++ b/cmd/iotrace.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +static void do_print_stats(void) +{ + ulong start, size, offset, count; + + printf("iotrace is %sabled\n", iotrace_get_enabled() ? "en" : "dis"); + iotrace_get_buffer(&start, &size, &offset, &count); + printf("Start: %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 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; +} + +int do_iotrace(cmd_tbl_t *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 'p': + iotrace_set_enabled(0); + break; + case 'r': + iotrace_set_enabled(1); + break; + case 's': + do_print_stats(); + 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
- set iotrace buffer\n" + "iotrace pause - pause tracing\n" + "iotrace resume - resume tracing" +); diff --git a/cmd/irq.c b/cmd/irq.c new file mode 100644 index 0000000..02da450 --- /dev/null +++ b/cmd/irq.c @@ -0,0 +1,40 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +static int do_interrupts(cmd_tbl_t *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 (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + +U_BOOT_CMD( + irqinfo, 1, 1, do_irqinfo, + "print information about IRQs", + "" +); diff --git a/cmd/itest.c b/cmd/itest.c new file mode 100644 index 0000000..91ae5c2 --- /dev/null +++ b/cmd/itest.c @@ -0,0 +1,207 @@ +/* + * (C) Copyright 2003 + * Tait Electronics Limited, Christchurch, New Zealand + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * 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 +#include +#include +#include + +#include + +#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) { + puts("Failed to map physical memory\n"); + return 0; + } + switch (w) { + case 1: + l = (long)(*(unsigned char *)buf); + break; + case 2: + l = (long)(*(unsigned short *)buf); + break; + case 4: + l = (long)(*(unsigned long *)buf); + break; + } + unmap_physmem(buf, w); + return l; + } else { + l = simple_strtoul(s, NULL, 16); + } + + return 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 getenv((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(cmd_tbl_t *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: + value = binary_test (argv[2], argv[1], argv[3], w); + break; + case -2: + value = binary_test (argv[2], argv[1], argv[3], 0); + break; + case -1: + 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", + "[.b, .w, .l, .s] [*]value1 [*]value2" +); diff --git a/cmd/jffs2.c b/cmd/jffs2.c new file mode 100644 index 0000000..bce0983 --- /dev/null +++ b/cmd/jffs2.c @@ -0,0 +1,619 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Robert Schwebel, Pengutronix, + * + * (C) Copyright 2003 + * Kai-Uwe Bloem, Auerswald GmbH & Co KG, + * + * (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 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Three environment variables are used by the parsing routines: + * + * 'partition' - keeps current partition identifier + * + * partition := + * := ,part_num + * + * + * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping + * + * mtdids=[,,...] + * + * := = + * := 'nand'|'nor'|'onenand' + * := mtd device number, 0... + * := unique device tag used by linux kernel to find mtd device (mtd->name) + * + * + * 'mtdparts' - partition list + * + * mtdparts=mtdparts=[;...] + * + * := :[,...] + * := unique device tag used by linux kernel to find mtd device (mtd->name) + * := [@][][] + * := standard linux memsize OR '-' to denote all remaining space + * := partition start offset within the device + * := '(' NAME ')' + * := when set to 'ro' makes partition read-only (not used, passed to kernel) + * + * Notes: + * - each 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 +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_NAND) +#include +#include +#endif + +#if defined(CONFIG_CMD_ONENAND) +#include +#include +#include +#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) + if (num < CONFIG_SYS_MAX_NAND_DEVICE) { + *size = nand_info[num].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 := 'nand'|'nor'|'onenand', + * 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) + nand_info_t *nand; + + nand = &nand_info[id->num]; + + return nand->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(¤t_mtd_dev->link); + current_mtd_dev->num_parts = 1; + INIT_LIST_HEAD(¤t_mtd_dev->parts); + list_add(&part->link, ¤t_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *fsname; + char *filename; + int size; + struct part_info *part; + ulong offset = load_addr; + + /* pre-set Boot file name */ + if ((filename = getenv("bootfile")) == NULL) { + filename = "uImage"; + } + + if (argc == 2) { + filename = argv[1]; + } + if (argc == 3) { + offset = simple_strtoul(argv[1], NULL, 16); + 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); + setenv_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(cmd_tbl_t *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(cmd_tbl_t *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( + ls, 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/cmd/ldrinfo.c b/cmd/ldrinfo.c new file mode 100644 index 0000000..2aa56bd --- /dev/null +++ b/cmd/ldrinfo.c @@ -0,0 +1,192 @@ +/* + * U-boot - ldrinfo + * + * Copyright (c) 2010 Analog Devices Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include + +#include +#include + +static uint32_t ldrinfo_header(const void *addr) +{ + uint32_t skip = 0; + +#if defined(__ADSPBF561__) + /* BF56x has a 4 byte global header */ + uint32_t header, sign; + static const char * const spi_speed[] = { + "500K", "1M", "2M", "??", + }; + + memcpy(&header, addr, sizeof(header)); + + sign = (header & GFLAG_56X_SIGN_MASK) >> GFLAG_56X_SIGN_SHIFT; + printf("Header: %08X ( %s-bit-flash wait:%i hold:%i spi:%s %s)\n", + header, + (header & GFLAG_56X_16BIT_FLASH) ? "16" : "8", + (header & GFLAG_56X_WAIT_MASK) >> GFLAG_56X_WAIT_SHIFT, + (header & GFLAG_56X_HOLD_MASK) >> GFLAG_56X_HOLD_SHIFT, + spi_speed[(header & GFLAG_56X_SPI_MASK) >> GFLAG_56X_SPI_SHIFT], + sign == GFLAG_56X_SIGN_MAGIC ? "" : "!!hdrsign!! "); + + skip = 4; +#endif + + /* |Block @ 12345678: 12345678 12345678 12345678 12345678 | */ +#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ + defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ + defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) + printf(" Address Count Flags\n"); +#else + printf(" BCode Address Count Argument\n"); +#endif + + return skip; +} + +struct ldr_flag { + uint16_t flag; + const char *desc; +}; + +static uint32_t ldrinfo_block(const void *base_addr) +{ + uint32_t count; + + printf("Block @ %08X: ", (uint32_t)base_addr); + +#if defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ + defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ + defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) + + uint32_t addr, pval; + uint16_t flags; + int i; + static const struct ldr_flag ldr_flags[] = { + { BFLAG_53X_ZEROFILL, "zerofill" }, + { BFLAG_53X_RESVECT, "resvect" }, + { BFLAG_53X_INIT, "init" }, + { BFLAG_53X_IGNORE, "ignore" }, + { BFLAG_53X_COMPRESSED, "compressed"}, + { BFLAG_53X_FINAL, "final" }, + }; + + memcpy(&addr, base_addr, sizeof(addr)); + memcpy(&count, base_addr+4, sizeof(count)); + memcpy(&flags, base_addr+8, sizeof(flags)); + + printf("%08X %08X %04X ( ", addr, count, flags); + + for (i = 0; i < ARRAY_SIZE(ldr_flags); ++i) + if (flags & ldr_flags[i].flag) + printf("%s ", ldr_flags[i].desc); + + pval = (flags & BFLAG_53X_PFLAG_MASK) >> BFLAG_53X_PFLAG_SHIFT; + if (pval) + printf("gpio%i ", pval); + pval = (flags & BFLAG_53X_PPORT_MASK) >> BFLAG_53X_PPORT_SHIFT; + if (pval) + printf("port%c ", 'e' + pval); + + if (flags & BFLAG_53X_ZEROFILL) + count = 0; + if (flags & BFLAG_53X_FINAL) + count = 0; + else + count += sizeof(addr) + sizeof(count) + sizeof(flags); + +#else + + const uint8_t *raw8 = base_addr; + uint32_t bcode, addr, arg, sign, chk; + int i; + static const struct ldr_flag ldr_flags[] = { + { BFLAG_SAFE, "safe" }, + { BFLAG_AUX, "aux" }, + { BFLAG_FILL, "fill" }, + { BFLAG_QUICKBOOT, "quickboot" }, + { BFLAG_CALLBACK, "callback" }, + { BFLAG_INIT, "init" }, + { BFLAG_IGNORE, "ignore" }, + { BFLAG_INDIRECT, "indirect" }, + { BFLAG_FIRST, "first" }, + { BFLAG_FINAL, "final" }, + }; + + memcpy(&bcode, base_addr, sizeof(bcode)); + memcpy(&addr, base_addr+4, sizeof(addr)); + memcpy(&count, base_addr+8, sizeof(count)); + memcpy(&arg, base_addr+12, sizeof(arg)); + + printf("%08X %08X %08X %08X ( ", bcode, addr, count, arg); + + if (addr % 4) + printf("!!addralgn!! "); + if (count % 4) + printf("!!cntalgn!! "); + + sign = (bcode & BFLAG_HDRSIGN_MASK) >> BFLAG_HDRSIGN_SHIFT; + if (sign != BFLAG_HDRSIGN_MAGIC) + printf("!!hdrsign!! "); + + chk = 0; + for (i = 0; i < 16; ++i) + chk ^= raw8[i]; + if (chk) + printf("!!hdrchk!! "); + + printf("dma:%i ", bcode & BFLAG_DMACODE_MASK); + + for (i = 0; i < ARRAY_SIZE(ldr_flags); ++i) + if (bcode & ldr_flags[i].flag) + printf("%s ", ldr_flags[i].desc); + + if (bcode & BFLAG_FILL) + count = 0; + if (bcode & BFLAG_FINAL) + count = 0; + else + count += sizeof(bcode) + sizeof(addr) + sizeof(count) + sizeof(arg); + +#endif + + printf(")\n"); + + return count; +} + +static int do_ldrinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const void *addr; + uint32_t skip; + + /* Get the address */ + if (argc < 2) + addr = (void *)load_addr; + else + addr = (void *)simple_strtoul(argv[1], NULL, 16); + + /* Walk the LDR */ + addr += ldrinfo_header(addr); + do { + skip = ldrinfo_block(addr); + addr += skip; + } while (skip); + + return 0; +} + +U_BOOT_CMD( + ldrinfo, 2, 0, do_ldrinfo, + "validate ldr image in memory", + "[addr]\n" +); diff --git a/cmd/led.c b/cmd/led.c new file mode 100644 index 0000000..b0f1a61 --- /dev/null +++ b/cmd/led.c @@ -0,0 +1,186 @@ +/* + * (C) Copyright 2010 + * Jason Kridner + * + * Based on cmd_led.c patch from: + * http://www.mail-archive.com/u-boot@lists.denx.de/msg06873.html + * (C) Copyright 2008 + * Ulf Samuelsson + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +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_BOARD_SPECIFIC_LED +#ifdef STATUS_LED_BIT + { "0", STATUS_LED_BIT, NULL, NULL, NULL }, +#endif +#ifdef STATUS_LED_BIT1 + { "1", STATUS_LED_BIT1, NULL, NULL, NULL }, +#endif +#ifdef STATUS_LED_BIT2 + { "2", STATUS_LED_BIT2, NULL, NULL, NULL }, +#endif +#ifdef STATUS_LED_BIT3 + { "3", STATUS_LED_BIT3, NULL, NULL, NULL }, +#endif +#ifdef STATUS_LED_BIT4 + { "4", STATUS_LED_BIT4, NULL, NULL, NULL }, +#endif +#ifdef STATUS_LED_BIT5 + { "5", STATUS_LED_BIT5, NULL, NULL, NULL }, +#endif +#endif +#ifdef STATUS_LED_GREEN + { "green", STATUS_LED_GREEN, green_led_off, green_led_on, NULL }, +#endif +#ifdef STATUS_LED_YELLOW + { "yellow", STATUS_LED_YELLOW, yellow_led_off, yellow_led_on, NULL }, +#endif +#ifdef STATUS_LED_RED + { "red", STATUS_LED_RED, red_led_off, red_led_on, NULL }, +#endif +#ifdef STATUS_LED_BLUE + { "blue", STATUS_LED_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_led (cmd_tbl_t *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, + STATUS_LED_ON); + break; + case LED_OFF: + if (led_commands[i].off) + led_commands[i].off(); + else + __led_set(led_commands[i].mask, + STATUS_LED_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_led, + "[" +#ifdef CONFIG_BOARD_SPECIFIC_LED +#ifdef STATUS_LED_BIT + "0|" +#endif +#ifdef STATUS_LED_BIT1 + "1|" +#endif +#ifdef STATUS_LED_BIT2 + "2|" +#endif +#ifdef STATUS_LED_BIT3 + "3|" +#endif +#ifdef STATUS_LED_BIT4 + "4|" +#endif +#ifdef STATUS_LED_BIT5 + "5|" +#endif +#endif +#ifdef STATUS_LED_GREEN + "green|" +#endif +#ifdef STATUS_LED_YELLOW + "yellow|" +#endif +#ifdef STATUS_LED_RED + "red|" +#endif +#ifdef STATUS_LED_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/cmd/license.c b/cmd/license.c new file mode 100644 index 0000000..b07de72 --- /dev/null +++ b/cmd/license.c @@ -0,0 +1,40 @@ +/* + * (C) Copyright 2007 by OpenMoko, Inc. + * Author: Harald Welte + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +/* COPYING is currently 15951 bytes in size */ +#define LICENSE_MAX 20480 + +#include +#include +#include + +int do_license(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *tok, *dst = malloc(LICENSE_MAX); + unsigned long len = LICENSE_MAX; + + if (!dst) + return -1; + + if (gunzip(dst, LICENSE_MAX, license_gz, &len) != 0) { + printf("Error uncompressing license text\n"); + free(dst); + return -1; + } + puts(dst); + free(dst); + + return 0; +} + +U_BOOT_CMD( + license, 1, 1, do_license, + "print GPL license text", + "" +); diff --git a/cmd/load.c b/cmd/load.c new file mode 100644 index 0000000..0aa7937 --- /dev/null +++ b/cmd/load.c @@ -0,0 +1,1113 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Serial up- and download support + */ +#include +#include +#include +#include +#include +#include +#include + +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(cmd_tbl_t *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 + + if (((env_echo = getenv("loads_echo")) != NULL) && (*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 (getc() == '\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()) { + (void) getc(); + } + udelay(1000); + } + + if (addr == ~0) { + printf("## S-Record download aborted\n"); + rcode = 1; + } else { + printf("## Start Addr = 0x%08lX\n", addr); + 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 (getc() == 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; +#ifndef CONFIG_SYS_NO_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); + setenv_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 = getc(); /* 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 != getc) { + if (ctrlc()) { + return (-1); + } + } + } + + /* line too long - truncate */ + *p = '\0'; + return (p - buf); +} + +#if defined(CONFIG_CMD_SAVES) + +int do_save_serial (cmd_tbl_t *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 (getc() == '\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 (getc() == '\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 (getc() == 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(cmd_tbl_t *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 */ + if ((s = getenv("loadaddr")) != NULL) { + 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 (getc() == '\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) { + load_addr = 0; + printf("## Binary (kermit) download aborted\n"); + rcode = 1; + } else { + printf("## Start Addr = 0x%08lX\n", addr); + 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 (getc() == 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()) { + (void) getc(); + } + udelay(1000); + } + + flush_cache(offset, size); + + printf("## Total Size = 0x%08x = %d Bytes\n", size, size); + setenv_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 (getc ()) { + 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 = getc(); + if ((new_char & 0xE0) == 0) + goto packet_error; + sum += new_char & 0xff; + length = untochar(new_char); + /* get sequence number */ + new_char = getc(); + 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 = getc(); + 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 = getc(); + if ((new_char & 0xE0) == 0) + goto packet_error; + sum += new_char & 0xff; + len_hi = untochar(new_char); + new_char = getc(); + 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 = getc(); + 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 = getc(); + 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 = getc(); + 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 = getc(); + 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 (getc()); + 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; +#ifndef CONFIG_SYS_NO_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); + } + + } + } else { + printf("%s\n", xyzModem_error(err)); + } + + xyzModem_stream_close(&err); + xyzModem_stream_terminate(false, &getcxmodem); + + + flush_cache(offset, size); + + printf("## Total Size = 0x%08x = %d Bytes\n", size, size); + setenv_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)", + "[ off ] [ baud ]\n" + " - load binary file over serial line" + " with offset 'off' and baudrate 'baud'" +); + +U_BOOT_CMD( + loadx, 3, 0, do_load_serial_bin, + "load binary file over serial line (xmodem mode)", + "[ off ] [ baud ]\n" + " - load binary file over serial line" + " with offset 'off' and baudrate 'baud'" +); + +U_BOOT_CMD( + loady, 3, 0, do_load_serial_bin, + "load binary file over serial line (ymodem mode)", + "[ off ] [ baud ]\n" + " - load binary file over serial line" + " with offset 'off' and baudrate 'baud'" +); + +#endif /* CONFIG_CMD_LOADB */ + +/* -------------------------------------------------------------------- */ + +#if defined(CONFIG_CMD_HWFLOW) +int do_hwflow(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + extern int hwflow_onoff(int); + + if (argc == 2) { + if (strcmp(argv[1], "off") == 0) + hwflow_onoff(-1); + else + if (strcmp(argv[1], "on") == 0) + hwflow_onoff(1); + else + return CMD_RET_USAGE; + } + printf("RTS/CTS hardware flow control: %s\n", hwflow_onoff(0) ? "on" : "off"); + return 0; +} + +/* -------------------------------------------------------------------- */ + +U_BOOT_CMD( + hwflow, 2, 0, do_hwflow, + "turn RTS/CTS hardware flow control in serial line on/off", + "[on|off]" +); + +#endif /* CONFIG_CMD_HWFLOW */ diff --git a/cmd/log.c b/cmd/log.c new file mode 100644 index 0000000..873ee40 --- /dev/null +++ b/cmd/log.c @@ -0,0 +1,311 @@ +/* + * (C) Copyright 2002-2007 + * Detlev Zundel, DENX Software Engineering, dzu@denx.de. + * + * Code used from linux/kernel/printk.c + * Copyright (C) 1991, 1992 Linus Torvalds + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Comments: + * + * After relocating the code, the environment variable "loglevel" is + * copied to console_loglevel. The functionality is similar to the + * handling in the Linux kernel, i.e. messages logged with a priority + * less than console_loglevel are also output to stdout. + * + * If you want messages with the default level (e.g. POST messages) to + * appear on stdout also, make sure the environment variable + * "loglevel" is set at boot time to a number higher than + * default_message_loglevel below. + */ + +/* + * Logbuffer handling routines + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* Local prototypes */ +static void logbuff_putc(struct stdio_dev *dev, const char c); +static void logbuff_puts(struct stdio_dev *dev, const char *s); +static int logbuff_printk(const char *line); + +static char buf[1024]; + +/* This combination will not print messages with the default loglevel */ +static unsigned console_loglevel = 3; +static unsigned default_message_loglevel = 4; +static unsigned log_version = 1; +#ifdef CONFIG_ALT_LB_ADDR +static volatile logbuff_t *log; +#else +static logbuff_t *log; +#endif +static char *lbuf; + +unsigned long __logbuffer_base(void) +{ + return CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - LOGBUFF_LEN; +} +unsigned long logbuffer_base(void) +__attribute__((weak, alias("__logbuffer_base"))); + +void logbuff_init_ptrs(void) +{ + unsigned long tag, post_word; + char *s; + +#ifdef CONFIG_ALT_LB_ADDR + log = (logbuff_t *)CONFIG_ALT_LH_ADDR; + lbuf = (char *)CONFIG_ALT_LB_ADDR; +#else + log = (logbuff_t *)(logbuffer_base()) - 1; + lbuf = (char *)log->buf; +#endif + + /* Set up log version */ + if ((s = getenv ("logversion")) != NULL) + log_version = (int)simple_strtoul(s, NULL, 10); + + if (log_version == 2) + tag = log->v2.tag; + else + tag = log->v1.tag; + post_word = post_word_load(); +#ifdef CONFIG_POST + /* The post routines have setup the word so we can simply test it */ + if (tag != LOGBUFF_MAGIC || (post_word & POST_COLDBOOT)) + logbuff_reset(); +#else + /* No post routines, so we do our own checking */ + if (tag != LOGBUFF_MAGIC || post_word != LOGBUFF_MAGIC) { + logbuff_reset (); + post_word_store (LOGBUFF_MAGIC); + } +#endif + if (log_version == 2 && (long)log->v2.start > (long)log->v2.con) + log->v2.start = log->v2.con; + + /* Initialize default loglevel if present */ + if ((s = getenv ("loglevel")) != NULL) + console_loglevel = (int)simple_strtoul(s, NULL, 10); + + gd->flags |= GD_FLG_LOGINIT; +} + +void logbuff_reset(void) +{ +#ifndef CONFIG_ALT_LB_ADDR + memset(log, 0, sizeof(logbuff_t)); +#endif + if (log_version == 2) { + log->v2.tag = LOGBUFF_MAGIC; +#ifdef CONFIG_ALT_LB_ADDR + log->v2.start = 0; + log->v2.con = 0; + log->v2.end = 0; + log->v2.chars = 0; +#endif + } else { + log->v1.tag = LOGBUFF_MAGIC; +#ifdef CONFIG_ALT_LB_ADDR + log->v1.dummy = 0; + log->v1.start = 0; + log->v1.size = 0; + log->v1.chars = 0; +#endif + } +} + +int drv_logbuff_init(void) +{ + struct stdio_dev logdev; + int rc; + + /* Device initialization */ + memset (&logdev, 0, sizeof (logdev)); + + strcpy (logdev.name, "logbuff"); + logdev.ext = 0; /* No extensions */ + logdev.flags = DEV_FLAGS_OUTPUT; /* Output only */ + logdev.putc = logbuff_putc; /* 'putc' function */ + logdev.puts = logbuff_puts; /* 'puts' function */ + + rc = stdio_register(&logdev); + + return (rc == 0) ? 1 : rc; +} + +static void logbuff_putc(struct stdio_dev *dev, const char c) +{ + char buf[2]; + buf[0] = c; + buf[1] = '\0'; + logbuff_printk(buf); +} + +static void logbuff_puts(struct stdio_dev *dev, const char *s) +{ + logbuff_printk (s); +} + +void logbuff_log(char *msg) +{ + if ((gd->flags & GD_FLG_LOGINIT)) { + logbuff_printk(msg); + } else { + /* + * Can happen only for pre-relocated errors as logging + * at that stage should be disabled + */ + puts (msg); + } +} + +/* + * Subroutine: do_log + * + * Description: Handler for 'log' command.. + * + * Inputs: argv[1] contains the subcommand + * + * Return: None + * + */ +int do_log(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct stdio_dev *sdev = NULL; + char *s; + unsigned long i, start, size; + + if (strcmp(argv[1], "append") == 0) { + /* Log concatenation of all arguments separated by spaces */ + for (i = 2; i < argc; i++) { + logbuff_printk(argv[i]); + logbuff_putc(sdev, (i < argc - 1) ? ' ' : '\n'); + } + return 0; + } + + switch (argc) { + + case 2: + if (strcmp(argv[1], "show") == 0) { + if (log_version == 2) { + start = log->v2.start; + size = log->v2.end - log->v2.start; + } else { + start = log->v1.start; + size = log->v1.size; + } + if (size > LOGBUFF_LEN) + size = LOGBUFF_LEN; + for (i = 0; i < size; i++) { + s = lbuf + ((start + i) & LOGBUFF_MASK); + putc(*s); + } + return 0; + } else if (strcmp(argv[1], "reset") == 0) { + logbuff_reset(); + return 0; + } else if (strcmp(argv[1], "info") == 0) { + printf("Logbuffer at %08lx\n", (unsigned long)lbuf); + if (log_version == 2) { + printf("log_start = %08lx\n", + log->v2.start); + printf("log_end = %08lx\n", log->v2.end); + printf("log_con = %08lx\n", log->v2.con); + printf("logged_chars = %08lx\n", + log->v2.chars); + } + else { + printf("log_start = %08lx\n", + log->v1.start); + printf("log_size = %08lx\n", + log->v1.size); + printf("logged_chars = %08lx\n", + log->v1.chars); + } + return 0; + } + return CMD_RET_USAGE; + + default: + return CMD_RET_USAGE; + } +} + +U_BOOT_CMD( + log, 255, 1, do_log, + "manipulate logbuffer", + "info - show pointer details\n" + "log reset - clear contents\n" + "log show - show contents\n" + "log append - append to the logbuffer" +); + +static int logbuff_printk(const char *line) +{ + int i; + char *msg, *p, *buf_end; + int line_feed; + static signed char msg_level = -1; + + strcpy(buf + 3, line); + i = strlen(line); + buf_end = buf + 3 + i; + for (p = buf + 3; p < buf_end; p++) { + msg = p; + if (msg_level < 0) { + if ( + p[0] != '<' || + p[1] < '0' || + p[1] > '7' || + p[2] != '>' + ) { + p -= 3; + p[0] = '<'; + p[1] = default_message_loglevel + '0'; + p[2] = '>'; + } else { + msg += 3; + } + msg_level = p[1] - '0'; + } + line_feed = 0; + for (; p < buf_end; p++) { + if (log_version == 2) { + lbuf[log->v2.end & LOGBUFF_MASK] = *p; + log->v2.end++; + if (log->v2.end - log->v2.start > LOGBUFF_LEN) + log->v2.start++; + log->v2.chars++; + } else { + lbuf[(log->v1.start + log->v1.size) & + LOGBUFF_MASK] = *p; + if (log->v1.size < LOGBUFF_LEN) + log->v1.size++; + else + log->v1.start++; + log->v1.chars++; + } + if (*p == '\n') { + line_feed = 1; + break; + } + } + if (msg_level < console_loglevel) { + printf("%s", msg); + } + if (line_feed) + msg_level = -1; + } + return i; +} diff --git a/cmd/lzmadec.c b/cmd/lzmadec.c new file mode 100644 index 0000000..1ad9ed6 --- /dev/null +++ b/cmd/lzmadec.c @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2013 Patrice Bouchand + * 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. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#include + +static int do_lzmadec(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + unsigned long src, dst; + unsigned long 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 = 0x%lX\n", src_len, src_len); + setenv_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/cmd/mac.c b/cmd/mac.c new file mode 100644 index 0000000..52d3ba0 --- /dev/null +++ b/cmd/mac.c @@ -0,0 +1,33 @@ +/* + * Copyright 2006 Freescale Semiconductor + * York Sun (yorksun@freescale.com) + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +extern int do_mac(cmd_tbl_t *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|0|1|2|3|4|5|6|7]\n" + "mac read\n" + " - read EEPROM content into memory\n" + "mac save\n" + " - save to the EEPROM\n" + "mac id\n" + " - program system id\n" + "mac num\n" + " - program system serial number\n" + "mac errata\n" + " - program errata data\n" + "mac date\n" + " - program date\n" + "mac ports\n" + " - program the number of ports\n" + "mac X\n" + " - program the MAC address for port X [X=0...7]" +); diff --git a/cmd/md5sum.c b/cmd/md5sum.c new file mode 100644 index 0000000..23bb81e --- /dev/null +++ b/cmd/md5sum.c @@ -0,0 +1,183 @@ +/* + * (C) Copyright 2011 + * Joe Hershberger, National Instruments, joe.hershberger@ni.com + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +/* + * 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; + } + setenv(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 = getenv(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(cmd_tbl_t *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(cmd_tbl_t *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/cmd/mdio.c b/cmd/mdio.c new file mode 100644 index 0000000..fb13d05 --- /dev/null +++ b/cmd/mdio.c @@ -0,0 +1,313 @@ +/* + * (C) Copyright 2011 Freescale Semiconductor, Inc + * Andy Fleming + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * MDIO Commands + */ + +#include +#include +#include +#include + + +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, 0); + if (end == input) + return -1; + + if ((*end == '-') && *(++end)) + *phi = simple_strtol(end, NULL, 0); + else if (*end == '\0') + *phi = *plo; + else + return -1; + + return 0; +} + +static int mdio_write_ranges(struct phy_device *phydev, struct mii_dev *bus, + int addrlo, + int addrhi, int devadlo, int devadhi, + int reglo, int reghi, unsigned short data, + int extended) +{ + int addr, devad, reg; + int err = 0; + + for (addr = addrlo; addr <= addrhi; addr++) { + for (devad = devadlo; devad <= devadhi; devad++) { + for (reg = reglo; reg <= reghi; reg++) { + if (!extended) + err = bus->write(bus, addr, 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 phy_device *phydev, struct mii_dev *bus, + int addrlo, + int addrhi, int devadlo, int devadhi, + int reglo, int reghi, int extended) +{ + int addr, devad, reg; + + printf("Reading from bus %s\n", bus->name); + for (addr = addrlo; addr <= addrhi; addr++) { + printf("PHY at address %d:\n", addr); + + for (devad = devadlo; devad <= devadhi; devad++) { + for (reg = reglo; reg <= reghi; reg++) { + int val; + + if (!extended) + val = bus->read(bus, addr, 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(cmd_tbl_t *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; + + /* + * 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 -1; + } + + if (!phydev->drv || + (!phydev->drv->writeext && (op[0] == 'w')) || + (!phydev->drv->readext && (op[0] == 'r'))) { + puts("PHY does not have extended functions\n"); + return -1; + } + } + } + + switch (op[0]) { + case 'w': + if (pos > 1) + data = simple_strtoul(argv[pos--], NULL, 16); + case 'r': + if (pos > 1) + if (extract_reg_range(argv[pos--], &devadlo, &devadhi, + ®lo, ®hi)) + return -1; + + default: + if (pos > 1) + if (extract_phy_range(&(argv[2]), pos - 1, &bus, + &phydev, &addrlo, &addrhi)) + return -1; + + break; + } + + 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(phydev, bus, addrlo, addrhi, devadlo, devadhi, + reglo, reghi, data, extended); + break; + + case 'r': + mdio_read_ranges(phydev, 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 [.] - " + "read PHY's register at .\n" + "mdio write [.] - " + "write PHY's register at .\n" + "mdio rx [.] - " + "read PHY's extended register at .\n" + "mdio wx [.] - " + "write PHY's extended register at .\n" + " may be:\n" + " \n" + " \n" + " \n" + " , and may be ranges, e.g. 1-5.4-0x1f.\n" +); diff --git a/cmd/mem.c b/cmd/mem.c new file mode 100644 index 0000000..efa3929 --- /dev/null +++ b/cmd/mem.c @@ -0,0 +1,1410 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Memory Functions + * + * Copied from FADS ROM, Dan Malek (dmalek@jlc.net) + */ + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HAS_DATAFLASH +#include +#endif +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_MEMTEST_SCRATCH +#define CONFIG_SYS_MEMTEST_SCRATCH 0 +#endif + +static int mod_mem(cmd_tbl_t *, 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; + +/* Memory Display + * + * Syntax: + * md{.b, .w, .l, .q} {addr} {len} + */ +#define DISP_LINE_LEN 16 +static int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + ulong addr, length; +#if defined(CONFIG_HAS_DATAFLASH) + ulong nbytes, linebytes; +#endif + 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); + } + +#if defined(CONFIG_HAS_DATAFLASH) + /* Print the lines. + * + * We buffer all read data, so we can make sure data is read only + * once, and all accesses are with the specified bus width. + */ + nbytes = length * size; + do { + char linebuf[DISP_LINE_LEN]; + void* p; + linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes; + + rc = read_dataflash(addr, (linebytes/size)*size, linebuf); + p = (rc == DATAFLASH_OK) ? linebuf : (void*)addr; + print_buffer(addr, p, size, linebytes/size, DISP_LINE_LEN/size); + + nbytes -= linebytes; + addr += linebytes; + if (ctrlc()) { + rc = 1; + break; + } + } while (nbytes > 0); +#else + +# if defined(CONFIG_BLACKFIN) + /* See if we're trying to display L1 inst */ + if (addr_bfin_on_chip_mem(addr)) { + char linebuf[DISP_LINE_LEN]; + ulong linebytes, nbytes = length * size; + do { + linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes; + memcpy(linebuf, (void *)addr, linebytes); + print_buffer(addr, linebuf, size, linebytes/size, DISP_LINE_LEN/size); + + nbytes -= linebytes; + addr += linebytes; + if (ctrlc()) { + rc = 1; + break; + } + } while (nbytes > 0); + } else +# endif + + { + ulong bytes = size * length; + const void *buf = map_sysmem(addr, bytes); + + /* Print the lines. */ + print_buffer(addr, buf, size, length, DISP_LINE_LEN / size); + addr += bytes; + unmap_sysmem(buf); + } +#endif + + dp_last_addr = addr; + dp_last_length = length; + dp_last_size = size; + return (rc); +} + +static int do_mem_mm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return mod_mem (cmdtp, 1, flag, argc, argv); +} +static int do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return mod_mem (cmdtp, 0, flag, argc, argv); +} + +static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + u64 writeval; +#else + ulong writeval; +#endif + 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. + */ +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + writeval = simple_strtoull(argv[2], NULL, 16); +#else + writeval = simple_strtoul(argv[2], NULL, 16); +#endif + + /* 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; +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + else if (size == 8) + *((u64 *)buf) = (u64)writeval; +#endif + else if (size == 2) + *((u16 *)buf) = (u16)writeval; + else + *((u8 *)buf) = (u8)writeval; + buf += size; + } + unmap_sysmem(start); + return 0; +} + +#ifdef CONFIG_MX_CYCLIC +static int do_mem_mdc(cmd_tbl_t *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 ms... */ + for (i=0; i ms... */ + for (i=0; i 0) { + if (size == 4) + *((u32 *)buf) = *((u32 *)src); +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + else if (size == 8) + *((u64 *)buf) = *((u64 *)src); +#endif + else if (size == 2) + *((u16 *)buf) = *((u16 *)src); + else + *((u8 *)buf) = *((u8 *)src); + src += size; + buf += size; + + /* reset watchdog from time to time */ + if ((count % (64 << 10)) == 0) + WATCHDOG_RESET(); + } + unmap_sysmem(buf); + unmap_sysmem(src); + + return 0; +} + +static int do_mem_base(cmd_tbl_t *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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + ulong addr, length, i, bytes; + int size; +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + volatile u64 *llp; +#endif + 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) { +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + if (size == 8) { + llp = (u64 *)buf; + for (;;) + i = *llp; + } +#endif + if (size == 4) { + longp = (u32 *)buf; + for (;;) + i = *longp; + } + if (size == 2) { + shortp = (u16 *)buf; + for (;;) + i = *shortp; + } + cp = (u8 *)buf; + for (;;) + i = *cp; + } + +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + if (size == 8) { + for (;;) { + llp = (u64 *)buf; + i = length; + while (i-- > 0) + *llp++; + } + } +#endif + 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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + ulong addr, length, i, bytes; + int size; +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + volatile u64 *llp; + u64 data; +#else + ulong data; +#endif + 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 */ +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + data = simple_strtoull(argv[3], NULL, 16); +#else + data = simple_strtoul(argv[3], NULL, 16); +#endif + + 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) { +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + if (size == 8) { + llp = (u64 *)buf; + for (;;) + *llp = data; + } +#endif + if (size == 4) { + longp = (u32 *)buf; + for (;;) + *longp = data; + } + if (size == 2) { + shortp = (u16 *)buf; + for (;;) + *shortp = data; + } + cp = (u8 *)buf; + for (;;) + *cp = data; + } + +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + if (size == 8) { + for (;;) { + llp = (u64 *)buf; + i = length; + while (i-- > 0) + *llp++ = data; + } + } +#endif + 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 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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + ulong start, end; + vu_long *buf, *dummy; + ulong iteration_limit = 0; + int ret; + ulong errs = 0; /* number of errors, or -1 if interrupted */ + ulong pattern = 0; + int iteration; +#if defined(CONFIG_SYS_ALT_MEMTEST) + const int alt_test = 1; +#else + const int alt_test = 0; +#endif + + 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 %08x ... %08x:\n", (uint)start, (uint)end); + debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__, + start, end); + + buf = map_sysmem(start, end - start); + dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long)); + for (iteration = 0; + !iteration_limit || iteration < iteration_limit; + iteration++) { + if (ctrlc()) { + errs = -1UL; + break; + } + + printf("Iteration: %6d\r", iteration + 1); + debug("\n"); + if (alt_test) { + errs = mem_test_alt(buf, start, end, dummy); + } else { + errs = mem_test_quick(buf, start, end, pattern, + iteration); + } + if (errs == -1UL) + break; + } + + /* + * Work-around for eldk-4.2 which gives this warning if we try to + * case in the unmap_sysmem() call: + * warning: initialization discards qualifiers from pointer target type + */ + { + void *vbuf = (void *)buf; + void *vdummy = (void *)dummy; + + unmap_sysmem(vbuf); + unmap_sysmem(vdummy); + } + + if (errs == -1UL) { + /* Memory test was aborted - write a newline to finish off */ + putc('\n'); + ret = 1; + } else { + printf("Tested %d iteration(s) with %lu errors.\n", + iteration, errs); + ret = errs != 0; + } + + return ret; +} +#endif /* CONFIG_CMD_MEMTEST */ + +/* Modify memory. + * + * Syntax: + * mm{.b, .w, .l, .q} {addr} + * nm{.b, .w, .l, .q} {addr} + */ +static int +mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) +{ + ulong addr; +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + u64 i; +#else + ulong i; +#endif + 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; + } + +#ifdef CONFIG_HAS_DATAFLASH + if (addr_dataflash(addr)){ + puts ("Can't modify DataFlash in place. Use cp instead.\n\r"); + return 0; + } +#endif + +#ifdef CONFIG_BLACKFIN + if (addr_bfin_on_chip_mem(addr)) { + puts ("Can't modify L1 instruction in place. Use cp instead.\n\r"); + return 0; + } +#endif + + /* 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)); +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + else if (size == 8) + printf(" %016" PRIx64, *((u64 *)ptr)); +#endif + else if (size == 2) + printf(" %04x", *((u16 *)ptr)); + else + printf(" %02x", *((u8 *)ptr)); + + nbytes = cli_readline(" ? "); + if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { + /* 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; +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + i = simple_strtoull(console_buffer, &endp, 16); +#else + i = simple_strtoul(console_buffer, &endp, 16); +#endif + nbytes = endp - console_buffer; + if (nbytes) { + /* good enough to not time out + */ + bootretry_reset_cmd_timeout(); + if (size == 4) + *((u32 *)ptr) = i; +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + else if (size == 8) + *((u64 *)ptr) = i; +#endif + 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(cmd_tbl_t *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_HASH_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 + +/**************************************************/ +U_BOOT_CMD( + md, 3, 1, do_mem_md, + "memory display", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] address [# of objects]" +#else + "[.b, .w, .l] address [# of objects]" +#endif +); + + +U_BOOT_CMD( + mm, 2, 1, do_mem_mm, + "memory modify (auto-incrementing address)", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] address" +#else + "[.b, .w, .l] address" +#endif +); + + +U_BOOT_CMD( + nm, 2, 1, do_mem_nm, + "memory modify (constant address)", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] address" +#else + "[.b, .w, .l] address" +#endif +); + +U_BOOT_CMD( + mw, 4, 1, do_mem_mw, + "memory write (fill)", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] address value [count]" +#else + "[.b, .w, .l] address value [count]" +#endif +); + +U_BOOT_CMD( + cp, 4, 1, do_mem_cp, + "memory copy", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] source target count" +#else + "[.b, .w, .l] source target count" +#endif +); + +U_BOOT_CMD( + cmp, 4, 1, do_mem_cmp, + "memory compare", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] addr1 addr2 count" +#else + "[.b, .w, .l] addr1 addr2 count" +#endif +); + +#ifdef CONFIG_CMD_CRC32 + +#ifndef CONFIG_HASH_VERIFY + +U_BOOT_CMD( + crc32, 4, 1, do_mem_crc, + "checksum calculation", + "address count [addr]\n - compute CRC32 checksum [save at addr]" +); + +#else /* CONFIG_HASH_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_HASH_VERIFY */ + +#endif + +#ifdef CONFIG_CMD_MEMINFO +__weak void board_show_dram(phys_size_t size) +{ + puts("DRAM: "); + print_size(size, "\n"); +} + +static int do_mem_info(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + board_show_dram(gd->ram_size); + + 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", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] address number_of_objects" +#else + "[.b, .w, .l] address number_of_objects" +#endif +); + +#ifdef CONFIG_LOOPW +U_BOOT_CMD( + loopw, 4, 1, do_mem_loopw, + "infinite write loop on address range", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] address number_of_objects data_to_write" +#else + "[.b, .w, .l] address number_of_objects data_to_write" +#endif +); +#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_MX_CYCLIC +U_BOOT_CMD( + mdc, 4, 1, do_mem_mdc, + "memory display cyclic", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] address count delay(ms)" +#else + "[.b, .w, .l] address count delay(ms)" +#endif +); + +U_BOOT_CMD( + mwc, 4, 1, do_mem_mwc, + "memory write cyclic", +#ifdef CONFIG_SYS_SUPPORT_64BIT_DATA + "[.b, .w, .l, .q] address value delay(ms)" +#else + "[.b, .w, .l] address value delay(ms)" +#endif +); +#endif /* CONFIG_MX_CYCLIC */ + +#ifdef CONFIG_CMD_MEMINFO +U_BOOT_CMD( + meminfo, 3, 1, do_mem_info, + "display memory information", + "" +); +#endif diff --git a/cmd/mfsl.c b/cmd/mfsl.c new file mode 100644 index 0000000..e8e8e3c --- /dev/null +++ b/cmd/mfsl.c @@ -0,0 +1,388 @@ +/* + * (C) Copyright 2007 Michal Simek + * + * Michal SIMEK + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Microblaze FSL support + */ + +#include +#include +#include +#include + +int do_frd (cmd_tbl_t * 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 (cmd_tbl_t * 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 (cmd_tbl_t * 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/cmd/mii.c b/cmd/mii.c new file mode 100644 index 0000000..7ef7532 --- /dev/null +++ b/cmd/mii.c @@ -0,0 +1,470 @@ +/* + * (C) Copyright 2001 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * MII Utilities + */ + +#include +#include +#include + +typedef struct _MII_reg_desc_t { + ushort regno; + char * name; +} MII_reg_desc_t; + +static const MII_reg_desc_t reg_0_5_desc_tbl[] = { + { MII_BMCR, "PHY control register" }, + { MII_BMSR, "PHY status register" }, + { MII_PHYSID1, "PHY ID 1 register" }, + { MII_PHYSID2, "PHY ID 2 register" }, + { MII_ADVERTISE, "Autonegotiation advertisement register" }, + { MII_LPA, "Autonegotiation partner abilities register" }, +}; + +typedef struct _MII_field_desc_t { + ushort hi; + ushort lo; + ushort mask; + 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, "xxx to do" }, +}; + +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, "xxx to do" }, +}; +typedef struct _MII_field_desc_and_len_t { + const MII_field_desc_t *pdesc; + ushort len; +} MII_field_desc_and_len_t; + +static const MII_field_desc_and_len_t desc_and_len_tbl[] = { + { reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl) }, + { reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl) }, + { reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl) }, + { reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl) }, + { reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl) }, + { reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl) }, +}; + +static void dump_reg( + ushort regval, + const MII_reg_desc_t *prd, + const MII_field_desc_and_len_t *pdl); + +static int special_field( + ushort regno, + const MII_field_desc_t *pdesc, + ushort regval); + +static void MII_dump_0_to_5( + ushort regvals[6], + uchar reglo, + uchar reghi) +{ + ulong i; + + for (i = 0; i < 6; i++) { + if ((reglo <= i) && (i <= reghi)) + dump_reg(regvals[i], ®_0_5_desc_tbl[i], + &desc_and_len_tbl[i]); + } +} + +static void dump_reg( + ushort regval, + const MII_reg_desc_t *prd, + const MII_field_desc_and_len_t *pdl) +{ + 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 < pdl->len; i++) { + pdesc = &pdl->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)) { + } + else { + if (pdesc->hi == pdesc->lo) + printf("%2u ", pdesc->lo); + else + printf("%2u-%2u", pdesc->hi, pdesc->lo); + printf(" = %5u %s", + (regval & mask_in_place) >> pdesc->lo, + pdesc->name); + } + printf("\n"); + + } + printf("\n"); +} + +/* Special fields: +** 0.6,13 +** 0.8 +** 2.15-0 +** 3.15-0 +** 4.4-0 +** 5.4-0 +*/ + +static int special_field( + ushort regno, + const MII_field_desc_t *pdesc, + ushort regval) +{ + 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)) { + printf("%2u = %5u duplex = %s", + pdesc->lo, + (regval >> pdesc->lo) & 1, + ((regval >> pdesc->lo) & 1) ? "full" : "half"); + return 1; + } + + else if ((regno == MII_ADVERTISE) && (pdesc->lo == 0)) { + ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask; + printf("%2u-%2u = %5u selector = %s", + pdesc->hi, pdesc->lo, sel_bits, + sel_bits == PHY_ANLPAR_PSB_802_3 ? + "IEEE 802.3" : + sel_bits == PHY_ANLPAR_PSB_802_9 ? + "IEEE 802.9 ISLAN-16T" : + "???"); + return 1; + } + + else if ((regno == MII_LPA) && (pdesc->lo == 0)) { + ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask; + printf("%2u-%2u = %u selector = %s", + pdesc->hi, pdesc->lo, sel_bits, + sel_bits == PHY_ANLPAR_PSB_802_3 ? + "IEEE 802.3" : + 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(cmd_tbl_t *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], ®lo, ®hi); + if (argc >= 5) + data = simple_strtoul(argv[4], NULL, 16); + if (argc >= 6) + mask = simple_strtoul(argv[5], NULL, 16); + } + + if (addrhi > 31) { + 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[6]; + int ok = 1; + if ((reglo > 5) || (reghi > 5)) { + printf( + "The MII dump command only formats the " + "standard MII registers, 0-5.\n"); + return 1; + } + for (addr = addrlo; addr <= addrhi; addr++) { + for (reg = reglo; reg < reghi + 1; reg++) { + if (miiphy_read(devname, addr, reg, ®s[reg]) != 0) { + ok = 0; + printf( + "Error reading from the PHY addr=%02x reg=%02x\n", + addr, reg); + rcode = 1; + } + } + if (ok) + MII_dump_0_to_5(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 - set current device\n" + "mii info - display MII PHY info\n" + "mii read - read MII PHY register \n" + "mii write - write MII PHY register \n" + "mii modify - modify MII PHY register \n" + " updating bits identified in \n" + "mii dump - pretty-print (0-5 only)\n" + "Addr and/or reg may be ranges, e.g. 2-7." +); diff --git a/cmd/misc.c b/cmd/misc.c new file mode 100644 index 0000000..39d8683 --- /dev/null +++ b/cmd/misc.c @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Misc functions + */ +#include +#include +#include + +static int do_sleep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + ulong start = get_timer(0); + ulong delay; + + if (argc != 2) + return CMD_RET_USAGE; + + delay = simple_strtoul(argv[1], NULL, 10) * CONFIG_SYS_HZ; + + while (get_timer(start) < delay) { + if (ctrlc()) + return (-1); + + 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_ !!!)" +); + +#ifdef CONFIG_CMD_TIMER +static int do_timer(cmd_tbl_t *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'." +); +#endif diff --git a/cmd/mmc.c b/cmd/mmc.c new file mode 100644 index 0000000..1c7156f --- /dev/null +++ b/cmd/mmc.c @@ -0,0 +1,882 @@ +/* + * (C) Copyright 2003 + * Kyle Harris, kharris@nexus-tech.net + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static int curr_device = -1; +#ifndef CONFIG_GENERIC_MMC +int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int dev; + + if (argc < 2) + return CMD_RET_USAGE; + + if (strcmp(argv[1], "init") == 0) { + if (argc == 2) { + if (curr_device < 0) + dev = 1; + else + dev = curr_device; + } else if (argc == 3) { + dev = (int)simple_strtoul(argv[2], NULL, 10); + } else { + return CMD_RET_USAGE; + } + + if (mmc_legacy_init(dev) != 0) { + puts("No MMC card found\n"); + return 1; + } + + curr_device = dev; + printf("mmc%d is available\n", curr_device); + } else if (strcmp(argv[1], "device") == 0) { + if (argc == 2) { + if (curr_device < 0) { + puts("No MMC device available\n"); + return 1; + } + } else if (argc == 3) { + dev = (int)simple_strtoul(argv[2], NULL, 10); + +#ifdef CONFIG_SYS_MMC_SET_DEV + if (mmc_set_dev(dev) != 0) + return 1; +#endif + curr_device = dev; + } else { + return CMD_RET_USAGE; + } + + printf("mmc%d is current device\n", curr_device); + } else { + return CMD_RET_USAGE; + } + + return 0; +} + +U_BOOT_CMD( + mmc, 3, 1, do_mmc, + "MMC sub-system", + "init [dev] - init MMC sub system\n" + "mmc device [dev] - show or set current device" +); +#else /* !CONFIG_GENERIC_MMC */ + +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("Tran Speed: %d\n", mmc->tran_speed); + 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" : ""); + + puts("Erase Group Size: "); + print_size(((u64)mmc->erase_grp_size) << 9, "\n"); + + 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); + + puts("HC WP Group Size: "); + print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n"); + + 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'); + } + } + } +} +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 (force_init) + mmc->has_init = 0; + if (mmc_init(mmc)) + return NULL; + return mmc; +} +static int do_mmcinfo(cmd_tbl_t *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; +} + +#ifdef CONFIG_SUPPORT_EMMC_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? "); + if (confirm_yesno()) + return 1; + + puts("Authentication key programming aborted\n"); + return 0; +} +static int do_mmcrpmb_key(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + cmd_tbl_t *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 && !cp->repeatable) + 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 a 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 */ + original_part = mmc->block_dev.part_num; + if (mmc_select_hwpart(curr_device, MMC_PART_RPMB) != 0) + return CMD_RET_FAILURE; + ret = cp->cmd(cmdtp, flag, argc, argv); + + /* Return to original partition */ + if (mmc_select_hwpart(curr_device, original_part) != 0) + return CMD_RET_FAILURE; + return ret; +} +#endif + +static int do_mmc_read(cmd_tbl_t *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 = mmc->block_dev.block_read(&mmc->block_dev, blk, cnt, addr); + /* flush cache after read */ + flush_cache((ulong)addr, cnt * 512); /* FIXME */ + printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); + + return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; +} +static int do_mmc_write(cmd_tbl_t *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 = mmc->block_dev.block_write(&mmc->block_dev, 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(cmd_tbl_t *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 = mmc->block_dev.block_erase(&mmc->block_dev, blk, cnt); + printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR"); + + return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE; +} +static int do_mmc_rescan(cmd_tbl_t *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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + block_dev_desc_t *mmc_dev; + struct mmc *mmc; + + mmc = init_mmc_device(curr_device, false); + if (!mmc) + return CMD_RET_FAILURE; + + mmc_dev = mmc_get_dev(curr_device); + if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) { + print_part(mmc_dev); + return CMD_RET_SUCCESS; + } + + puts("get mmc type error!\n"); + return CMD_RET_FAILURE; +} +static int do_mmc_dev(cmd_tbl_t *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 = mmc_select_hwpart(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->block_dev.hwpart); + + return CMD_RET_SUCCESS; +} +static int do_mmc_list(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + print_mmc_devices('\n'); + return CMD_RET_SUCCESS; +} + +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(cmd_tbl_t *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; + } +} + +#ifdef CONFIG_SUPPORT_EMMC_BOOT +static int do_mmc_bootbus(cmd_tbl_t *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; + } + + /* acknowledge to be sent during boot operation */ + return mmc_set_boot_bus_width(mmc, width, reset, mode); +} +static int do_mmc_boot_resize(cmd_tbl_t *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 a 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 do_mmc_partconf(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + int dev; + struct mmc *mmc; + u8 ack, part_num, access; + + if (argc != 5) + return CMD_RET_USAGE; + + dev = simple_strtoul(argv[1], NULL, 10); + ack = simple_strtoul(argv[2], NULL, 10); + part_num = simple_strtoul(argv[3], NULL, 10); + access = simple_strtoul(argv[4], 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; + } + + /* acknowledge to be sent during boot operation */ + return mmc_set_part_conf(mmc, ack, part_num, access); +} +static int do_mmc_rst_func(cmd_tbl_t *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(cmd_tbl_t *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[2], 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; +} + +static cmd_tbl_t 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(write, 4, 0, do_mmc_write, "", ""), + U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""), + 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, "", ""), + U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""), +#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 +#ifdef CONFIG_SUPPORT_EMMC_RPMB + U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), +#endif + U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), +}; + +static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *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 && !cp->repeatable) + 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" + "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 hwpartition [args...] - does hardware partitioning\n" + " arguments (sizes in 512-byte blocks):\n" + " [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n" + " [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n" + " [check|set|complete] - 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" +#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 \n" + " - Change sizes of boot and RPMB partitions of specified device\n" + "mmc partconf dev boot_ack boot_partition partition_access\n" + " - Change the bits of the PARTITION_CONFIG field of the specified device\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 +#ifdef CONFIG_SUPPORT_EMMC_RPMB + "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n" + "mmc rpmb write addr blk# cnt
- block size is 256 bytes\n" + "mmc rpmb key
- program the RPMB authentication key.\n" + "mmc rpmb counter - read the value of the write counter\n" +#endif + "mmc setdsr - set DSR register value\n" + ); + +/* 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" +); + +#endif /* !CONFIG_GENERIC_MMC */ diff --git a/cmd/mmc_spi.c b/cmd/mmc_spi.c new file mode 100644 index 0000000..a2138b8 --- /dev/null +++ b/cmd/mmc_spi.c @@ -0,0 +1,88 @@ +/* + * Command for mmc_spi setup. + * + * Copyright (C) 2010 Thomas Chou + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include + +#ifndef CONFIG_MMC_SPI_BUS +# define CONFIG_MMC_SPI_BUS 0 +#endif +#ifndef CONFIG_MMC_SPI_CS +# define CONFIG_MMC_SPI_CS 1 +#endif +/* in SPI mode, MMC speed limit is 20MHz, while SD speed limit is 25MHz */ +#ifndef CONFIG_MMC_SPI_SPEED +# define CONFIG_MMC_SPI_SPEED 25000000 +#endif +/* MMC and SD specs only seem to care that sampling is on the + * rising edge ... meaning SPI modes 0 or 3. So either SPI mode + * should be legit. We'll use mode 0 since the steady state is 0, + * which is appropriate for hotplugging, unless the platform data + * specify mode 3 (if hardware is not compatible to mode 0). + */ +#ifndef CONFIG_MMC_SPI_MODE +# define CONFIG_MMC_SPI_MODE SPI_MODE_0 +#endif + +static int do_mmc_spi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uint bus = CONFIG_MMC_SPI_BUS; + uint cs = CONFIG_MMC_SPI_CS; + uint speed = CONFIG_MMC_SPI_SPEED; + uint mode = CONFIG_MMC_SPI_MODE; + char *endp; + struct mmc *mmc; + + if (argc < 2) + goto usage; + + cs = simple_strtoul(argv[1], &endp, 0); + if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) + goto usage; + if (*endp == ':') { + if (endp[1] == 0) + goto usage; + bus = cs; + cs = simple_strtoul(endp + 1, &endp, 0); + if (*endp != 0) + goto usage; + } + if (argc >= 3) { + speed = simple_strtoul(argv[2], &endp, 0); + if (*argv[2] == 0 || *endp != 0) + goto usage; + } + if (argc >= 4) { + mode = simple_strtoul(argv[3], &endp, 16); + if (*argv[3] == 0 || *endp != 0) + goto usage; + } + if (!spi_cs_is_valid(bus, cs)) { + printf("Invalid SPI bus %u cs %u\n", bus, cs); + return 1; + } + + mmc = mmc_spi_init(bus, cs, speed, mode); + if (!mmc) { + printf("Failed to create MMC Device\n"); + return 1; + } + printf("%s: %d at %u:%u hz %u mode %u\n", mmc->cfg->name, mmc->block_dev.dev, + bus, cs, speed, mode); + mmc_init(mmc); + return 0; + +usage: + return CMD_RET_USAGE; +} + +U_BOOT_CMD( + mmc_spi, 4, 0, do_mmc_spi, + "mmc_spi setup", + "[bus:]cs [hz] [mode] - setup mmc_spi device" +); diff --git a/cmd/mp.c b/cmd/mp.c new file mode 100644 index 0000000..a80c642 --- /dev/null +++ b/cmd/mp.c @@ -0,0 +1,95 @@ +/* + * Copyright 2008-2009 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +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(cmd_tbl_t *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[] = + " reset - Reset cpu \n" + "cpu status - Status of all cpus\n" + "cpu status - Status of cpu \n" + "cpu disable - Disable cpu \n" + "cpu release [args] - Release cpu at with [args]" +#ifdef CONFIG_PPC + "\n" + " [args] : \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 and r6 is 0\n" \ + "\n" \ + " When cpu 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/cmd/mtdparts.c b/cmd/mtdparts.c new file mode 100644 index 0000000..dab1958 --- /dev/null +++ b/cmd/mtdparts.c @@ -0,0 +1,2106 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Robert Schwebel, Pengutronix, + * + * (C) Copyright 2003 + * Kai-Uwe Bloem, Auerswald GmbH & Co KG, + * + * (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 + * + * $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $ + * Copyright 2002 SYSGO Real-Time Solutions GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Three environment variables are used by the parsing routines: + * + * 'partition' - keeps current partition identifier + * + * partition := + * := ,part_num + * + * + * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping + * + * mtdids=[,,...] + * + * := = + * := 'nand'|'nor'|'onenand' + * := mtd device number, 0... + * := unique device tag used by linux kernel to find mtd device (mtd->name) + * + * + * 'mtdparts' - partition list + * + * mtdparts=mtdparts=[;...] + * + * := :[,...] + * := unique device tag used by linux kernel to find mtd device (mtd->name) + * := [@][][] + * := standard linux memsize OR '-' to denote all remaining space + * := partition start offset within the device + * := '(' NAME ')' + * := when set to 'ro' makes partition read-only (not used, passed to kernel) + * + * Notes: + * - each 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 +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_NAND) +#include +#include +#endif + +#if defined(CONFIG_CMD_ONENAND) +#include +#include +#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) +static const char *const mtdids_default = MTDIDS_DEFAULT; +#else +static const char *const mtdids_default = NULL; +#endif + +#if defined(MTDPARTS_DEFAULT) +static const char *const mtdparts_default = MTDPARTS_DEFAULT; +#else +static const char *const mtdparts_default = NULL; +#endif + +/* 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]; +static char last_parts[MTDPARTS_MAXLEN]; +static char last_partition[PARTITION_MAXLEN]; + +/* 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; + +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; + case 'M': + case 'm': + ret <<= 10; + case 'K': + case 'k': + ret <<= 10; + (*retptr)++; + 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; + setenv_ulong("mtddevnum", mtddevnum); + break; + } + mtddevnum += dev->num_parts; + } + + part = mtd_part_info(current_mtd_dev, current_mtd_partnum); + setenv("mtddevname", part->name); + + debug("=> mtddevnum %d,\n=> mtddevname %s\n", mtddevnum, part->name); + } else { + setenv("mtddevnum", NULL); + setenv("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); + + setenv("partition", buf); + strncpy(last_partition, buf, 16); + + debug("=> partition %s\n", buf); + } else { + setenv("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, 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. + * @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 */ + sprintf(part->name, "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. + * @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 = p = mtd_dev; + if (!(p = strchr(mtd_id, ':'))) { + printf("no 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; + } + +#ifdef DEBUG + pend = strchr(p, ';'); +#endif + 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; + } + + if (num_parts == 0) { + printf("no partitions for device %s%d (%s)\n", + MTD_DEV_TYPE(id->type), id->num, id->mtd_id); + 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 := 'nand'|'nor'|'onenand', + * 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 { + 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; + } + + strcpy(p, "mtdparts="); + p += 9; + + 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)) + setenv("mtdparts", buf); + else + setenv("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%08x\t0x%08x%s\t0x%08x\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 , 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%08x@0x%08x\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 */ + +/** + * 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 = mtdparts; + struct mtd_device *dev; + int err = 1; + char tmp_parts[MTDPARTS_MAXLEN]; + + debug("\n---parse_mtdparts---\nmtdparts = %s\n\n", p); + + /* 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 */ + if (gd->flags & GD_FLG_ENV_READY) { + p = getenv("mtdparts"); + } else { + p = tmp_parts; + getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN); + } + + if (strncmp(p, "mtdparts=", 9) != 0) { + printf("mtdparts variable doesn't start with 'mtdparts='\n"); + return err; + } + p += 9; + + while (p && (*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) { + device_delall(&devices); + return 1; + } + + return 0; +} + +/** + * 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' */ + if (mtd_id_parse(p, &p, &type, &num) != 0) + break; + + if (*p != '=') { + printf("mtdids: incorrect \n"); + break; + } + p++; + + /* check if requested device exists */ + if (mtd_device_validate(type, num, &size) != 0) + return 1; + + /* locate */ + 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 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]; + char tmp_parts[MTDPARTS_MAXLEN]; + + debug("\n---mtdparts_init---\n"); + if (!initialized) { + INIT_LIST_HEAD(&mtdids); + INIT_LIST_HEAD(&devices); + memset(last_ids, 0, MTDIDS_MAXLEN); + memset(last_parts, 0, MTDPARTS_MAXLEN); + memset(last_partition, 0, PARTITION_MAXLEN); + initialized = 1; + } + + /* get variables */ + ids = getenv("mtdids"); + /* + * 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. + */ + if (gd->flags & GD_FLG_ENV_READY) { + parts = getenv("mtdparts"); + } else { + parts = tmp_parts; + getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN); + } + current_partition = getenv("partition"); + + /* save it for later parsing, cannot rely on current partition pointer + * as 'partition' variable may be updated during init */ + tmp_ep[0] = '\0'; + 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 varible is empty try to use defaults */ + if (!ids) { + if (mtdids_default) { + debug("mtdids variable not defined, using default\n"); + ids = mtdids_default; + setenv("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; + } + + /* do no try to use defaults when mtdparts variable is not defined, + * just check the length */ + if (!parts) + 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 (getenv("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(cmd_tbl_t *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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + if (argc == 2) { + if (strcmp(argv[1], "default") == 0) { + setenv("mtdids", (char *)mtdids_default); + setenv("mtdparts", (char *)mtdparts_default); + setenv("partition", NULL); + + mtdparts_init(); + return 0; + } else if (strcmp(argv[1], "delall") == 0) { + /* this may be the first run, initialize lists if needed */ + mtdparts_init(); + + setenv("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 [@] [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 %d 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 [@] [] [ro]\n" + " - add partition\n" +#if defined(CONFIG_CMD_MTDPARTS_SPREAD) + "mtdparts add.spread [@] [] [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 := \n" + " := ,part_num\n\n" + "'mtdids' - linux kernel mtd device id <-> u-boot device id mapping\n\n" + "mtdids=[,,...]\n\n" + " := =\n" + " := 'nand'|'nor'|'onenand'\n" + " := mtd device number, 0...\n" + " := unique device tag used by linux kernel to find mtd device (mtd->name)\n\n" + "'mtdparts' - partition list\n\n" + "mtdparts=mtdparts=[;...]\n\n" + " := :[,...]\n" + " := unique device tag used by linux kernel to find mtd device (mtd->name)\n" + " := [@][][]\n" + " := standard linux memsize OR '-' to denote all remaining space\n" + " := partition start offset within the device\n" + " := '(' NAME ')'\n" + " := 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/cmd/nand.c b/cmd/nand.c new file mode 100644 index 0000000..a6b67e2 --- /dev/null +++ b/cmd/nand.c @@ -0,0 +1,973 @@ +/* + * Driver for NAND support, Rick Bronson + * borrowed heavily from: + * (c) 1999 Machine Vision Holdings, Inc. + * (c) 1999, 2000 David Woodhouse + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_MTDPARTS) + +/* partition handling routines */ +int mtdparts_init(void); +int 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 + +static int nand_dump(nand_info_t *nand, 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 + nand->writesize; + + last = off; + + datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize); + if (!datbuf) { + puts("No memory for page buffer\n"); + return 1; + } + + oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize); + if (!oobbuf) { + puts("No memory for page buffer\n"); + ret = 1; + goto free_dat; + } + off &= ~(nand->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 = nand->writesize; + ops.ooblen = nand->oobsize; + ops.mode = MTD_OPS_RAW; + i = mtd_read_oob(nand, 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 = nand->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 = nand->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) +{ + if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || + !nand_info[dev].name) { + puts("No such device\n"); + return -1; + } + + if (nand_curr_device == dev) + return 0; + + printf("Device %d: %s", dev, nand_info[dev].name); + puts("... is now current device\n"); + nand_curr_device = dev; + +#ifdef CONFIG_SYS_NAND_SELECT_DEVICE + board_nand_select_device(nand_info[dev].priv, 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(nand_info_t *nand) +{ + ulong block_start = 0; + ulong off; + int last_status = -1; + + struct nand_chip *nand_chip = nand->priv; + /* check the WP bit */ + nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1); + printf("device is %swrite protected\n", + (nand_chip->read_byte(nand) & 0x80 ? + "NOT " : "")); + + for (off = 0; off < nand->size; off += nand->erasesize) { + int s = nand_get_lock_status(nand, off); + + /* print message only if status has changed */ + if (s != last_status && off != 0) { + print_status(block_start, off, nand->erasesize, + last_status); + block_start = off; + } + last_status = s; + } + /* Print the last block info */ + print_status(block_start, off, nand->erasesize, last_status); +} +#endif + +#ifdef CONFIG_ENV_OFFSET_OOB +unsigned long nand_env_oob_offset; + +int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[]) +{ + int ret; + uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)]; + nand_info_t *nand = &nand_info[0]; + char *cmd = argv[1]; + + if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) { + puts("no devices available\n"); + return 1; + } + + set_dev(0); + + if (!strcmp(cmd, "get")) { + ret = get_nand_env_oob(nand, &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; + + /* We don't care about size, or maxsize. */ + if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize, + MTD_DEV_TYPE_NAND, nand_info[idx].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 (nand->oobavail < ENV_OFFSET_SIZE) { + printf("Insufficient available OOB bytes:\n" + "%d OOB bytes available but %d required for " + "env.oob support\n", + nand->oobavail, ENV_OFFSET_SIZE); + return 1; + } + + if ((addr & (nand->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 / nand->erasesize; + + ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops); + if (ret) { + printf("Error writing OOB block 0\n"); + return ret; + } + + ret = get_nand_env_oob(nand, &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) +{ + nand_info_t *nand = &nand_info[idx]; + struct nand_chip *chip = nand->priv; + + printf("Device %d: ", idx); + if (chip->numchips > 1) + printf("%dx ", chip->numchips); + printf("%s, sector size %u KiB\n", + nand->name, nand->erasesize >> 10); + printf(" Page size %8d b\n", nand->writesize); + printf(" OOB size %8d b\n", nand->oobsize); + printf(" Erase size %8d b\n", nand->erasesize); + printf(" subpagesize %8d b\n", chip->subpagesize); + printf(" options 0x%8x\n", chip->options); + printf(" bbt options 0x%8x\n", chip->bbt_options); + + /* Set geometry info */ + setenv_hex("nand_writesize", nand->writesize); + setenv_hex("nand_oobsize", nand->oobsize); + setenv_hex("nand_erasesize", nand->erasesize); +} + +static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, + int read) +{ + int ret = 0; + + while (count--) { + /* Raw access */ + mtd_oob_ops_t ops = { + .datbuf = (u8 *)addr, + .oobbuf = ((u8 *)addr) + nand->writesize, + .len = nand->writesize, + .ooblen = nand->oobsize, + .mode = MTD_OPS_RAW + }; + + if (read) { + ret = mtd_read_oob(nand, off, &ops); + } else { + ret = mtd_write_oob(nand, off, &ops); + if (!ret) + ret = nand_verify_page_oob(nand, &ops, off); + } + + if (ret) { + printf("%s: error at offset %llx, ret %d\n", + __func__, (long long)off, ret); + break; + } + + addr += nand->writesize + nand->oobsize; + off += nand->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. + */ + nand_info_t *nand = &nand_info[dev]; + loff_t maxoffset = offset + *size; + int badblocks = 0; + + /* count badblocks in NAND from offset to offset + size */ + for (; offset < maxoffset; offset += nand->erasesize) { + if (nand_block_isbad(nand, offset)) + badblocks++; + } + /* adjust size if any bad blocks found */ + if (badblocks) { + *size -= badblocks * nand->erasesize; + printf("size adjusted to 0x%llx (%d bad blocks)\n", + (unsigned long long)*size, badblocks); + } +} + +static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int i, ret = 0; + ulong addr; + loff_t off, size, maxsize; + char *cmd, *s; + nand_info_t *nand; +#ifdef CONFIG_SYS_NAND_QUIET + int quiet = CONFIG_SYS_NAND_QUIET; +#else + int quiet = 0; +#endif + const char *quiet_str = getenv("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++) { + if (nand_info[i].name) + 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. + */ + if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || + !nand_info[dev].name) { + puts("\nno devices available\n"); + return 1; + } + nand = &nand_info[dev]; + + if (strcmp(cmd, "bad") == 0) { + printf("\nDevice %d bad blocks:\n", dev); + for (off = 0; off < nand->size; off += nand->erasesize) + if (nand_block_isbad(nand, 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? \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, + nand_info[dev].size) != 0) + return 1; + + if (set_dev(dev)) + return 1; + + nand = &nand_info[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(nand, &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(nand, 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; + + 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 && !strcmp(s, ".raw")) { + raw = 1; + + if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize, + MTD_DEV_TYPE_NAND, + nand_info[dev].size)) + return 1; + + if (set_dev(dev)) + return 1; + + nand = &nand_info[dev]; + + if (argc > 4 && !str2long(argv[4], &pagecount)) { + printf("'%s' is not a number\n", argv[4]); + return 1; + } + + if (pagecount * nand->writesize > size) { + puts("Size exceeds partition or device limit\n"); + return -1; + } + + rwsize = pagecount * (nand->writesize + nand->oobsize); + } else { + if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off, + &size, &maxsize, + MTD_DEV_TYPE_NAND, + nand_info[dev].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; + } + + nand = &nand_info[dev]; + + if (!s || !strcmp(s, ".jffs2") || + !strcmp(s, ".e") || !strcmp(s, ".i")) { + if (read) + ret = nand_read_skip_bad(nand, off, &rwsize, + NULL, maxsize, + (u_char *)addr); + else + ret = nand_write_skip_bad(nand, 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(nand, 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(nand, off, &ops); + else + ret = mtd_write_oob(nand, off, &ops); + } else if (raw) { + ret = raw_access(nand, addr, off, pagecount, read); + } 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) { + if (argc < 3) + goto usage; + + if (!str2off(argv[2], &off)) { + puts("Offset is not a valid number\n"); + return 1; + } + + printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n", + dev, off, nand->erasesize); + ret = nand_torture(nand, off); + printf(" %s\n", ret ? "Failed" : "Passed"); + + return ret == 0 ? 0 : 1; + } +#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(nand, 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(nand); + } else { + if (!nand_lock(nand, 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, + nand_info[dev].size) < 0) + return 1; + + if (set_dev(dev)) + return 1; + + if (!nand_unlock(&nand_info[dev], 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 - 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 block at offset\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(cmd_tbl_t *cmdtp, nand_info_t *nand, + ulong offset, ulong addr, char *cmd) +{ + int r; + char *s; + size_t cnt; +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + 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", nand->name, offset); + + cnt = nand->writesize; + r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->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_IMAGE_FORMAT_LEGACY) + 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(nand, offset, &cnt, NULL, nand->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)) { + 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 */ + + load_addr = addr; + + return bootm_maybe_autostart(cmdtp, cmd); +} + +static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + char *boot_device = NULL; + int idx; + ulong addr, offset = 0; +#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; + return nand_load_image(cmdtp, &nand_info[dev->id->num], + part->offset, addr, argv[0]); + } + } +#endif + + bootstage_mark(BOOTSTAGE_ID_NAND_PART); + switch (argc) { + case 1: + addr = CONFIG_SYS_LOAD_ADDR; + boot_device = getenv("bootdevice"); + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = getenv("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); + + if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) { + 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, &nand_info[idx], offset, addr, argv[0]); +} + +U_BOOT_CMD(nboot, 4, 1, do_nandboot, + "boot from NAND device", + "[partition] | [[[loadAddr] dev] offset]" +); diff --git a/cmd/net.c b/cmd/net.c new file mode 100644 index 0000000..b2f3c7b --- /dev/null +++ b/cmd/net.c @@ -0,0 +1,447 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Boot support + */ +#include +#include +#include + +static int netboot_common(enum proto_t, cmd_tbl_t *, int, char * const []); + +static int do_bootp(cmd_tbl_t *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]" +); + +int do_tftpb(cmd_tbl_t *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]" +); + +#ifdef CONFIG_CMD_TFTPPUT +int do_tftpput(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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); + setenv("gatewayip", tmp); + } + + if (net_netmask.s_addr) { + ip_to_string(net_netmask, tmp); + setenv("netmask", tmp); + } + + if (net_hostname[0]) + setenv("hostname", net_hostname); + + if (net_root_path[0]) + setenv("rootpath", net_root_path); + + if (net_ip.s_addr) { + ip_to_string(net_ip, tmp); + setenv("ipaddr", tmp); + } +#if !defined(CONFIG_BOOTP_SERVERIP) + /* + * Only attempt to change serverip if net/bootp.c:BootpCopyNetParams() + * could have set it + */ + if (net_server_ip.s_addr) { + ip_to_string(net_server_ip, tmp); + setenv("serverip", tmp); + } +#endif + if (net_dns_server.s_addr) { + ip_to_string(net_dns_server, tmp); + setenv("dnsip", tmp); + } +#if defined(CONFIG_BOOTP_DNS2) + if (net_dns_server2.s_addr) { + ip_to_string(net_dns_server2, tmp); + setenv("dnsip2", tmp); + } +#endif + if (net_nis_domain[0]) + setenv("domain", net_nis_domain); + +#if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET) + if (net_ntp_time_offset) { + sprintf(tmp, "%d", net_ntp_time_offset); + setenv("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); + setenv("ntpserverip", tmp); + } +#endif +} + +static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, + char * const argv[]) +{ + char *s; + char *end; + int rcode = 0; + int size; + ulong addr; + + /* pre-set load_addr */ + s = getenv("loadaddr"); + if (s != NULL) + load_addr = simple_strtoul(s, NULL, 16); + + switch (argc) { + case 1: + 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]))) + load_addr = addr; + else + copy_filename(net_boot_file_name, argv[1], + sizeof(net_boot_file_name)); + break; + + case 3: + load_addr = simple_strtoul(argv[1], NULL, 16); + 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, &save_addr) < 0 || + strict_strtoul(argv[2], 16, &save_size) < 0) { + printf("Invalid address/size\n"); + return CMD_RET_USAGE; + } + 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; + } + + /* flush cache */ + flush_cache(load_addr, size); + + 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(cmd_tbl_t *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); + setenv("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); + setenv("nvlan", tmp); + net_native_vlan = cdp_native_vlan; + } +} + +int do_cdp(cmd_tbl_t *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) +int do_sntp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *toff; + + if (argc < 2) { + net_ntp_server = getenv_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 = getenv("timeoffset"); + if (toff == NULL) + net_ntp_time_offset = 0; + else + net_ntp_time_offset = simple_strtol(toff, NULL, 10); + + if (net_loop(SNTP) < 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(cmd_tbl_t *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(cmd_tbl_t *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); + setenv("gatewayip", tmp); + + ip_to_string(net_netmask, tmp); + setenv("netmask", tmp); + + ip_to_string(net_ip, tmp); + setenv("ipaddr", tmp); + setenv("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/cmd/nvedit.c b/cmd/nvedit.c new file mode 100644 index 0000000..5ae9d9d --- /dev/null +++ b/cmd/nvedit.c @@ -0,0 +1,1298 @@ +/* + * (C) Copyright 2000-2013 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + * + * Copyright 2011 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * 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 preceeded 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_ENV_IS_IN_EEPROM) && \ + !defined(CONFIG_ENV_IS_IN_FLASH) && \ + !defined(CONFIG_ENV_IS_IN_DATAFLASH) && \ + !defined(CONFIG_ENV_IS_IN_MMC) && \ + !defined(CONFIG_ENV_IS_IN_FAT) && \ + !defined(CONFIG_ENV_IS_IN_NAND) && \ + !defined(CONFIG_ENV_IS_IN_NVRAM) && \ + !defined(CONFIG_ENV_IS_IN_ONENAND) && \ + !defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \ + !defined(CONFIG_ENV_IS_IN_REMOTE) && \ + !defined(CONFIG_ENV_IS_IN_UBI) && \ + !defined(CONFIG_ENV_IS_NOWHERE) +# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|ONENAND|\ +SPI_FLASH|NVRAM|MMC|FAT|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 get_env_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 get_env_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 */ + ENTRY e, *ep; + + e.key = name; + e.data = NULL; + hsearch_r(e, 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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int i; + int rcode = 0; + int env_flag = H_HIDE_DOT; + + 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(cmd_tbl_t *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; + ENTRY e, *ep; + + 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); + name = argv[1]; + value = argv[2]; + + 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); + return !rc; + } + + /* + * 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, 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 setenv(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 setenv_ulong(const char *varname, ulong value) +{ + /* TODO: this should be unsigned */ + char *str = simple_itoa(value); + + return setenv(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 setenv_hex(const char *varname, ulong value) +{ + char str[17]; + + sprintf(str, "%lx", value); + return setenv(varname, str); +} + +ulong getenv_hex(const char *varname, ulong default_val) +{ + const char *s; + ulong value; + char *endp; + + s = getenv(varname); + if (s) + value = simple_strtoul(s, &endp, 16); + if (!s || endp == s) + return default_val; + + return value; +} + +#ifndef CONFIG_SPL_BUILD +static int do_env_set(cmd_tbl_t *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(cmd_tbl_t *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; i++) { + if (pos) + message[pos++] = ' '; + + strcpy(message + pos, argv[i]); + pos += strlen(argv[i]); + } + message[pos++] = ' '; + message[pos] = '\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(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(cmd_tbl_t *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(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(cmd_tbl_t *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(cmd_tbl_t *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 = getenv(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 *getenv(const char *name) +{ + if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */ + ENTRY e, *ep; + + WATCHDOG_RESET(); + + e.key = name; + e.data = NULL; + hsearch_r(e, FIND, &ep, &env_htab, 0); + + return ep ? ep->data : NULL; + } + + /* restricted capabilities before import */ + if (getenv_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0) + return (char *)(gd->env_buf); + + return NULL; +} + +/* + * Look up variable from environment for restricted C runtime env. + */ +int getenv_f(const char *name, char *buf, unsigned len) +{ + int i, nxt; + + for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { + int val, n; + + for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) { + if (nxt >= CONFIG_ENV_SIZE) + return -1; + } + + val = envmatch((uchar *)name, i); + if (val < 0) + continue; + + /* found; copy out */ + for (n = 0; n < len; ++n, ++buf) { + *buf = env_get_char(val++); + if (*buf == '\0') + return n; + } + + if (n) + *--buf = '\0'; + + printf("env_buf [%d 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 environemnt 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 getenv_ulong(const char *name, int base, ulong default_val) +{ + /* + * We can use getenv() here, even before relocation, since the + * environment variable value is an integer and thus short. + */ + const char *str = getenv(name); + + return str ? simple_strtoul(str, NULL, base) : default_val; +} + +#ifndef CONFIG_SPL_BUILD +#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) +static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + printf("Saving Environment to %s...\n", env_name_spec); + + return saveenv() ? 1 : 0; +} + +U_BOOT_CMD( + saveenv, 1, 0, do_env_save, + "save environment variables to persistent storage", + "" +); +#endif +#endif /* CONFIG_SPL_BUILD */ + + +/* + * Match a name / name=value pair + * + * s1 is either a simple 'name', or a 'name=value' pair. + * i2 is the environment index for a 'name2=value2' pair. + * If the names match, return the index for the value2, else -1. + */ +int envmatch(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(cmd_tbl_t *cmdtp, int __flag, + int argc, char * const argv[]) +{ + int all = 0, flag = 0; + + 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 */ + 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 */ + set_default_env("## Resetting to default environment\n"); + return 0; + } + if (!all && (argc > 0)) { + /* Reset individual variables */ + set_default_vars(argc, argv); + return 0; + } + + return cmd_usage(cmdtp); +} + +static int do_env_delete(cmd_tbl_t *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 resundant + * 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 remainign 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 szenario: 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(cmd_tbl_t *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) { + error("Cannot export environment: errno = %d\n", errno); + return 1; + } + sprintf(buf, "%zX", (size_t)len); + setenv("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) { + error("Cannot export environment: errno = %d\n", errno); + return 1; + } + + if (chk) { + envp->crc = crc32(0, envp->data, ENV_SIZE); +#ifdef CONFIG_ENV_ADDR_REDUND + envp->flags = ACTIVE_FLAG; +#endif + } + setenv_hex("filesize", len + offsetof(env_t, data)); + + return 0; + +sep_err: + printf("## %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] + * -d: delete existing environment before importing; + * otherwise overwrite / append to existion 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 + */ +static int do_env_import(cmd_tbl_t *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; + 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) { + size = simple_strtoul(argv[1], NULL, 16); + } else if (argc == 1 && 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 (chk) { + uint32_t crc; + env_t *ep = (env_t *)ptr; + + 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, 0, NULL) == 0) { + 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_ENV_EXISTS) +static int do_env_exists(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + ENTRY e, *ep; + + if (argc < 2) + return CMD_RET_USAGE; + + e.key = argv[1]; + e.data = NULL; + hsearch_r(e, FIND, &ep, &env_htab, 0); + + return (ep == NULL) ? 1 : 0; +} +#endif + +/* + * New command line interface: "env" command with subcommands + */ +static cmd_tbl_t 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 + 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(CONFIG_ENV_IS_NOWHERE) + U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""), +#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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *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] - import environment\n" +#endif + "env print [-a | name ...] - print environment\n" +#if defined(CONFIG_CMD_RUN) + "env run var [...] - run commands in an environment variable\n" +#endif +#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) + "env save - save environment\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" + "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", + "[-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/cmd/onenand.c b/cmd/onenand.c new file mode 100644 index 0000000..feab01a --- /dev/null +++ b/cmd/onenand.c @@ -0,0 +1,595 @@ +/* + * U-Boot command for OneNAND support + * + * Copyright (C) 2005-2008 Samsung Electronics + * Kyungmin Park + * + * 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 +#include +#include + +#include +#include +#include + +#include + +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 == 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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + printf("%s\n", mtd->name); + return 0; +} + +static int do_onenand_bad(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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(cmd_tbl_t * 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 cmd_tbl_t 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(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *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/cmd/otp.c b/cmd/otp.c new file mode 100644 index 0000000..10c1475 --- /dev/null +++ b/cmd/otp.c @@ -0,0 +1,228 @@ +/* + * cmd_otp.c - interface to Blackfin on-chip One-Time-Programmable memory + * + * Copyright (c) 2007-2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +/* There are 512 128-bit "pages" (0x000 through 0x1FF). + * The pages are accessable as 64-bit "halfpages" (an upper and lower half). + * The pages are not part of the memory map. There is an OTP controller which + * handles scanning in/out of bits. While access is done through OTP MMRs, + * the bootrom provides C-callable helper functions to handle the interaction. + */ + +#include +#include +#include +#include + +#include +#include +#include + +static const char *otp_strerror(uint32_t err) +{ + switch (err) { + case 0: return "no error"; + case OTP_WRITE_ERROR: return "OTP fuse write error"; + case OTP_READ_ERROR: return "OTP fuse read error"; + case OTP_ACC_VIO_ERROR: return "invalid OTP address"; + case OTP_DATA_MULT_ERROR: return "multiple bad bits detected"; + case OTP_ECC_MULT_ERROR: return "error in ECC bits"; + case OTP_PREV_WR_ERROR: return "space already written"; + case OTP_DATA_SB_WARN: return "single bad bit in half page"; + case OTP_ECC_SB_WARN: return "single bad bit in ECC"; + default: return "unknown error"; + } +} + +#define lowup(x) ((x) % 2 ? "upper" : "lower") + +static int check_voltage(void) +{ + /* Make sure voltage limits are within datasheet spec */ + uint16_t vr_ctl = bfin_read_VR_CTL(); + +#ifdef __ADSPBF54x__ + /* 0.9V <= VDDINT <= 1.1V */ + if ((vr_ctl & 0xc) && (vr_ctl & 0xc0) == 0xc0) + return 1; +#else + /* for the parts w/out qualification yet */ + (void)vr_ctl; +#endif + + return 0; +} + +static void set_otp_timing(bool write) +{ + static uint32_t timing; + if (!timing) { + uint32_t tp1, tp2, tp3; + /* OTP_TP1 = 1000 / sclk_period (in nanoseconds) + * OTP_TP1 = 1000 / (1 / get_sclk() * 10^9) + * OTP_TP1 = (1000 * get_sclk()) / 10^9 + * OTP_TP1 = get_sclk() / 10^6 + */ + tp1 = get_sclk() / 1000000; + /* OTP_TP2 = 400 / (2 * sclk_period) + * OTP_TP2 = 400 / (2 * 1 / get_sclk() * 10^9) + * OTP_TP2 = (400 * get_sclk()) / (2 * 10^9) + * OTP_TP2 = (2 * get_sclk()) / 10^7 + */ + tp2 = (2 * get_sclk() / 10000000) << 8; + /* OTP_TP3 = magic constant */ + tp3 = (0x1401) << 15; + timing = tp1 | tp2 | tp3; + } + + bfrom_OtpCommand(OTP_INIT, write ? timing : timing & ~(-1 << 15)); +} + +int do_otp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *cmd; + uint32_t ret, base_flags; + bool prompt_user, force_read; + uint32_t (*otp_func)(uint32_t page, uint32_t flags, uint64_t *page_content); + + if (argc < 4) { + usage: + return CMD_RET_USAGE; + } + + prompt_user = false; + base_flags = 0; + cmd = argv[1]; + if (!strcmp(cmd, "read")) + otp_func = bfrom_OtpRead; + else if (!strcmp(cmd, "dump")) { + otp_func = bfrom_OtpRead; + force_read = true; + } else if (!strcmp(cmd, "write")) { + otp_func = bfrom_OtpWrite; + base_flags = OTP_CHECK_FOR_PREV_WRITE; + if (!strcmp(argv[2], "--force")) { + argv++; + --argc; + } else + prompt_user = false; + } else if (!strcmp(cmd, "lock")) { + if (argc != 4) + goto usage; + otp_func = bfrom_OtpWrite; + base_flags = OTP_LOCK; + } else + goto usage; + + uint64_t *addr = (uint64_t *)simple_strtoul(argv[2], NULL, 16); + uint32_t page = simple_strtoul(argv[3], NULL, 16); + uint32_t flags; + size_t i, count; + ulong half; + + if (argc > 4) + count = simple_strtoul(argv[4], NULL, 16); + else + count = 2; + + if (argc > 5) { + half = simple_strtoul(argv[5], NULL, 16); + if (half != 0 && half != 1) { + puts("Error: 'half' can only be '0' or '1'\n"); + goto usage; + } + } else + half = 0; + + /* "otp lock" has slightly different semantics */ + if (base_flags & OTP_LOCK) { + count = page; + page = (uint32_t)addr; + addr = NULL; + } + + /* do to the nature of OTP, make sure users are sure */ + if (prompt_user) { + printf( + "Writing one time programmable memory\n" + "Make sure your operating voltages and temperature are within spec\n" + " source address: 0x%p\n" + " OTP destination: %s page 0x%03X - %s page 0x%03lX\n" + " number to write: %lu halfpages\n" + " type \"YES\" (no quotes) to confirm: ", + addr, + lowup(half), page, + lowup(half + count - 1), page + (half + count - 1) / 2, + half + count + ); + if (!confirm_yesno()) { + printf(" Aborting\n"); + return 1; + } + } + + printf("OTP memory %s: addr 0x%p page 0x%03X count %zu ... ", + cmd, addr, page, count); + + set_otp_timing(otp_func == bfrom_OtpWrite); + if (otp_func == bfrom_OtpWrite && check_voltage()) { + puts("ERROR: VDDINT voltage is out of spec for writing\n"); + return -1; + } + + /* Do the actual reading/writing stuff */ + ret = 0; + for (i = half; i < count + half; ++i) { + flags = base_flags | (i % 2 ? OTP_UPPER_HALF : OTP_LOWER_HALF); + try_again: + ret = otp_func(page, flags, addr); + if (ret & OTP_MASTER_ERROR) { + if (force_read) { + if (flags & OTP_NO_ECC) + break; + else + flags |= OTP_NO_ECC; + puts("E"); + goto try_again; + } else + break; + } else if (ret) + puts("W"); + else + puts("."); + if (!(base_flags & OTP_LOCK)) { + ++addr; + if (i % 2) + ++page; + } else + ++page; + } + if (ret & 0x1) + printf("\nERROR at page 0x%03X (%s-halfpage): 0x%03X: %s\n", + page, lowup(i), ret, otp_strerror(ret)); + else + puts(" done\n"); + + /* Make sure we disable writing */ + set_otp_timing(false); + bfrom_OtpCommand(OTP_CLOSE, 0); + + return ret; +} + +U_BOOT_CMD( + otp, 7, 0, do_otp, + "One-Time-Programmable sub-system", + "read [count] [half]\n" + " - read 'count' half-pages starting at 'page' (offset 'half') to 'addr'\n" + "otp dump [count] [half]\n" + " - like 'otp read', but skip read errors\n" + "otp write [--force] [count] [half]\n" + " - write 'count' half-pages starting at 'page' (offset 'half') from 'addr'\n" + "otp lock \n" + " - lock 'count' pages starting at 'page'" +); diff --git a/cmd/part.c b/cmd/part.c new file mode 100644 index 0000000..5599509 --- /dev/null +++ b/cmd/part.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * made from cmd_ext2, which was: + * + * (C) Copyright 2004 + * esd gmbh + * Reinhard Arlt + * + * made from cmd_reiserfs by + * + * (C) Copyright 2003 - 2004 + * Sysgo Real-Time Solutions, AG + * Pavel Bartusek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#ifndef CONFIG_PARTITION_UUIDS +#error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_PART to be enabled +#endif + +static int do_part_uuid(int argc, char * const argv[]) +{ + int part; + block_dev_desc_t *dev_desc; + disk_partition_t info; + + if (argc < 2) + return CMD_RET_USAGE; + if (argc > 3) + return CMD_RET_USAGE; + + part = get_device_and_partition(argv[0], argv[1], &dev_desc, &info, 0); + if (part < 0) + return 1; + + if (argc > 2) + setenv(argv[2], info.uuid); + else + printf("%s\n", info.uuid); + + return 0; +} + +static int do_part_list(int argc, char * const argv[]) +{ + int ret; + block_dev_desc_t *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 = get_device(argv[0], argv[1], &desc); + if (ret < 0) + return 1; + + if (var != NULL) { + int p; + char str[512] = { '\0', }; + disk_partition_t info; + + for (p = 1; p < 128; p++) { + char t[5]; + int r = get_partition_info(desc, p, &info); + + if (r != 0) + continue; + + if (bootable && !info.bootable) + continue; + + sprintf(t, "%s%x", str[0] ? " " : "", p); + strcat(str, t); + } + setenv(var, str); + return 0; + } + + print_part(desc); + + return 0; +} + +static int do_part_start(int argc, char * const argv[]) +{ + block_dev_desc_t *desc; + disk_partition_t info; + char buf[512] = { 0 }; + int part; + int err; + int ret; + + if (argc < 3) + return CMD_RET_USAGE; + if (argc > 4) + return CMD_RET_USAGE; + + part = simple_strtoul(argv[2], NULL, 0); + + ret = get_device(argv[0], argv[1], &desc); + if (ret < 0) + return 1; + + err = get_partition_info(desc, part, &info); + if (err) + return 1; + + snprintf(buf, sizeof(buf), LBAF, info.start); + + if (argc > 3) + setenv(argv[3], buf); + else + printf("%s\n", buf); + + return 0; +} + +static int do_part_size(int argc, char * const argv[]) +{ + block_dev_desc_t *desc; + disk_partition_t info; + char buf[512] = { 0 }; + int part; + int err; + int ret; + + if (argc < 3) + return CMD_RET_USAGE; + if (argc > 4) + return CMD_RET_USAGE; + + part = simple_strtoul(argv[2], NULL, 0); + + ret = get_device(argv[0], argv[1], &desc); + if (ret < 0) + return 1; + + err = get_partition_info(desc, part, &info); + if (err) + return 1; + + snprintf(buf, sizeof(buf), LBAF, info.size); + + if (argc > 3) + setenv(argv[3], buf); + else + printf("%s\n", buf); + + return 0; +} + +static int do_part(cmd_tbl_t *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); + + return CMD_RET_USAGE; +} + +U_BOOT_CMD( + part, CONFIG_SYS_MAXARGS, 1, do_part, + "disk partition related commands", + "uuid :\n" + " - print partition UUID\n" + "part uuid : \n" + " - set environment variable to partition UUID\n" + "part list \n" + " - print a device's partition table\n" + "part list [flags] \n" + " - set environment variable to the list of partitions\n" + " flags can be -bootable (list only bootable partitions)\n" + "part start \n" + " - set environment variable to the start of the partition (in blocks)\n" + "part size \n" + " - set environment variable to the size of the partition (in blocks)" +); diff --git a/cmd/pci.c b/cmd/pci.c new file mode 100644 index 0000000..8094d33 --- /dev/null +++ b/cmd/pci.c @@ -0,0 +1,687 @@ +/* + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH + * Andreas Heppel + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * PCI routines + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 + +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(bus->seq, short_listing); + + for (device_find_first_child(bus, &dev); + dev; + device_find_next_child(&dev)) { + struct pci_child_platdata *pplat; + + pplat = dev_get_parent_platdata(dev); + if (short_listing) { + printf("%02x.%02x.%02x ", bus->seq, + PCI_DEV(pplat->devfn), PCI_FUNC(pplat->devfn)); + pci_header_show_brief(dev); + } else { + printf("\nFound PCI device %02x.%02x.%02x:\n", bus->seq, + 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] == '-')) { + /* 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; +} + +/* 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(cmd_tbl_t *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 */ + if (argc < 3) + goto usage; + if ((bdf = get_pci_dev(argv[2])) == -1) + return 1; + break; +#ifdef CONFIG_CMD_PCI_ENUM + case 'e': + break; +#endif + default: /* scan bus */ + value = 1; /* short listing */ + if (argc > 1) { + if (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; + } + 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); +#ifdef CONFIG_CMD_PCI_ENUM + case 'e': +# ifdef CONFIG_DM_PCI + printf("This command is not yet supported with driver model\n"); +# else + pci_init(); +# endif + break; +#endif + 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; + 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" +#ifdef CONFIG_CMD_PCI_ENUM + "pci enum\n" + " - re-enumerate PCI buses\n" +#endif + "pci header b.d.f\n" + " - show header of PCI device 'bus.device.function'\n" + "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/cmd/pcmcia.c b/cmd/pcmcia.c new file mode 100644 index 0000000..682d18f --- /dev/null +++ b/cmd/pcmcia.c @@ -0,0 +1,346 @@ +/* + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + * + ******************************************************************** + * + * Lots of code copied from: + * + * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series. + * (C) 1999-2000 Magnus Damm + * + * "The ExCA standard specifies that socket controllers should provide + * two IO and five memory windows per socket, which can be independently + * configured and positioned in the host address space and mapped to + * arbitrary segments of card address space. " - David A Hinds. 1999 + * + * This controller does _not_ meet the ExCA standard. + * + * m8xx pcmcia controller brief info: + * + 8 windows (attrib, mem, i/o) + * + up to two slots (SLOT_A and SLOT_B) + * + inputpins, outputpins, event and mask registers. + * - no offset register. sigh. + * + * Because of the lacking offset register we must map the whole card. + * We assign each memory window PCMCIA_MEM_WIN_SIZE address space. + * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO + * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE. + * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE. + * They are maximum 64KByte each... + */ + +/* #define DEBUG 1 */ + +/* + * PCMCIA support + */ +#include +#include +#include +#include +#include + +/* -------------------------------------------------------------------- */ + +#if defined(CONFIG_CMD_PCMCIA) + +extern int pcmcia_on (void); +extern int pcmcia_off (void); + +int do_pinit (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int rcode = 0; + + if (argc != 2) { + printf ("Usage: pinit {on | off}\n"); + return 1; + } + if (strcmp(argv[1],"on") == 0) { + rcode = pcmcia_on (); + } else if (strcmp(argv[1],"off") == 0) { + rcode = pcmcia_off (); + } else { + printf ("Usage: pinit {on | off}\n"); + return 1; + } + + return rcode; +} + +U_BOOT_CMD( + pinit, 2, 0, do_pinit, + "PCMCIA sub-system", + "on - power on PCMCIA socket\n" + "pinit off - power off PCMCIA socket" +); + +#endif + +/* -------------------------------------------------------------------- */ + +#undef CHECK_IDE_DEVICE + +#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) +#define CHECK_IDE_DEVICE +#endif + +#if defined(CONFIG_PXA_PCMCIA) +#define CHECK_IDE_DEVICE +#endif + +#ifdef CHECK_IDE_DEVICE + +int ide_devices_found; +static uchar *known_cards[] = { + (uchar *)"ARGOSY PnPIDE D5", + NULL +}; + +#define MAX_TUPEL_SZ 512 +#define MAX_FEATURES 4 + +#define MAX_IDENT_CHARS 64 +#define MAX_IDENT_FIELDS 4 + +#define indent "\t " + +static void print_funcid (int func) +{ + puts (indent); + switch (func) { + case CISTPL_FUNCID_MULTI: + puts (" Multi-Function"); + break; + case CISTPL_FUNCID_MEMORY: + puts (" Memory"); + break; + case CISTPL_FUNCID_SERIAL: + puts (" Serial Port"); + break; + case CISTPL_FUNCID_PARALLEL: + puts (" Parallel Port"); + break; + case CISTPL_FUNCID_FIXED: + puts (" Fixed Disk"); + break; + case CISTPL_FUNCID_VIDEO: + puts (" Video Adapter"); + break; + case CISTPL_FUNCID_NETWORK: + puts (" Network Adapter"); + break; + case CISTPL_FUNCID_AIMS: + puts (" AIMS Card"); + break; + case CISTPL_FUNCID_SCSI: + puts (" SCSI Adapter"); + break; + default: + puts (" Unknown"); + break; + } + puts (" Card\n"); +} + +static void print_fixed (volatile uchar *p) +{ + if (p == NULL) + return; + + puts(indent); + + switch (*p) { + case CISTPL_FUNCE_IDE_IFACE: + { uchar iface = *(p+2); + + puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown"); + puts (" interface "); + break; + } + case CISTPL_FUNCE_IDE_MASTER: + case CISTPL_FUNCE_IDE_SLAVE: + { uchar f1 = *(p+2); + uchar f2 = *(p+4); + + puts ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]"); + + if (f1 & CISTPL_IDE_UNIQUE) + puts (" [unique]"); + + puts ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]"); + + if (f2 & CISTPL_IDE_HAS_SLEEP) + puts (" [sleep]"); + + if (f2 & CISTPL_IDE_HAS_STANDBY) + puts (" [standby]"); + + if (f2 & CISTPL_IDE_HAS_IDLE) + puts (" [idle]"); + + if (f2 & CISTPL_IDE_LOW_POWER) + puts (" [low power]"); + + if (f2 & CISTPL_IDE_REG_INHIBIT) + puts (" [reg inhibit]"); + + if (f2 & CISTPL_IDE_HAS_INDEX) + puts (" [index]"); + + if (f2 & CISTPL_IDE_IOIS16) + puts (" [IOis16]"); + + break; + } + } + putc ('\n'); +} + +static int identify (volatile uchar *p) +{ + uchar id_str[MAX_IDENT_CHARS]; + uchar data; + uchar *t; + uchar **card; + int i, done; + + if (p == NULL) + return (0); /* Don't know */ + + t = id_str; + done =0; + + for (i=0; i<=4 && !done; ++i, p+=2) { + while ((data = *p) != '\0') { + if (data == 0xFF) { + done = 1; + break; + } + *t++ = data; + if (t == &id_str[MAX_IDENT_CHARS-1]) { + done = 1; + break; + } + p += 2; + } + if (!done) + *t++ = ' '; + } + *t = '\0'; + while (--t > id_str) { + if (*t == ' ') + *t = '\0'; + else + break; + } + puts ((char *)id_str); + putc ('\n'); + + for (card=known_cards; *card; ++card) { + debug ("## Compare against \"%s\"\n", *card); + if (strcmp((char *)*card, (char *)id_str) == 0) { /* found! */ + debug ("## CARD FOUND ##\n"); + return (1); + } + } + + return (0); /* don't know */ +} + +int check_ide_device (int slot) +{ + volatile uchar *ident = NULL; + volatile uchar *feature_p[MAX_FEATURES]; + volatile uchar *p, *start, *addr; + int n_features = 0; + uchar func_id = ~0; + uchar code, len; + ushort config_base = 0; + int found = 0; + int i; + + addr = (volatile uchar *)(CONFIG_SYS_PCMCIA_MEM_ADDR + + CONFIG_SYS_PCMCIA_MEM_SIZE * (slot * 4)); + debug ("PCMCIA MEM: %08lX\n", (ulong)addr); + + start = p = (volatile uchar *) addr; + + while ((p - start) < MAX_TUPEL_SZ) { + + code = *p; p += 2; + + if (code == 0xFF) { /* End of chain */ + break; + } + + len = *p; p += 2; +#if defined(DEBUG) && (DEBUG > 1) + { volatile uchar *q = p; + printf ("\nTuple code %02x length %d\n\tData:", + code, len); + + for (i = 0; i < len; ++i) { + printf (" %02x", *q); + q+= 2; + } + } +#endif /* DEBUG */ + switch (code) { + case CISTPL_VERS_1: + ident = p + 4; + break; + case CISTPL_FUNCID: + /* Fix for broken SanDisk which may have 0x80 bit set */ + func_id = *p & 0x7F; + break; + case CISTPL_FUNCE: + if (n_features < MAX_FEATURES) + feature_p[n_features++] = p; + break; + case CISTPL_CONFIG: + config_base = (*(p+6) << 8) + (*(p+4)); + debug ("\n## Config_base = %04x ###\n", config_base); + default: + break; + } + p += 2 * len; + } + + found = identify (ident); + + if (func_id != ((uchar)~0)) { + print_funcid (func_id); + + if (func_id == CISTPL_FUNCID_FIXED) + found = 1; + else + return (1); /* no disk drive */ + } + + for (i=0; i only valid for ARGOSY D5!!! */ + *((uchar *)(addr + config_base)) = 1; +#if 0 + printf("\n## Config_base = %04x ###\n", config_base); + printf("Configuration Option Register: %02x @ %x\n", readb(addr + config_base), addr + config_base); + printf("Card Configuration and Status Register: %02x\n", readb(addr + config_base + 2)); + printf("Pin Replacement Register Register: %02x\n", readb(addr + config_base + 4)); + printf("Socket and Copy Register: %02x\n", readb(addr + config_base + 6)); +#endif + return (0); +} + +#endif /* CHECK_IDE_DEVICE */ diff --git a/cmd/pmic.c b/cmd/pmic.c new file mode 100644 index 0000000..970767c --- /dev/null +++ b/cmd/pmic.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2014-2015 Samsung Electronics + * Przemyslaw Marczak + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include + +#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(cmd_tbl_t *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", currdev->seq, currdev->name); + } + + return CMD_RET_SUCCESS; +} + +static int do_list(cmd_tbl_t *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->parent->seq); + } + + if (ret) + return CMD_RET_FAILURE; + + return CMD_RET_SUCCESS; +} + +static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + uint8_t value; + uint reg; + int ret; + + if (!currdev) { + printf("First, set the PMIC device!\n"); + return CMD_RET_USAGE; + } + + dev = currdev; + + printf("Dump pmic: %s registers\n", dev->name); + + for (reg = 0; reg < pmic_reg_count(dev); reg++) { + ret = pmic_read(dev, reg, &value, 1); + if (ret) { + printf("Can't read register: %d\n", reg); + return failure(ret); + } + + if (!(reg % 16)) + printf("\n0x%02x: ", reg); + + printf("%2.2x ", value); + } + printf("\n"); + + return CMD_RET_SUCCESS; +} + +static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + int regs, ret; + uint8_t value; + uint reg; + + if (!currdev) { + printf("First, set the PMIC device!\n"); + return CMD_RET_USAGE; + } + + dev = currdev; + + 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_read(dev, reg, &value, 1); + if (ret) { + printf("Can't read PMIC register: %d!\n", reg); + return failure(ret); + } + + printf("0x%02x: 0x%2.2x\n", reg, value); + + return CMD_RET_SUCCESS; +} + +static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + int regs, ret; + uint8_t value; + uint reg; + + 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_write(dev, reg, &value, 1); + if (ret) { + printf("Can't write PMIC register: %d!\n", reg); + return failure(ret); + } + + return CMD_RET_SUCCESS; +} + +static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *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, + " operations", + "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/cmd/portio.c b/cmd/portio.c new file mode 100644 index 0000000..bf3a997 --- /dev/null +++ b/cmd/portio.c @@ -0,0 +1,145 @@ +/* + * (C) Copyright 2003 + * Marc Singer, elf@buici.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Port I/O Functions + * + * Copied from FADS ROM, Dan Malek (dmalek@jlc.net) + */ + +#include +#include + +/* Display values from last command. + * Memory modify remembered values are different from display memory. + */ +static uint in_last_addr, in_last_size; +static uint out_last_addr, out_last_size, out_last_value; + + +int do_portio_out (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + uint addr = out_last_addr; + uint size = out_last_size; + uint value = out_last_value; + + if (argc != 3) + 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], 1); + addr = simple_strtoul (argv[1], NULL, 16); + value = simple_strtoul (argv[2], NULL, 16); + } +#if defined (CONFIG_X86) + + { + unsigned short port = addr; + + switch (size) { + default: + case 1: + { + unsigned char ch = value; + __asm__ volatile ("out %0, %%dx"::"a" (ch), "d" (port)); + } + break; + case 2: + { + unsigned short w = value; + __asm__ volatile ("out %0, %%dx"::"a" (w), "d" (port)); + } + break; + case 4: + __asm__ volatile ("out %0, %%dx"::"a" (value), "d" (port)); + + break; + } + } + +#endif /* CONFIG_X86 */ + + out_last_addr = addr; + out_last_size = size; + out_last_value = value; + + return 0; +} + +U_BOOT_CMD( + out, 3, 1, do_portio_out, + "write datum to IO port", + "[.b, .w, .l] port value\n - output to IO port" +); + +int do_portio_in (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + uint addr = in_last_addr; + uint size = in_last_size; + + 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], 1); + addr = simple_strtoul (argv[1], NULL, 16); + } +#if defined (CONFIG_X86) + + { + unsigned short port = addr; + + switch (size) { + default: + case 1: + { + unsigned char ch; + __asm__ volatile ("in %%dx, %0":"=a" (ch):"d" (port)); + + printf (" %02x\n", ch); + } + break; + case 2: + { + unsigned short w; + __asm__ volatile ("in %%dx, %0":"=a" (w):"d" (port)); + + printf (" %04x\n", w); + } + break; + case 4: + { + unsigned long l; + __asm__ volatile ("in %%dx, %0":"=a" (l):"d" (port)); + + printf (" %08lx\n", l); + } + break; + } + } +#endif /* CONFIG_X86 */ + + in_last_addr = addr; + in_last_size = size; + + return 0; +} + +U_BOOT_CMD( + in, 2, 1, do_portio_in, + "read data from an IO port", + "[.b, .w, .l] port\n" + " - read datum from IO port" +); diff --git a/cmd/pxe.c b/cmd/pxe.c new file mode 100644 index 0000000..080b376 --- /dev/null +++ b/cmd/pxe.c @@ -0,0 +1,1725 @@ +/* + * Copyright 2010-2011 Calxeda, Inc. + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "menu.h" +#include "cli.h" + +#define MAX_TFTP_PATH_LEN 127 + +const char *pxe_default_paths[] = { +#ifdef CONFIG_SYS_SOC + "default-" CONFIG_SYS_ARCH "-" CONFIG_SYS_SOC, +#endif + "default-" CONFIG_SYS_ARCH, + "default", + NULL +}; + +static bool is_pxe; + +/* + * Like getenv, but prints an error if envvar isn't defined in the + * environment. It always returns what getenv does, so it can be used in + * place of getenv without changing error handling otherwise. + */ +static char *from_env(const char *envvar) +{ + char *ret; + + ret = getenv(envvar); + + if (!ret) + printf("missing environment variable: %s\n", envvar); + + return ret; +} + +#ifdef CONFIG_CMD_NET +/* + * 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. + */ +static 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_getenv_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; +} +#endif + +/* + * 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 == NULL) + 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; +} + +static int (*do_getfile)(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr); + +#ifdef CONFIG_CMD_NET +static int do_get_tftp(cmd_tbl_t *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; +} +#endif + +static char *fs_argv[5]; + +static int do_get_ext2(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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; +} + +/* + * 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(cmd_tbl_t *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. + */ +static int get_pxe_file(cmd_tbl_t *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; +} + +#ifdef CONFIG_CMD_NET + +#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. + */ +static int get_pxelinux_path(cmd_tbl_t *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); +} + +/* + * 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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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; +} +#endif + +/* + * 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(cmd_tbl_t *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); +} + +/* + * 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 *append; + char *initrd; + char *fdt; + char *fdtdir; + 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. + * 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; + int timeout; + int prompt; + struct list_head labels; +}; + +/* + * 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->append) + free(label->append); + + if (label->initrd) + free(label->initrd); + + if (label->fdt) + free(label->fdt); + + if (label->fdtdir) + free(label->fdtdir); + + 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); + setenv("bootargs", bootargs); + } + + debug("running: %s\n", localcmd); + + return run_command_list(localcmd, strlen(localcmd), 0); +} + +/* + * 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(cmd_tbl_t *cmdtp, struct pxe_label *label) +{ + char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL }; + char initrd_str[22]; + char mac_str[29] = ""; + char ip_str[68] = ""; + int bootm_argc = 3; + 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 == NULL) { + 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; + strcpy(bootm_argv[2], getenv("ramdisk_addr_r")); + strcat(bootm_argv[2], ":"); + strcat(bootm_argv[2], getenv("filesize")); + } else { + bootm_argv[2] = "-"; + } + + 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", + getenv("ipaddr"), getenv("serverip"), + getenv("gatewayip"), getenv("netmask")); + } + +#ifdef 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'; + } +#endif + + 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) + strcpy(bootargs, label->append); + strcat(bootargs, ip_str); + strcat(bootargs, mac_str); + + cli_simple_process_macros(bootargs, finalbootargs); + setenv("bootargs", finalbootargs); + printf("append: %s\n", finalbootargs); + } + + bootm_argv[1] = getenv("kernel_addr_r"); + + /* + * fdt usage is optional: + * It handles the following scenarios. All scenarios are exclusive + * + * Scenario 1: If fdt_addr_r specified and "fdt" label is defined in + * pxe file, retrieve fdt blob from server. Pass fdt_addr_r to bootm, + * and adjust argc appropriately. + * + * 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] = getenv("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 = getenv("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 = getenv("soc"); + f2 = "-"; + f3 = getenv("board"); + f4 = ".dtb"; + } + + 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"); + return 1; + } + + 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) { + printf("Skipping %s for failure retrieving fdt\n", + label->name); + return 1; + } + } else { + bootm_argv[3] = NULL; + } + } + + if (!bootm_argv[3]) + bootm_argv[3] = getenv("fdt_addr"); + + if (bootm_argv[3]) + 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); +#ifdef CONFIG_CMD_BOOTI + /* Try booting an AArch64 Linux kernel image */ + else + do_booti(cmdtp, 0, bootm_argc, bootm_argv); +#elif defined(CONFIG_CMD_BOOTZ) + /* Try booting a Image */ + else + do_bootz(cmdtp, 0, bootm_argc, bootm_argv); +#endif + unmap_sysmem(buf); + 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_ONTIMEOUT, + T_IPAPPEND, + 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}, + {"ontimeout", T_ONTIMEOUT,}, + {"ipappend", T_IPAPPEND,}, + {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 = 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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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; + + 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; +} + +/* + * 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_sliteral(c, &label->kernel); + 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_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(cmd_tbl_t *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. + */ +static 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. + */ +static struct pxe_menu *parse_pxefile(cmd_tbl_t *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, cfg->timeout, cfg->prompt, 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(cmd_tbl_t *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. + */ +static void handle_pxe_menu(cmd_tbl_t *cmdtp, struct pxe_menu *cfg) +{ + void *choice; + struct menu *m; + int err; + + 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); +} + +#ifdef CONFIG_CMD_NET +/* + * Boots a system using a pxe file + * + * Returns 0 on success, 1 on error. + */ +static int +do_pxe_boot(cmd_tbl_t *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 == NULL) { + 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 cmd_tbl_t cmd_pxe_sub[] = { + U_BOOT_CMD_MKENT(get, 1, 1, do_pxe_get, "", ""), + U_BOOT_CMD_MKENT(boot, 2, 1, do_pxe_boot, "", "") +}; + +static int do_pxe(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *cp; + + 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\npxe " + "boot [pxefile_addr_r] - boot from the pxe file at pxefile_addr_r\n" +); +#endif + +/* + * Boots a system using a local disk syslinux/extlinux file + * + * Returns 0 on success, 1 on error. + */ +static int do_sysboot(cmd_tbl_t *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 = getenv("bootfile"); + else { + filename = argv[5]; + setenv("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 == NULL) { + 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] [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/cmd/read.c b/cmd/read.c new file mode 100644 index 0000000..8710288 --- /dev/null +++ b/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 +#include +#include + +int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *ep; + block_dev_desc_t *dev_desc = NULL; + int dev; + int part = 0; + disk_partition_t 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 = 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 (get_partition_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 block_dev_desc_t. */ + limit = ~0; + } + + if (cnt + blk > limit) { + printf("Read out of range\n"); + return 1; + } + + if (dev_desc->block_read(dev_desc, offset + blk, cnt, addr) < 0) { + printf("Error reading blocks\n"); + return 1; + } + + return 0; +} + +U_BOOT_CMD( + read, 6, 0, do_read, + "Load binary data from a partition", + " addr blk# cnt" +); diff --git a/cmd/reginfo.c b/cmd/reginfo.c new file mode 100644 index 0000000..5f19e79 --- /dev/null +++ b/cmd/reginfo.c @@ -0,0 +1,245 @@ +/* + * (C) Copyright 2000 + * Subodh Nijsure, SkyStream Networks, snijsure@skystream.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#if defined(CONFIG_8xx) +#include +#elif defined (CONFIG_4xx) +extern void ppc4xx_reginfo(void); +#elif defined (CONFIG_5xx) +#include +#elif defined (CONFIG_MPC5200) +#include +#elif defined (CONFIG_MPC86xx) +extern void mpc86xx_reginfo(void); +#elif defined(CONFIG_MPC85xx) +extern void mpc85xx_reginfo(void); +#endif + +static int do_reginfo(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ +#if defined(CONFIG_8xx) + volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + volatile sysconf8xx_t *sysconf = &immap->im_siu_conf; + volatile sit8xx_t *timers = &immap->im_sit; + + /* Hopefully more PowerPC knowledgable people will add code to display + * other useful registers + */ + + printf ("\nSystem Configuration registers\n" + + "\tIMMR\t0x%08X\n", get_immr(0)); + + printf("\tSIUMCR\t0x%08X", sysconf->sc_siumcr); + printf("\tSYPCR\t0x%08X\n",sysconf->sc_sypcr); + + printf("\tSWT\t0x%08X", sysconf->sc_swt); + printf("\tSWSR\t0x%04X\n", sysconf->sc_swsr); + + printf("\tSIPEND\t0x%08X\tSIMASK\t0x%08X\n", + sysconf->sc_sipend, sysconf->sc_simask); + printf("\tSIEL\t0x%08X\tSIVEC\t0x%08X\n", + sysconf->sc_siel, sysconf->sc_sivec); + printf("\tTESR\t0x%08X\tSDCR\t0x%08X\n", + sysconf->sc_tesr, sysconf->sc_sdcr); + + printf ("Memory Controller Registers\n" + + "\tBR0\t0x%08X\tOR0\t0x%08X \n", memctl->memc_br0, memctl->memc_or0); + printf("\tBR1\t0x%08X\tOR1\t0x%08X \n", memctl->memc_br1, memctl->memc_or1); + printf("\tBR2\t0x%08X\tOR2\t0x%08X \n", memctl->memc_br2, memctl->memc_or2); + printf("\tBR3\t0x%08X\tOR3\t0x%08X \n", memctl->memc_br3, memctl->memc_or3); + printf("\tBR4\t0x%08X\tOR4\t0x%08X \n", memctl->memc_br4, memctl->memc_or4); + printf("\tBR5\t0x%08X\tOR5\t0x%08X \n", memctl->memc_br5, memctl->memc_or5); + printf("\tBR6\t0x%08X\tOR6\t0x%08X \n", memctl->memc_br6, memctl->memc_or6); + printf("\tBR7\t0x%08X\tOR7\t0x%08X \n", memctl->memc_br7, memctl->memc_or7); + printf ("\n" + "\tmamr\t0x%08X\tmbmr\t0x%08X \n", + memctl->memc_mamr, memctl->memc_mbmr ); + printf("\tmstat\t0x%08X\tmptpr\t0x%08X \n", + memctl->memc_mstat, memctl->memc_mptpr ); + printf("\tmdr\t0x%08X \n", memctl->memc_mdr); + + printf ("\nSystem Integration Timers\n" + "\tTBSCR\t0x%08X\tRTCSC\t0x%08X \n", + timers->sit_tbscr, timers->sit_rtcsc); + printf("\tPISCR\t0x%08X \n", timers->sit_piscr); + + /* + * May be some CPM info here? + */ + +#elif defined (CONFIG_4xx) + ppc4xx_reginfo(); +#elif defined(CONFIG_5xx) + + volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; + volatile memctl5xx_t *memctl = &immap->im_memctl; + volatile sysconf5xx_t *sysconf = &immap->im_siu_conf; + volatile sit5xx_t *timers = &immap->im_sit; + volatile car5xx_t *car = &immap->im_clkrst; + volatile uimb5xx_t *uimb = &immap->im_uimb; + + puts ("\nSystem Configuration registers\n"); + printf("\tIMMR\t0x%08X\tSIUMCR\t0x%08X \n", get_immr(0), sysconf->sc_siumcr); + printf("\tSYPCR\t0x%08X\tSWSR\t0x%04X \n" ,sysconf->sc_sypcr, sysconf->sc_swsr); + printf("\tSIPEND\t0x%08X\tSIMASK\t0x%08X \n", sysconf->sc_sipend, sysconf->sc_simask); + printf("\tSIEL\t0x%08X\tSIVEC\t0x%08X \n", sysconf->sc_siel, sysconf->sc_sivec); + printf("\tTESR\t0x%08X\n", sysconf->sc_tesr); + + puts ("\nMemory Controller Registers\n"); + printf("\tBR0\t0x%08X\tOR0\t0x%08X \n", memctl->memc_br0, memctl->memc_or0); + printf("\tBR1\t0x%08X\tOR1\t0x%08X \n", memctl->memc_br1, memctl->memc_or1); + printf("\tBR2\t0x%08X\tOR2\t0x%08X \n", memctl->memc_br2, memctl->memc_or2); + printf("\tBR3\t0x%08X\tOR3\t0x%08X \n", memctl->memc_br3, memctl->memc_or3); + printf("\tDMBR\t0x%08X\tDMOR\t0x%08X \n", memctl->memc_dmbr, memctl->memc_dmor ); + printf("\tMSTAT\t0x%08X\n", memctl->memc_mstat); + + puts ("\nSystem Integration Timers\n"); + printf("\tTBSCR\t0x%08X\tRTCSC\t0x%08X \n", timers->sit_tbscr, timers->sit_rtcsc); + printf("\tPISCR\t0x%08X \n", timers->sit_piscr); + + puts ("\nClocks and Reset\n"); + printf("\tSCCR\t0x%08X\tPLPRCR\t0x%08X \n", car->car_sccr, car->car_plprcr); + + puts ("\nU-Bus to IMB3 Bus Interface\n"); + printf("\tUMCR\t0x%08X\tUIPEND\t0x%08X \n", uimb->uimb_umcr, uimb->uimb_uipend); + puts ("\n\n"); + +#elif defined(CONFIG_MPC5200) + puts ("\nMPC5200 registers\n"); + printf ("MBAR=%08x\n", CONFIG_SYS_MBAR); + puts ("Memory map registers\n"); + printf ("\tCS0: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", + *(volatile ulong*)MPC5XXX_CS0_START, + *(volatile ulong*)MPC5XXX_CS0_STOP, + *(volatile ulong*)MPC5XXX_CS0_CFG, + (*(volatile ulong*)MPC5XXX_ADDECR & 0x00010000) ? 1 : 0); + printf ("\tCS1: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", + *(volatile ulong*)MPC5XXX_CS1_START, + *(volatile ulong*)MPC5XXX_CS1_STOP, + *(volatile ulong*)MPC5XXX_CS1_CFG, + (*(volatile ulong*)MPC5XXX_ADDECR & 0x00020000) ? 1 : 0); + printf ("\tCS2: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", + *(volatile ulong*)MPC5XXX_CS2_START, + *(volatile ulong*)MPC5XXX_CS2_STOP, + *(volatile ulong*)MPC5XXX_CS2_CFG, + (*(volatile ulong*)MPC5XXX_ADDECR & 0x00040000) ? 1 : 0); + printf ("\tCS3: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", + *(volatile ulong*)MPC5XXX_CS3_START, + *(volatile ulong*)MPC5XXX_CS3_STOP, + *(volatile ulong*)MPC5XXX_CS3_CFG, + (*(volatile ulong*)MPC5XXX_ADDECR & 0x00080000) ? 1 : 0); + printf ("\tCS4: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", + *(volatile ulong*)MPC5XXX_CS4_START, + *(volatile ulong*)MPC5XXX_CS4_STOP, + *(volatile ulong*)MPC5XXX_CS4_CFG, + (*(volatile ulong*)MPC5XXX_ADDECR & 0x00100000) ? 1 : 0); + printf ("\tCS5: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", + *(volatile ulong*)MPC5XXX_CS5_START, + *(volatile ulong*)MPC5XXX_CS5_STOP, + *(volatile ulong*)MPC5XXX_CS5_CFG, + (*(volatile ulong*)MPC5XXX_ADDECR & 0x00200000) ? 1 : 0); + printf ("\tCS6: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", + *(volatile ulong*)MPC5XXX_CS6_START, + *(volatile ulong*)MPC5XXX_CS6_STOP, + *(volatile ulong*)MPC5XXX_CS6_CFG, + (*(volatile ulong*)MPC5XXX_ADDECR & 0x04000000) ? 1 : 0); + printf ("\tCS7: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", + *(volatile ulong*)MPC5XXX_CS7_START, + *(volatile ulong*)MPC5XXX_CS7_STOP, + *(volatile ulong*)MPC5XXX_CS7_CFG, + (*(volatile ulong*)MPC5XXX_ADDECR & 0x08000000) ? 1 : 0); + printf ("\tBOOTCS: start %08lX\tstop %08lX\tconfig %08lX\ten %d\n", + *(volatile ulong*)MPC5XXX_BOOTCS_START, + *(volatile ulong*)MPC5XXX_BOOTCS_STOP, + *(volatile ulong*)MPC5XXX_BOOTCS_CFG, + (*(volatile ulong*)MPC5XXX_ADDECR & 0x02000000) ? 1 : 0); + printf ("\tSDRAMCS0: %08lX\n", + *(volatile ulong*)MPC5XXX_SDRAM_CS0CFG); + printf ("\tSDRAMCS1: %08lX\n", + *(volatile ulong*)MPC5XXX_SDRAM_CS1CFG); +#elif defined(CONFIG_MPC86xx) + mpc86xx_reginfo(); + +#elif defined(CONFIG_MPC85xx) + mpc85xx_reginfo(); + +#elif defined(CONFIG_BLACKFIN) + puts("\nSystem Configuration registers\n"); +#ifndef __ADSPBF60x__ + puts("\nPLL Registers\n"); + printf("\tPLL_DIV: 0x%04x PLL_CTL: 0x%04x\n", + bfin_read_PLL_DIV(), bfin_read_PLL_CTL()); + printf("\tPLL_STAT: 0x%04x PLL_LOCKCNT: 0x%04x\n", + bfin_read_PLL_STAT(), bfin_read_PLL_LOCKCNT()); + printf("\tVR_CTL: 0x%04x\n", bfin_read_VR_CTL()); + + puts("\nEBIU AMC Registers\n"); + printf("\tEBIU_AMGCTL: 0x%04x\n", bfin_read_EBIU_AMGCTL()); + printf("\tEBIU_AMBCTL0: 0x%08x EBIU_AMBCTL1: 0x%08x\n", + bfin_read_EBIU_AMBCTL0(), bfin_read_EBIU_AMBCTL1()); +# ifdef EBIU_MODE + printf("\tEBIU_MBSCTL: 0x%08x EBIU_ARBSTAT: 0x%08x\n", + bfin_read_EBIU_MBSCTL(), bfin_read_EBIU_ARBSTAT()); + printf("\tEBIU_MODE: 0x%08x EBIU_FCTL: 0x%08x\n", + bfin_read_EBIU_MODE(), bfin_read_EBIU_FCTL()); +# endif + +# ifdef EBIU_RSTCTL + puts("\nEBIU DDR Registers\n"); + printf("\tEBIU_DDRCTL0: 0x%08x EBIU_DDRCTL1: 0x%08x\n", + bfin_read_EBIU_DDRCTL0(), bfin_read_EBIU_DDRCTL1()); + printf("\tEBIU_DDRCTL2: 0x%08x EBIU_DDRCTL3: 0x%08x\n", + bfin_read_EBIU_DDRCTL2(), bfin_read_EBIU_DDRCTL3()); + printf("\tEBIU_DDRQUE: 0x%08x EBIU_RSTCTL 0x%04x\n", + bfin_read_EBIU_DDRQUE(), bfin_read_EBIU_RSTCTL()); + printf("\tEBIU_ERRADD: 0x%08x EBIU_ERRMST: 0x%04x\n", + bfin_read_EBIU_ERRADD(), bfin_read_EBIU_ERRMST()); +# else + puts("\nEBIU SDC Registers\n"); + printf("\tEBIU_SDRRC: 0x%04x EBIU_SDBCTL: 0x%04x\n", + bfin_read_EBIU_SDRRC(), bfin_read_EBIU_SDBCTL()); + printf("\tEBIU_SDSTAT: 0x%04x EBIU_SDGCTL: 0x%08x\n", + bfin_read_EBIU_SDSTAT(), bfin_read_EBIU_SDGCTL()); +# endif +#else + puts("\nCGU Registers\n"); + printf("\tCGU_DIV: 0x%08x CGU_CTL: 0x%08x\n", + bfin_read_CGU_DIV(), bfin_read_CGU_CTL()); + printf("\tCGU_STAT: 0x%08x CGU_LOCKCNT: 0x%08x\n", + bfin_read_CGU_STAT(), bfin_read_CGU_CLKOUTSEL()); + + puts("\nSMC DDR Registers\n"); + printf("\tDDR_CFG: 0x%08x DDR_TR0: 0x%08x\n", + bfin_read_DMC0_CFG(), bfin_read_DMC0_TR0()); + printf("\tDDR_TR1: 0x%08x DDR_TR2: 0x%08x\n", + bfin_read_DMC0_TR1(), bfin_read_DMC0_TR2()); + printf("\tDDR_MR: 0x%08x DDR_EMR1: 0x%08x\n", + bfin_read_DMC0_MR(), bfin_read_DMC0_EMR1()); + printf("\tDDR_CTL: 0x%08x DDR_STAT: 0x%08x\n", + bfin_read_DMC0_CTL(), bfin_read_DMC0_STAT()); + printf("\tDDR_DLLCTL:0x%08x\n", bfin_read_DMC0_DLLCTL()); +#endif +#endif /* CONFIG_BLACKFIN */ + + return 0; +} + + /**************************************************/ + +#if defined(CONFIG_CMD_REGINFO) +U_BOOT_CMD( + reginfo, 2, 1, do_reginfo, + "print register information", + "" +); +#endif diff --git a/cmd/regulator.c b/cmd/regulator.c new file mode 100644 index 0000000..bfea6e0 --- /dev/null +++ b/cmd/regulator.c @@ -0,0 +1,455 @@ +/* + * Copyright (C) 2014-2015 Samsung Electronics + * Przemyslaw Marczak + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include + +#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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct dm_regulator_uclass_platdata *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_platdata(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_platdata(struct udevice **devp, + struct dm_regulator_uclass_platdata **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_platdata(*devp); + if (!*uc_pdata) { + error("Regulator: %s - missing platform data!", 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct dm_regulator_uclass_platdata *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_platdata(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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + struct dm_regulator_mode *modes; + const char *parent_uc; + int mode_count; + int ret; + int i; + + ret = curr_dev_and_platdata(&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_platdata *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_platdata *pdata; + int current, value, mode; + const char *mode_name; + bool enabled; + + pdata = dev_get_uclass_platdata(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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + struct udevice *dev; + int ret; + + if (currdev && (argc < 2 || strcmp(argv[1], "-a"))) { + ret = curr_dev_and_platdata(&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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int value; + int force; + int ret; + + ret = curr_dev_and_platdata(&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; + } + + ret = regulator_set_value(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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int current; + int ret; + + ret = curr_dev_and_platdata(&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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int mode; + int ret; + + ret = curr_dev_and_platdata(&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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int ret; + + ret = curr_dev_and_platdata(&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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + struct dm_regulator_uclass_platdata *uc_pdata; + int ret; + + ret = curr_dev_and_platdata(&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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *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/cmd/reiser.c b/cmd/reiser.c new file mode 100644 index 0000000..8871564 --- /dev/null +++ b/cmd/reiser.c @@ -0,0 +1,171 @@ +/* + * (C) Copyright 2003 - 2004 + * Sysgo Real-Time Solutions, AG + * Pavel Bartusek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Reiserfs support + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CONFIG_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 (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *filename = "/"; + int dev, part; + block_dev_desc_t *dev_desc=NULL; + disk_partition_t info; + + if (argc < 3) + return CMD_RET_USAGE; + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) + return 1; + + if (argc == 4) { + filename = argv[3]; + } + + dev = dev_desc->dev; + 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 /)", + " [directory]\n" + " - list files from 'dev' on 'interface' in a 'directory'" +); + +/****************************************************************************** + * Reiserfs boot command intepreter. Derived from diskboot + */ +int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *filename = NULL; + int dev, part; + ulong addr = 0, filelen; + disk_partition_t info; + block_dev_desc_t *dev_desc = NULL; + unsigned long count; + char *addr_str; + + switch (argc) { + case 3: + addr_str = getenv("loadaddr"); + if (addr_str != NULL) { + addr = simple_strtoul (addr_str, NULL, 16); + } else { + addr = CONFIG_SYS_LOAD_ADDR; + } + filename = getenv ("bootfile"); + count = 0; + break; + case 4: + addr = simple_strtoul (argv[3], NULL, 16); + filename = getenv ("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 = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) + return 1; + + dev = dev_desc->dev; + + 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 */ + load_addr = addr; + + printf ("\n%ld bytes read\n", filelen); + setenv_hex("filesize", filelen); + + return filelen; +} + +U_BOOT_CMD( + reiserload, 6, 0, do_reiserload, + "load binary file from a Reiser filesystem", + " [addr] [filename] [bytes]\n" + " - load binary file 'filename' from 'dev' on 'interface'\n" + " to address 'addr' from dos filesystem" +); diff --git a/cmd/remoteproc.c b/cmd/remoteproc.c new file mode 100644 index 0000000..794a406 --- /dev/null +++ b/cmd/remoteproc.c @@ -0,0 +1,281 @@ +/* + * (C) Copyright 2015 + * Texas Instruments Incorporated - http://www.ti.com/ + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include + +/** + * 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_platdata(dev); + + 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, + 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(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (rproc_is_initialized()) { + printf("\tRemote Processors are already initialized\n"); + } else { + if (!rproc_init()) + return 0; + printf("Few Remote Processors failed to be initalized\n"); + } + + 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(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (!rproc_is_initialized()) { + printf("\t Remote Processors is not initialized\n"); + return CMD_RET_USAGE; + } + + 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(cmd_tbl_t *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, 3); + 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; + } + + if (!rproc_is_initialized()) { + printf("\tRemote Processors are not initialized\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(cmd_tbl_t *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, 3); + + if (!rproc_is_initialized()) { + printf("\tRemote Processors are not initialized\n"); + return CMD_RET_USAGE; + } + + 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 cmd_tbl_t cmd_remoteproc_sub[] = { + U_BOOT_CMD_MKENT(init, 0, 1, do_rproc_init, + "Enumerate and initialize all 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", + " [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(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + cmd_tbl_t *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 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 - Enumerate and initalize the remote processors\n" + "\tlist - list available remote processors\n" + "\tload [addr] [size]- Load the remote processor with binary\n" + "\t image stored at address [addr] in memory\n" + "\tstart - Start the remote processor(must be loaded)\n" + "\tstop - Stop the remote processor\n" + "\treset - Reset the remote processor\n" + "\tis_running - Reports if the remote processor is running\n" + "\tping - Ping the remote processor for communication\n"); diff --git a/cmd/sata.c b/cmd/sata.c new file mode 100644 index 0000000..76bacea --- /dev/null +++ b/cmd/sata.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2000-2005, DENX Software Engineering + * Wolfgang Denk + * Copyright (C) Procsys. All rights reserved. + * Mushtaq Khan + * + * Copyright (C) 2008 Freescale Semiconductor, Inc. + * Dave Liu + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +static int sata_curr_device = -1; +block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; + +static unsigned long sata_bread(block_dev_desc_t *block_dev, lbaint_t start, + lbaint_t blkcnt, void *dst) +{ + return sata_read(block_dev->dev, start, blkcnt, dst); +} + +static unsigned long sata_bwrite(block_dev_desc_t *block_dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + return sata_write(block_dev->dev, start, blkcnt, buffer); +} + +int __sata_initialize(void) +{ + int rc; + int i; + + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) { + memset(&sata_dev_desc[i], 0, sizeof(struct block_dev_desc)); + sata_dev_desc[i].if_type = IF_TYPE_SATA; + sata_dev_desc[i].dev = i; + sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + sata_dev_desc[i].type = DEV_TYPE_HARDDISK; + sata_dev_desc[i].lba = 0; + sata_dev_desc[i].blksz = 512; + sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); + sata_dev_desc[i].block_read = sata_bread; + sata_dev_desc[i].block_write = sata_bwrite; + + rc = init_sata(i); + if (!rc) { + rc = scan_sata(i); + if (!rc && (sata_dev_desc[i].lba > 0) && + (sata_dev_desc[i].blksz > 0)) + init_part(&sata_dev_desc[i]); + } + } + sata_curr_device = 0; + return rc; +} +int sata_initialize(void) __attribute__((weak,alias("__sata_initialize"))); + +__weak int __sata_stop(void) +{ + int i, err = 0; + + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) + err |= reset_sata(i); + + if (err) + printf("Could not reset some SATA devices\n"); + + return err; +} +int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); + +#ifdef CONFIG_PARTITIONS +block_dev_desc_t *sata_get_dev(int dev) +{ + return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; +} +#endif + +static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int rc = 0; + + if (argc == 2 && strcmp(argv[1], "stop") == 0) + return sata_stop(); + + if (argc == 2 && strcmp(argv[1], "init") == 0) { + if (sata_curr_device != -1) + sata_stop(); + + return sata_initialize(); + } + + /* If the user has not yet run `sata init`, do it now */ + if (sata_curr_device == -1) + if (sata_initialize()) + return 1; + + switch (argc) { + case 0: + case 1: + return CMD_RET_USAGE; + case 2: + if (strncmp(argv[1],"inf", 3) == 0) { + int i; + putc('\n'); + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) { + if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) + continue; + printf ("SATA device %d: ", i); + dev_print(&sata_dev_desc[i]); + } + return 0; + } else if (strncmp(argv[1],"dev", 3) == 0) { + if ((sata_curr_device < 0) || (sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE)) { + puts("\nno SATA devices available\n"); + return 1; + } + printf("\nSATA device %d: ", sata_curr_device); + dev_print(&sata_dev_desc[sata_curr_device]); + return 0; + } else if (strncmp(argv[1],"part",4) == 0) { + int dev, ok; + + for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) { + if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { + ++ok; + if (dev) + putc ('\n'); + print_part(&sata_dev_desc[dev]); + } + } + if (!ok) { + puts("\nno SATA devices available\n"); + rc ++; + } + return rc; + } + return CMD_RET_USAGE; + case 3: + if (strncmp(argv[1], "dev", 3) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + + printf("\nSATA device %d: ", dev); + if (dev >= CONFIG_SYS_SATA_MAX_DEVICE) { + puts ("unknown device\n"); + return 1; + } + dev_print(&sata_dev_desc[dev]); + + if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN) + return 1; + + sata_curr_device = dev; + + puts("... is now current device\n"); + + return 0; + } else if (strncmp(argv[1], "part", 4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + + if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { + print_part(&sata_dev_desc[dev]); + } else { + printf("\nSATA device %d not available\n", dev); + rc = 1; + } + return rc; + } + return CMD_RET_USAGE; + + default: /* at least 4 args */ + if (strcmp(argv[1], "read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + + printf("\nSATA read: device %d block # %ld, count %ld ... ", + sata_curr_device, blk, cnt); + + n = sata_read(sata_curr_device, blk, cnt, (u32 *)addr); + + /* flush cache after read */ + flush_cache(addr, cnt * sata_dev_desc[sata_curr_device].blksz); + + 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); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + + printf("\nSATA write: device %d block # %ld, count %ld ... ", + sata_curr_device, blk, cnt); + + n = sata_write(sata_curr_device, blk, cnt, (u32 *)addr); + + printf("%ld blocks written: %s\n", + n, (n == cnt) ? "OK" : "ERROR"); + return (n == cnt) ? 0 : 1; + } else { + return CMD_RET_USAGE; + } + + return rc; + } +} + +U_BOOT_CMD( + sata, 5, 1, do_sata, + "SATA sub system", + "init - init SATA sub system\n" + "sata stop - disable SATA sub system\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/cmd/scsi.c b/cmd/scsi.c new file mode 100644 index 0000000..bc7d1b6 --- /dev/null +++ b/cmd/scsi.c @@ -0,0 +1,733 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * SCSI support. + */ +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SCSI_DEV_LIST +#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST +#else +#ifdef CONFIG_SCSI_SYM53C8XX +#define SCSI_VEND_ID 0x1000 +#ifndef CONFIG_SCSI_DEV_ID +#define SCSI_DEV_ID 0x0001 +#else +#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID +#endif +#elif defined CONFIG_SATA_ULI5288 + +#define SCSI_VEND_ID 0x10b9 +#define SCSI_DEV_ID 0x5288 + +#elif !defined(CONFIG_SCSI_AHCI_PLAT) +#error no scsi device defined +#endif +#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} +#endif + +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) +const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; +#endif +static ccb tempccb; /* temporary scsi command buffer */ + +static unsigned char tempbuff[512]; /* temporary data buffer */ + +static int scsi_max_devs; /* number of highest available scsi device */ + +static int scsi_curr_dev; /* current device */ + +static block_dev_desc_t scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; + +/******************************************************************************** + * forward declerations of some Setup Routines + */ +void scsi_setup_test_unit_ready(ccb * pccb); +void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks); +void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks); +void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks); + +static void scsi_setup_write_ext(ccb *pccb, lbaint_t start, + unsigned short blocks); +void scsi_setup_inquiry(ccb * pccb); +void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); + + +static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, + unsigned long *blksz); +static ulong scsi_read(block_dev_desc_t *block_dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer); +static ulong scsi_write(block_dev_desc_t *block_dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer); + + +/********************************************************************************* + * (re)-scan the scsi bus and reports scsi device info + * to the user if mode = 1 + */ +void scsi_scan(int mode) +{ + unsigned char i,perq,modi,lun; + lbaint_t capacity; + unsigned long blksz; + ccb* pccb=(ccb *)&tempccb; + + if(mode==1) { + printf("scanning bus for devices...\n"); + } + for(i=0;itarget=i; + for(lun=0;lunlun=lun; + pccb->pdata=(unsigned char *)&tempbuff; + pccb->datalen=512; + scsi_setup_inquiry(pccb); + if (scsi_exec(pccb) != true) { + if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { + debug ("Selection timeout ID %d\n",pccb->target); + continue; /* selection timeout => assuming no device present */ + } + scsi_print_error(pccb); + continue; + } + perq=tempbuff[0]; + modi=tempbuff[1]; + if((perq & 0x1f)==0x1f) { + continue; /* skip unknown devices */ + } + if((modi&0x80)==0x80) /* drive is removable */ + scsi_dev_desc[scsi_max_devs].removable=true; + /* get info for this device */ + scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], + &tempbuff[8], 8); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0], + &tempbuff[16], 16); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], + &tempbuff[32], 4); + scsi_dev_desc[scsi_max_devs].target=pccb->target; + scsi_dev_desc[scsi_max_devs].lun=pccb->lun; + + pccb->datalen=0; + scsi_setup_test_unit_ready(pccb); + if (scsi_exec(pccb) != true) { + if (scsi_dev_desc[scsi_max_devs].removable == true) { + scsi_dev_desc[scsi_max_devs].type=perq; + goto removable; + } + scsi_print_error(pccb); + continue; + } + if (scsi_read_capacity(pccb, &capacity, &blksz)) { + scsi_print_error(pccb); + continue; + } + scsi_dev_desc[scsi_max_devs].lba=capacity; + scsi_dev_desc[scsi_max_devs].blksz=blksz; + scsi_dev_desc[scsi_max_devs].log2blksz = + LOG2(scsi_dev_desc[scsi_max_devs].blksz); + scsi_dev_desc[scsi_max_devs].type=perq; + init_part(&scsi_dev_desc[scsi_max_devs]); +removable: + if(mode==1) { + printf (" Device %d: ", scsi_max_devs); + dev_print(&scsi_dev_desc[scsi_max_devs]); + } /* if mode */ + scsi_max_devs++; + } /* next LUN */ + } + if(scsi_max_devs>0) + scsi_curr_dev=0; + else + scsi_curr_dev = -1; + + printf("Found %d device(s).\n", scsi_max_devs); +#ifndef CONFIG_SPL_BUILD + setenv_ulong("scsidevs", scsi_max_devs); +#endif +} + +int scsi_get_disk_count(void) +{ + return scsi_max_devs; +} + +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) +void scsi_init(void) +{ + int busdevfunc = -1; + int i; + /* + * Find a device from the list, this driver will support a single + * controller. + */ + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { + /* get PCI Device ID */ +#ifdef CONFIG_DM_PCI + struct udevice *dev; + int ret; + + ret = dm_pci_find_device(scsi_device_list[i].vendor, + scsi_device_list[i].device, 0, &dev); + if (!ret) { + busdevfunc = dm_pci_get_bdf(dev); + break; + } +#else + busdevfunc = pci_find_device(scsi_device_list[i].vendor, + scsi_device_list[i].device, + 0); +#endif + if (busdevfunc != -1) + break; + } + + if (busdevfunc == -1) { + printf("Error: SCSI Controller(s) "); + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { + printf("%04X:%04X ", + scsi_device_list[i].vendor, + scsi_device_list[i].device); + } + printf("not found\n"); + return; + } +#ifdef DEBUG + else { + printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", + scsi_device_list[i].vendor, + scsi_device_list[i].device, + (busdevfunc >> 16) & 0xFF, + (busdevfunc >> 11) & 0x1F, + (busdevfunc >> 8) & 0x7); + } +#endif + bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); + scsi_low_level_init(busdevfunc); + scsi_scan(1); + bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); +} +#endif + +#ifdef CONFIG_PARTITIONS +block_dev_desc_t * scsi_get_dev(int dev) +{ + return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; +} +#endif + +/****************************************************************************** + * scsi boot command intepreter. Derived from diskboot + */ +int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return common_diskboot(cmdtp, "scsi", argc, argv); +} + +/********************************************************************************* + * scsi command intepreter + */ +int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + switch (argc) { + case 0: + case 1: + return CMD_RET_USAGE; + + case 2: + if (strncmp(argv[1],"res",3) == 0) { + printf("\nReset SCSI\n"); + scsi_bus_reset(); + scsi_scan(1); + return 0; + } + if (strncmp(argv[1],"inf",3) == 0) { + int i; + for (i=0; i= CONFIG_SYS_SCSI_MAX_DEVICE)) { + printf("\nno SCSI devices available\n"); + return 1; + } + printf ("\n Device %d: ", scsi_curr_dev); + dev_print(&scsi_dev_desc[scsi_curr_dev]); + return 0; + } + if (strncmp(argv[1],"scan",4) == 0) { + scsi_scan(1); + return 0; + } + if (strncmp(argv[1],"part",4) == 0) { + int dev, ok; + for (ok=0, dev=0; dev= CONFIG_SYS_SCSI_MAX_DEVICE) { + printf("unknown device\n"); + return 1; + } + printf ("\n Device %d: ", dev); + dev_print(&scsi_dev_desc[dev]); + if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { + return 1; + } + scsi_curr_dev = dev; + printf("... is now current device\n"); + return 0; + } + if (strncmp(argv[1],"part",4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { + print_part(&scsi_dev_desc[dev]); + } + else { + printf ("\nSCSI device %d not available\n", dev); + } + return 1; + } + return CMD_RET_USAGE; + default: + /* at least 4 args */ + if (strcmp(argv[1],"read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + printf ("\nSCSI read: device %d block # %ld, count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_read(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); + return 0; + } else if (strcmp(argv[1], "write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + printf("\nSCSI write: device %d block # %ld, " + "count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_write(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf("%ld blocks written: %s\n", n, + (n == cnt) ? "OK" : "ERROR"); + return 0; + } + } /* switch */ + return CMD_RET_USAGE; +} + +/**************************************************************************************** + * scsi_read + */ + +/* almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_READ_BLK 0xFFFF +#define SCSI_LBA48_READ 0xFFFFFFF + +static ulong scsi_read(block_dev_desc_t *block_dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +{ + int device = block_dev->dev; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks = 0; + ccb* pccb=(ccb *)&tempccb; + device&=0xff; + /* Setup device + */ + pccb->target=scsi_dev_desc[device].target; + pccb->lun=scsi_dev_desc[device].lun; + buf_addr=(unsigned long)buffer; + start=blknr; + blks=blkcnt; + debug("\nscsi_read: dev %d startblk " LBAF + ", blccnt " LBAF " buffer %lx\n", + device, start, blks, (unsigned long)buffer); + do { + pccb->pdata=(unsigned char *)buf_addr; +#ifdef CONFIG_SYS_64BIT_LBA + if (start > SCSI_LBA48_READ) { + unsigned long blocks; + blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); + pccb->datalen = scsi_dev_desc[device].blksz * blocks; + scsi_setup_read16(pccb, start, blocks); + start += blocks; + blks -= blocks; + } else +#endif + if (blks > SCSI_MAX_READ_BLK) { + pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; + smallblks=SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb,start,smallblks); + start+=SCSI_MAX_READ_BLK; + blks-=SCSI_MAX_READ_BLK; + } + else { + pccb->datalen=scsi_dev_desc[device].blksz * blks; + smallblks=(unsigned short) blks; + scsi_setup_read_ext(pccb,start,smallblks); + start+=blks; + blks=0; + } + debug("scsi_read_ext: startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", + start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt-=blks; + break; + } + buf_addr+=pccb->datalen; + } while(blks!=0); + debug("scsi_read_ext: end startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); + return(blkcnt); +} + +/******************************************************************************* + * scsi_write + */ + +/* Almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_WRITE_BLK 0xFFFF + +static ulong scsi_write(block_dev_desc_t *block_dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +{ + int device = block_dev->dev; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks; + ccb* pccb = (ccb *)&tempccb; + device &= 0xff; + /* Setup device + */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + __func__, device, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; + if (blks > SCSI_MAX_WRITE_BLK) { + pccb->datalen = (scsi_dev_desc[device].blksz * + SCSI_MAX_WRITE_BLK); + smallblks = SCSI_MAX_WRITE_BLK; + scsi_setup_write_ext(pccb, start, smallblks); + start += SCSI_MAX_WRITE_BLK; + blks -= SCSI_MAX_WRITE_BLK; + } else { + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_write_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + return blkcnt; +} + +/* copy src to dest, skipping leading and trailing blanks + * and null terminate the string + */ +void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len) +{ + int start,end; + + start=0; + while(startstart) { + if(src[end]!=' ') + break; + end--; + } + for( ; start<=end; start++) { + *dest++=src[start]; + } + *dest='\0'; +} + + +/* Trim trailing blanks, and NUL-terminate string + */ +void scsi_trim_trail (unsigned char *str, unsigned int len) +{ + unsigned char *p = str + len - 1; + + while (len-- > 0) { + *p-- = '\0'; + if (*p != ' ') { + return; + } + } +} + +int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) +{ + *capacity = 0; + + memset(pccb->cmd, 0, sizeof(pccb->cmd)); + pccb->cmd[0] = SCSI_RD_CAPAC10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + + pccb->datalen = 8; + if (scsi_exec(pccb) != true) + return 1; + + *capacity = ((lbaint_t)pccb->pdata[0] << 24) | + ((lbaint_t)pccb->pdata[1] << 16) | + ((lbaint_t)pccb->pdata[2] << 8) | + ((lbaint_t)pccb->pdata[3]); + + if (*capacity != 0xffffffff) { + /* Read capacity (10) was sufficient for this drive. */ + *blksz = ((unsigned long)pccb->pdata[4] << 24) | + ((unsigned long)pccb->pdata[5] << 16) | + ((unsigned long)pccb->pdata[6] << 8) | + ((unsigned long)pccb->pdata[7]); + return 0; + } + + /* Read capacity (10) was insufficient. Use read capacity (16). */ + + memset(pccb->cmd, 0, sizeof(pccb->cmd)); + pccb->cmd[0] = SCSI_RD_CAPAC16; + pccb->cmd[1] = 0x10; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + + pccb->datalen = 16; + if (scsi_exec(pccb) != true) + return 1; + + *capacity = ((uint64_t)pccb->pdata[0] << 56) | + ((uint64_t)pccb->pdata[1] << 48) | + ((uint64_t)pccb->pdata[2] << 40) | + ((uint64_t)pccb->pdata[3] << 32) | + ((uint64_t)pccb->pdata[4] << 24) | + ((uint64_t)pccb->pdata[5] << 16) | + ((uint64_t)pccb->pdata[6] << 8) | + ((uint64_t)pccb->pdata[7]); + + *blksz = ((uint64_t)pccb->pdata[8] << 56) | + ((uint64_t)pccb->pdata[9] << 48) | + ((uint64_t)pccb->pdata[10] << 40) | + ((uint64_t)pccb->pdata[11] << 32) | + ((uint64_t)pccb->pdata[12] << 24) | + ((uint64_t)pccb->pdata[13] << 16) | + ((uint64_t)pccb->pdata[14] << 8) | + ((uint64_t)pccb->pdata[15]); + + return 0; +} + + +/************************************************************************************ + * Some setup (fill-in) routines + */ +void scsi_setup_test_unit_ready(ccb * pccb) +{ + pccb->cmd[0]=SCSI_TST_U_RDY; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=0; + pccb->cmd[3]=0; + pccb->cmd[4]=0; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ +} + +#ifdef CONFIG_SYS_64BIT_LBA +void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) +{ + pccb->cmd[0] = SCSI_READ16; + pccb->cmd[1] = pccb->lun<<5; + pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; + pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; + pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; + pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; + pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; + pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; + pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; + pccb->cmd[9] = ((unsigned char) (start)) & 0xff; + pccb->cmd[10] = 0; + pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; + pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; + pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; + pccb->cmd[14] = (unsigned char) blocks & 0xff; + pccb->cmd[15] = 0; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read16: cmd: %02X %02X " + "startblk %02X%02X%02X%02X%02X%02X%02X%02X " + "blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); +} +#endif + +void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0]=SCSI_READ10; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=((unsigned char) (start>>24))&0xff; + pccb->cmd[3]=((unsigned char) (start>>16))&0xff; + pccb->cmd[4]=((unsigned char) (start>>8))&0xff; + pccb->cmd[5]=((unsigned char) (start))&0xff; + pccb->cmd[6]=0; + pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; + pccb->cmd[8]=(unsigned char) blocks & 0xff; + pccb->cmd[6]=0; + pccb->cmdlen=10; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + pccb->cmd[0],pccb->cmd[1], + pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], + pccb->cmd[7],pccb->cmd[8]); +} + +void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_WRITE10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; + pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; + pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; + pccb->cmd[5] = ((unsigned char) (start)) & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[9] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + __func__, + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[7], pccb->cmd[8]); +} + +void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0]=SCSI_READ6; + pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); + pccb->cmd[2]=((unsigned char) (start>>8))&0xff; + pccb->cmd[3]=((unsigned char) (start))&0xff; + pccb->cmd[4]=(unsigned char) blocks & 0xff; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", + pccb->cmd[0],pccb->cmd[1], + pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]); +} + + +void scsi_setup_inquiry(ccb * pccb) +{ + pccb->cmd[0]=SCSI_INQUIRY; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=0; + pccb->cmd[3]=0; + if(pccb->datalen>255) + pccb->cmd[4]=255; + else + pccb->cmd[4]=(unsigned char)pccb->datalen; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ +} + + +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/cmd/setexpr.c b/cmd/setexpr.c new file mode 100644 index 0000000..e7194fc --- /dev/null +++ b/cmd/setexpr.c @@ -0,0 +1,398 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * Copyright 2013 Wolfgang Denk + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * This file provides a shell like 'expr' function to return. + */ + +#include +#include +#include +#include + +static ulong get_arg(char *s, int w) +{ + /* + * 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; + + addr = simple_strtoul(&s[1], NULL, 16); + switch (w) { + case 1: + p = map_sysmem(addr, sizeof(uchar)); + val = (ulong)*(uchar *)p; + unmap_sysmem(p); + return val; + case 2: + p = map_sysmem(addr, sizeof(ushort)); + val = (ulong)*(ushort *)p; + unmap_sysmem(p); + return val; + case 4: + default: + p = map_sysmem(addr, sizeof(ulong)); + val = *p; + unmap_sysmem(p); + return val; + } + } else { + return simple_strtoul(s, NULL, 16); + } +} + +#ifdef CONFIG_REGEX + +#include + +#define SLRE_BUFSZ 16384 +#define SLRE_PATSZ 4096 + +/* + * 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; +} + +static char *substitute(char *string, /* string buffer */ + int *slen, /* current string length */ + int ssize, /* string bufer size */ + const char *old,/* old (replaced) string */ + int olen, /* length of old string */ + const char *new,/* new (replacement) string */ + int nlen) /* length of new string */ +{ + 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 substitue */ + memcpy(p, new, nlen); + + *slen += nlen - olen; + + return p + nlen; +} + +/* + * Perform regex operations on a environment variable + * + * Returns 0 if OK, 1 in case of errors. + */ +static int regex_sub(const char *name, + const char *r, const char *s, const char *t, + int global) +{ + struct slre slre; + char data[SLRE_BUFSZ]; + char *datap = data; + const char *value; + int res, len, nlen, loop; + + if (name == NULL) + return 1; + + if (slre_compile(&slre, r) == 0) { + printf("Error compiling regex: %s\n", slre.err_str); + return 1; + } + + if (t == NULL) { + value = getenv(name); + + if (value == NULL) { + 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 : "", 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); + + if (s == NULL) + nlen = 0; + else + nlen = strlen(s); + + for (loop = 0;; loop++) { + struct cap caps[slre.num_caps + 2]; + char nbuf[SLRE_PATSZ]; + const char *old; + char *np; + int i, olen; + + (void) memset(caps, 0, sizeof(caps)); + + res = slre_match(&slre, datap, len, 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", t); + return 1; + } else { + break; + } + } + + debug("## MATCH ## %s\n", data); + + if (s == NULL) { + printf("%s=%s\n", name, t); + return 1; + } + + old = caps[0].ptr; + olen = caps[0].len; + + if (nlen + 1 >= SLRE_PATSZ) { + printf("## error: pattern buffer overflow: have %d, need %d\n", + SLRE_BUFSZ, 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, + SLRE_PATSZ, + backref, 2, + caps[i].ptr, caps[i].len); + + if (np == NULL) + return 1; + } + } + debug("## SUBST(2) ## %s\n", nbuf); + + datap = substitute(datap, &len, SLRE_BUFSZ, + 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 setenv()) : %s\n", data); + + printf("%s=%s\n", name, data); + + return setenv(name, data); +} +#endif + +static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + ulong a, b; + ulong value; + 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); + + a = get_arg(argv[2], w); + + /* plain assignment: "setexpr name value" */ + if (argc == 3) { + setenv_hex(argv[1], a); + return 0; + } + + /* 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(argv[1], argv[3], argv[4], argv[5], 1); + + if (strcmp(argv[2], "sub") == 0) + return regex_sub(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; + + b = get_arg(argv[4], w); + + 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; + } + + setenv_hex(argv[1], value); + + return 0; +} + +U_BOOT_CMD( + setexpr, 6, 0, do_setexpr, + "set environment variable as the result of eval expression", + "[.b, .w, .l] name [*]value1 [*]value2\n" + " - set environment variable 'name' to the result of the evaluated\n" + " expression specified by . can be &, |, ^, +, -, *, /, %\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 in the\n" + " string , substitute the string . The result is\n" + " assigned to . If is not supplied, use the old\n" + " value of \n" + "setexpr name sub r s [t]\n" + " - Just like gsub(), but replace only the first matching substring" +#endif +); diff --git a/cmd/sf.c b/cmd/sf.c new file mode 100644 index 0000000..42862d9 --- /dev/null +++ b/cmd/sf.c @@ -0,0 +1,618 @@ +/* + * Command for accessing SPI flash. + * + * Copyright (C) 2008 Atmel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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. offset len - operate on <'offset', 'len') + * 2. 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; + unsigned int speed = CONFIG_SF_DEFAULT_SPEED; + unsigned int mode = CONFIG_SF_DEFAULT_MODE; + char *endp; +#ifdef CONFIG_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; + } + +#ifdef CONFIG_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); + device_unbind(new); + } + 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; + } + + flash = new; +#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) { + 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: %s\n", (size_t)size, (u32)offset, + ret ? "ERROR" : "OK"); + + 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: %d 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 i; + + printf("SPI flash test:\n"); + memset(&test, '\0', sizeof(test)); + test.base_ms = get_timer(0); + test.bytes = len; + if (spi_flash_erase(flash, offset, len)) { + printf("Erase failed\n"); + return -1; + } + spi_test_next_stage(&test); + + if (spi_flash_read(flash, offset, len, vbuf)) { + printf("Check read failed\n"); + 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); + + if (spi_flash_write(flash, offset, len, buf)) { + printf("Write failed\n"); + return -1; + } + memset(vbuf, '\0', len); + spi_test_next_stage(&test); + + if (spi_flash_read(flash, offset, len, vbuf)) { + printf("Read failed\n"); + 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(cmd_tbl_t *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/cmd/sha1sum.c b/cmd/sha1sum.c new file mode 100644 index 0000000..783ea2e --- /dev/null +++ b/cmd/sha1sum.c @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2011 + * Joe Hershberger, National Instruments, joe.hershberger@ni.com + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +int do_sha1sum(cmd_tbl_t *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/cmd/softswitch.c b/cmd/softswitch.c new file mode 100644 index 0000000..f75d926 --- /dev/null +++ b/cmd/softswitch.c @@ -0,0 +1,41 @@ +/* + * cmd_softswitch.c - set the softswitch for bf60x + * + * Copyright (c) 2012 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include + +int do_softswitch(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int switchaddr, value, pin, port; + + if (argc != 5) + return CMD_RET_USAGE; + + if (strcmp(argv[2], "GPA") == 0) + port = IO_PORT_A; + else if (strcmp(argv[2], "GPB") == 0) + port = IO_PORT_B; + else + return CMD_RET_USAGE; + + switchaddr = simple_strtoul(argv[1], NULL, 16); + pin = simple_strtoul(argv[3], NULL, 16); + value = simple_strtoul(argv[4], NULL, 16); + + config_switch_bit(switchaddr, port, (1 << pin), IO_PORT_OUTPUT, value); + + return 0; +} + +U_BOOT_CMD( + softswitch_output, 5, 1, do_softswitch, + "switchaddr GPA/GPB pin_offset value", + "" +); diff --git a/cmd/sound.c b/cmd/sound.c new file mode 100644 index 0000000..f5dd8bc --- /dev/null +++ b/cmd/sound.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * Rajeshwari Shinde + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* Initilaise sound subsystem */ +static int do_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int ret; + + ret = sound_init(gd->fdt_blob); + if (ret) { + printf("Initialise Audio driver failed\n"); + return CMD_RET_FAILURE; + } + + return 0; +} + +/* play sound from buffer */ +static int do_play(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + 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 = sound_play(msec, freq); + if (ret) { + printf("play failed"); + return CMD_RET_FAILURE; + } + + return 0; +} + +static cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + cmd_tbl_t *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/cmd/source.c b/cmd/source.c new file mode 100644 index 0000000..db7ab7e --- /dev/null +++ b/cmd/source.c @@ -0,0 +1,188 @@ +/* + * (C) Copyright 2001 + * Kyle Harris, kharris@nexus-tech.net + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_8xx) +#include +#endif + +int +source (ulong addr, const char *fit_uname) +{ + ulong len; +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + 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 = getenv_yesno ("verify"); + + buf = map_sysmem(addr, 0); + switch (genimg_get_format(buf)) { +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + 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: + if (fit_uname == NULL) { + puts ("No FIT subimage unit name\n"); + return 1; + } + + fit_hdr = buf; + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT image format\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(cmd_tbl_t *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], 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 = source (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:" +#endif + ""; +#endif + +U_BOOT_CMD( + source, 2, 0, do_source, + "run script from memory", source_help_text +); +#endif diff --git a/cmd/spi.c b/cmd/spi.c new file mode 100644 index 0000000..64c3ffc --- /dev/null +++ b/cmd/spi.c @@ -0,0 +1,174 @@ +/* + * (C) Copyright 2002 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * SPI Read/Write Utilities + */ + +#include +#include +#include +#include +#include + +/*----------------------------------------------------------------------- + * Definitions + */ + +#ifndef MAX_SPI_BYTES +# define MAX_SPI_BYTES 32 /* Maximum number of bytes we can handle */ +#endif + +#ifndef CONFIG_DEFAULT_SPI_BUS +# define CONFIG_DEFAULT_SPI_BUS 0 +#endif +#ifndef CONFIG_DEFAULT_SPI_MODE +# define CONFIG_DEFAULT_SPI_MODE SPI_MODE_0 +#endif + +/* + * Values from last command. + */ +static unsigned int bus; +static unsigned int cs; +static unsigned int mode; +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; + +#ifdef CONFIG_DM_SPI + char name[30], *str; + struct udevice *dev; + + snprintf(name, sizeof(name), "generic_%d:%d", bus, cs); + str = strdup(name); + ret = spi_get_bus_and_cs(bus, cs, 1000000, mode, "spi_generic_drv", + str, &dev, &slave); + if (ret) + return ret; +#else + slave = spi_setup_slave(bus, cs, 1000000, 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); +#ifndef CONFIG_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); +#ifndef CONFIG_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 (cmd_tbl_t *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 ((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, NULL, 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", + "[:][.] - Send and receive bits\n" + " - Identifies the SPI bus\n" + " - Identifies the chip select\n" + " - Identifies the SPI mode to use\n" + " - Number of bits to send (base 10)\n" + " - Hexadecimal string that gets sent" +); diff --git a/cmd/spibootldr.c b/cmd/spibootldr.c new file mode 100644 index 0000000..ca76dde --- /dev/null +++ b/cmd/spibootldr.c @@ -0,0 +1,37 @@ +/* + * U-boot - spibootldr.c + * + * Copyright (c) 2005-2008 Analog Devices Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include + +#include +#include + +int do_spibootldr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + s32 addr; + + /* Get the address */ + if (argc < 2) + addr = 0; + else + addr = simple_strtoul(argv[1], NULL, 16); + + printf("## Booting ldr image at SPI offset 0x%x ...\n", addr); + + return bfrom_SpiBoot(addr, BFLAG_PERIPHERAL | 4, 0, NULL); +} + +U_BOOT_CMD( + spibootldr, 2, 0, do_spibootldr, + "boot ldr image from spi", + "[offset]\n" + " - boot ldr image stored at offset into spi\n"); diff --git a/cmd/spl.c b/cmd/spl.c new file mode 100644 index 0000000..057764a --- /dev/null +++ b/cmd/spl.c @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const cmd_tbl_t *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) && ((int)c->cmd <= SPL_EXPORT_LAST)) { + argc -= 2; + argv += 2; + if (call_bootm(argc, argv, subcmd_list[(int)c->cmd])) + return -1; + switch ((int)c->cmd) { +#ifdef CONFIG_OF_LIBFDT + case SPL_EXPORT_FDT: + printf("Argument image is now in RAM: 0x%p\n", + (void *)images.ft_addr); + 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 cmd_tbl_t cmd_spl_sub[] = { + U_BOOT_CMD_MKENT(export, 0, 1, (void *)SPL_EXPORT, "", ""), +}; + +static int do_spl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const cmd_tbl_t *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 = (int)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 [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/cmd/strings.c b/cmd/strings.c new file mode 100644 index 0000000..41b1665 --- /dev/null +++ b/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 +#include +#include + +static char *start_addr, *last_addr; + +int do_strings(cmd_tbl_t *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", + " [byte count]\n" + " - display strings at for at least [byte count] or first double NUL" +); diff --git a/cmd/terminal.c b/cmd/terminal.c new file mode 100644 index 0000000..4b9c0b3 --- /dev/null +++ b/cmd/terminal.c @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2007 OpenMoko, Inc. + * Written by Harald Welte + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * Boot support + */ +#include +#include +#include +#include + +int do_terminal(cmd_tbl_t * 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; + + 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()) { + c = stdio_devices[0]->getc(); + if (last_tilde == 1) { + if (c == '.') { + putc(c); + putc('\n'); + break; + } else { + last_tilde = 0; + /* write the delayed tilde */ + dev->putc('~'); + /* fall-through to print current + * character */ + } + } + if (c == '~') { + last_tilde = 1; + puts("[u-boot]"); + putc(c); + } + dev->putc(c); + } + + /* read from serial port and display on console */ + if (dev->tstc()) { + c = dev->getc(); + putc(c); + } + } + return 0; +} + + +/***************************************************/ + +U_BOOT_CMD( + terminal, 3, 1, do_terminal, + "start terminal emulator", + "" +); diff --git a/cmd/test.c b/cmd/test.c new file mode 100644 index 0000000..7285f75 --- /dev/null +++ b/cmd/test.c @@ -0,0 +1,214 @@ +/* + * Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#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(cmd_tbl_t *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, 10) == + simple_strtol(ap[2], NULL, 10); + break; + case OP_INT_NEQ: + expr = simple_strtol(ap[0], NULL, 10) != + simple_strtol(ap[2], NULL, 10); + break; + case OP_INT_LT: + expr = simple_strtol(ap[0], NULL, 10) < + simple_strtol(ap[2], NULL, 10); + break; + case OP_INT_LE: + expr = simple_strtol(ap[0], NULL, 10) <= + simple_strtol(ap[2], NULL, 10); + break; + case OP_INT_GT: + expr = simple_strtol(ap[0], NULL, 10) > + simple_strtol(ap[2], NULL, 10); + break; + case OP_INT_GE: + expr = simple_strtol(ap[0], NULL, 10) >= + simple_strtol(ap[2], NULL, 10); + 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(cmd_tbl_t *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(cmd_tbl_t *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/cmd/thordown.c b/cmd/thordown.c new file mode 100644 index 0000000..436b7f5 --- /dev/null +++ b/cmd/thordown.c @@ -0,0 +1,72 @@ +/* + * cmd_thordown.c -- USB TIZEN "THOR" Downloader gadget + * + * Copyright (C) 2013 Lukasz Majewski + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +int do_thor_down(cmd_tbl_t *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 = board_usb_init(controller_index, USB_INIT_DEVICE); + if (ret) { + error("USB init failed: %d", ret); + ret = CMD_RET_FAILURE; + goto exit; + } + + g_dnl_register("usb_dnl_thor"); + + ret = thor_init(); + if (ret) { + error("THOR DOWNLOAD failed: %d", ret); + ret = CMD_RET_FAILURE; + goto exit; + } + + ret = thor_handle(); + if (ret) { + error("THOR failed: %d", ret); + ret = CMD_RET_FAILURE; + goto exit; + } + +exit: + g_dnl_unregister(); + board_usb_cleanup(controller_index, USB_INIT_DEVICE); +done: + dfu_free_entities(); + + return ret; +} + +U_BOOT_CMD(thordown, CONFIG_SYS_MAXARGS, 1, do_thor_down, + "TIZEN \"THOR\" downloader", + " \n" + " - device software upgrade via LTHOR TIZEN dowload\n" + " program via on device ,\n" + " attached to interface \n" +); diff --git a/cmd/time.c b/cmd/time.c new file mode 100644 index 0000000..de57e3b --- /dev/null +++ b/cmd/time.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + ulong cycles = 0; + int retval = 0; + int repeatable; + + 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/cmd/tpm.c b/cmd/tpm.c new file mode 100644 index 0000000..add6bfb --- /dev/null +++ b/cmd/tpm.c @@ -0,0 +1,802 @@ +/* + * Copyright (c) 2013 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Useful constants */ +enum { + DIGEST_LENGTH = 20, + /* max lengths, valid for RSA keys <= 2048 bits */ + TPM_PUBKEY_MAX_LENGTH = 288, +}; + +/** + * 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 + */ +static void print_byte_string(uint8_t *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 + */ +static void *parse_byte_string(char *bytes, uint8_t *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] = (uint8_t)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 + */ +static 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 + */ +static 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. + */ +static 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 + */ +static void *type_string_alloc(const char *type_str, uint32_t *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 + */ +static int type_string_pack(const char *type_str, char * const values[], + uint8_t *data) +{ + size_t offset; + uint32_t 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 + */ +static int type_string_write_vars(const char *type_str, uint8_t *data, + char * const vars[]) +{ + size_t offset; + uint32_t 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 (setenv_ulong(*vars, value)) + return -1; + } + + return 0; +} + +static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + enum tpm_startup_type mode; + + 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(mode)); +} + +static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t index, perm, size; + + 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(tpm_nv_define_space(index, perm, size)); +} + +static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t index, count, rc; + void *data; + + 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(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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t index, rc; + size_t count; + void *data; + + 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(index, data, count); + free(data); + + return report_return_code(rc); +} + +static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t index, rc; + uint8_t in_digest[20], out_digest[20]; + + 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_extend(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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t index, count, rc; + void *data; + + 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(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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint16_t presence; + + if (argc != 2) + return CMD_RET_USAGE; + presence = (uint16_t)simple_strtoul(argv[1], NULL, 0); + + return report_return_code(tpm_tsc_physical_presence(presence)); +} + +static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t count, rc; + void *data; + + 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(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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint8_t state; + + if (argc != 2) + return CMD_RET_USAGE; + state = (uint8_t)simple_strtoul(argv[1], NULL, 0); + + return report_return_code(tpm_physical_set_deactivated(state)); +} + +static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t cap_area, sub_cap, rc; + void *cap; + size_t count; + + 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(cap_area, sub_cap, cap, count); + if (!rc) { + puts("capability information:\n"); + print_byte_string(cap, count); + } + + return report_return_code(rc); +} + +#define TPM_COMMAND_NO_ARG(cmd) \ +static int do_##cmd(cmd_tbl_t *cmdtp, int flag, \ + int argc, char * const argv[]) \ +{ \ + if (argc != 1) \ + return CMD_RET_USAGE; \ + return report_return_code(cmd()); \ +} + +TPM_COMMAND_NO_ARG(tpm_init) +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 int get_tpm(struct udevice **devp) +{ + int rc; + + rc = uclass_first_device(UCLASS_TPM, devp); + if (rc) { + printf("Could not find TPM (ret=%d)\n", rc); + return CMD_RET_FAILURE; + } + + return 0; +} + +static int do_tpm_info(cmd_tbl_t *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; +} + +static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + struct udevice *dev; + void *command; + uint8_t response[1024]; + size_t count, response_length = sizeof(response); + uint32_t 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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t index, perm, size; + + 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(tpm_nv_define_space(index, perm, size)); +} + +static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t index, count, err; + void *data; + + 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(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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t index, count, err; + void *data; + + 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(index, data, count); + free(data); + + return report_return_code(err); +} + +#ifdef CONFIG_TPM_AUTH_SESSIONS + +static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t auth_handle, err; + + err = tpm_oiap(&auth_handle); + + return report_return_code(err); +} + +static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t parent_handle, key_len, key_handle, err; + uint8_t usage_auth[DIGEST_LENGTH]; + void *key; + + 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 = tpm_load_key2_oiap(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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + uint32_t key_handle, err; + uint8_t usage_auth[DIGEST_LENGTH]; + uint8_t pub_key_buffer[TPM_PUBKEY_MAX_LENGTH]; + size_t pub_key_len = sizeof(pub_key_buffer); + + 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 = tpm_get_pub_key_oiap(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(tpm_end_oiap) + +#endif /* CONFIG_TPM_AUTH_SESSIONS */ + +#define MAKE_TPM_CMD_ENTRY(cmd) \ + U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "") + +static cmd_tbl_t tpm_commands[] = { + 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_tpm_end_oiap, "", ""), + U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1, + do_tpm_load_key2_oiap, "", ""), + U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1, + do_tpm_get_pub_key_oiap, "", ""), +#endif /* CONFIG_TPM_AUTH_SESSIONS */ +}; + +static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *tpm_cmd; + + if (argc < 2) + return CMD_RET_USAGE; + tpm_cmd = find_cmd_tbl(argv[1], tpm_commands, ARRAY_SIZE(tpm_commands)); + if (!tpm_cmd) + return CMD_RET_USAGE; + + return tpm_cmd->cmd(cmdtp, flag, argc - 1, argv + 1); +} + +U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, +"Issue a TPM command", +"cmd args...\n" +" - Issue TPM command with arguments .\n" +"Admin Startup and State Commands:\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. 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 .\n" +"The Capability Commands:\n" +" get_capability cap_area sub_cap addr count\n" +" - Read bytes of TPM capability indexed by and\n" +" to memory address .\n" +#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 , bytes\n" +" into TPM using the parent key with authorization\n" +" (20 bytes hex string).\n" +" get_pub_key_oiap key_handle usage_auth\n" +" - get the public key portion of a loaded key using\n" +" authorization (20 bytes hex string)\n" +#endif /* CONFIG_TPM_AUTH_SESSIONS */ +"Endorsement Key Handling Commands:\n" +" read_pubek addr count\n" +" - Read bytes of the public endorsement key to memory\n" +" address \n" +"Integrity Collection and Reporting Commands:\n" +" extend index digest_hex_string\n" +" - Add a new measurement to a PCR. Update PCR with the 20-bytes\n" +" \n" +" pcr_read index addr count\n" +" - Read bytes from PCR to memory address .\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 with of bytes.\n" +" nv_read_value index addr count\n" +" - Read bytes from space to memory address .\n" +" nv_write_value index addr count\n" +" - Write bytes from memory address to space .\n" +"Miscellaneous helper functions:\n" +" raw_transfer byte_string\n" +" - Send a 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 with permission .\n" +" nv_read types_string index vars...\n" +" - Read from space to environment variables .\n" +" nv_write types_string index values...\n" +" - Write to space from values .\n" +); diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c new file mode 100644 index 0000000..65332d1 --- /dev/null +++ b/cmd/tpm_test.c @@ -0,0 +1,564 @@ +/* + * Copyright (c) 2015 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +/* 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(void) +{ + uint32_t result = tpm_startup(TPM_ST_CLEAR); + + return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result; +} + +static int test_timer(void) +{ + printf("get_timer(0) = %lu\n", get_timer(0)); + return 0; +} + +static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated, + uint8_t *nvlocked) +{ + struct tpm_permanent_flags pflags; + uint32_t result; + + result = tpm_get_permanent_flags(&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_set_global_lock(void) +{ + uint32_t x; + + debug("TPM: Set global lock\n"); + return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0); +} + +static uint32_t tpm_nv_write_value_lock(uint32_t index) +{ + debug("TPM: Write lock 0x%x\n", index); + + return tpm_nv_write_value(index, NULL, 0); +} + +static uint32_t tpm_nv_set_locked(void) +{ + debug("TPM: Set NV locked\n"); + + return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0); +} + +static int tpm_is_owned(void) +{ + uint8_t response[TPM_PUBEK_SIZE]; + uint32_t result; + + result = tpm_read_pubek(response, sizeof(response)); + + return result != TPM_SUCCESS; +} + +static int test_early_extend(void) +{ + uint8_t value_in[20]; + uint8_t value_out[20]; + + printf("Testing earlyextend ..."); + tpm_init(); + TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); + TPM_CHECK(tpm_continue_self_test()); + TPM_CHECK(tpm_extend(1, value_in, value_out)); + printf("done\n"); + return 0; +} + +static int test_early_nvram(void) +{ + uint32_t x; + + printf("Testing earlynvram ..."); + tpm_init(); + TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); + TPM_CHECK(tpm_continue_self_test()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); + printf("done\n"); + return 0; +} + +static int test_early_nvram2(void) +{ + uint32_t x; + + printf("Testing earlynvram2 ..."); + tpm_init(); + TPM_CHECK(tpm_startup(TPM_ST_CLEAR)); + TPM_CHECK(tpm_continue_self_test()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x))); + printf("done\n"); + return 0; +} + +static int test_enable(void) +{ + uint8_t disable = 0, deactivated = 0; + + printf("Testing enable ...\n"); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); + printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); + TPM_CHECK(tpm_physical_enable()); + TPM_CHECK(tpm_physical_set_deactivated(0)); + TPM_CHECK(tpm_get_flags(&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(0); \ +} while (0) + +static int test_fast_enable(void) +{ + uint8_t disable = 0, deactivated = 0; + int i; + + printf("Testing fastenable ...\n"); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); + printf("\tdisable is %d, deactivated is %d\n", disable, deactivated); + for (i = 0; i < 2; i++) { + TPM_CHECK(tpm_force_clear()); + TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL)); + printf("\tdisable is %d, deactivated is %d\n", disable, + deactivated); + assert(disable == 1 && deactivated == 1); + TPM_CHECK(tpm_physical_enable()); + TPM_CHECK(tpm_physical_set_deactivated(0)); + TPM_CHECK(tpm_get_flags(&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(void) +{ + uint32_t zero = 0; + uint32_t result; + uint32_t x; + + printf("Testing globallock ...\n"); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); + TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero, + sizeof(uint32_t))); + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); + TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero, + sizeof(uint32_t))); + TPM_CHECK(tpm_set_global_lock()); + /* Verifies that write to index0 fails */ + x = 1; + result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)); + assert(result == TPM_AREA_LOCKED); + TPM_CHECK(tpm_nv_read_value(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(INDEX1, (uint8_t *)&x, sizeof(x))); + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); + assert(x == 2); + /* Turns off PP */ + tpm_tsc_physical_presence(PHYS_PRESENCE); + /* Verifies that write to index1 fails */ + x = 3; + result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)); + assert(result == TPM_BAD_PRESENCE); + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); + assert(x == 2); + printf("\tdone\n"); + return 0; +} + +static int test_lock(void) +{ + printf("Testing lock ...\n"); + tpm_init(); + tpm_startup(TPM_ST_CLEAR); + tpm_self_test_full(); + tpm_tsc_physical_presence(PRESENCE); + tpm_nv_write_value_lock(INDEX0); + printf("\tLocked 0x%x\n", INDEX0); + printf("\tdone\n"); + return 0; +} + +static void initialise_spaces(void) +{ + uint32_t zero = 0; + uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; + + printf("\tInitialising spaces\n"); + tpm_nv_set_locked(); /* useful only the first time */ + tpm_nv_define_space(INDEX0, perm, 4); + tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4); + tpm_nv_define_space(INDEX1, perm, 4); + tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4); + tpm_nv_define_space(INDEX2, perm, 4); + tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4); + tpm_nv_define_space(INDEX3, perm, 4); + tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4); + perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR | + TPM_NV_PER_PPWRITE; + tpm_nv_define_space(INDEX_INITIALISED, perm, 1); +} + +static int test_readonly(void) +{ + uint8_t c; + uint32_t index_0, index_1, index_2, index_3; + int read0, read1, read2, read3; + + printf("Testing readonly ...\n"); + tpm_init(); + tpm_startup(TPM_ST_CLEAR); + tpm_self_test_full(); + tpm_tsc_physical_presence(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(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) { + /* The initialisation did not complete */ + initialise_spaces(); + } + + /* Checks if spaces are OK or messed up */ + read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)); + read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1)); + read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2)); + read3 = tpm_nv_read_value(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(INDEX0, (uint8_t *)&index_0, sizeof(index_0) != + TPM_SUCCESS)) { + error("\tcould not write index 0\n"); + } + tpm_nv_write_value_lock(INDEX0); + if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) == + TPM_SUCCESS) + error("\tindex 0 is not locked\n"); + + printf("\tdone\n"); + return 0; +} + +static int test_redefine_unowned(void) +{ + uint32_t perm; + uint32_t result; + uint32_t x; + + printf("Testing redefine_unowned ..."); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + assert(!tpm_is_owned()); + + /* Ensures spaces exist. */ + TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x))); + TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x))); + + /* Redefines spaces a couple of times. */ + perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK; + TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t))); + TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t))); + perm = TPM_NV_PER_PPWRITE; + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); + + /* Sets the global lock */ + tpm_set_global_lock(); + + /* Verifies that index0 cannot be redefined */ + result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); + assert(result == TPM_AREA_LOCKED); + + /* Checks that index1 can */ + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t))); + TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t))); + + /* Turns off PP */ + tpm_tsc_physical_presence(PHYS_PRESENCE); + + /* Verifies that neither index0 nor index1 can be redefined */ + result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)); + assert(result == TPM_BAD_PRESENCE); + result = tpm_nv_define_space(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(void) +{ + uint32_t perm; + + printf("Testing spaceperm ..."); + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_continue_self_test()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_get_permissions(INDEX0, &perm)); + assert((perm & PERMPPGL) == PERMPPGL); + TPM_CHECK(tpm_get_permissions(INDEX1, &perm)); + assert((perm & PERMPP) == PERMPP); + printf("done\n"); + return 0; +} + +static int test_startup(void) +{ + uint32_t result; + printf("Testing startup ...\n"); + + tpm_init(); + result = tpm_startup(TPM_ST_CLEAR); + if (result != 0 && result != TPM_INVALID_POSTINIT) + printf("\ttpm startup failed with 0x%x\n", result); + result = tpm_get_flags(NULL, NULL, NULL); + if (result != 0) + printf("\ttpm getflags failed with 0x%x\n", result); + printf("\texecuting SelfTestFull\n"); + tpm_self_test_full(); + result = tpm_get_flags(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(void) +{ + uint32_t x; + uint8_t in[20], out[20]; + + printf("Testing timing ..."); + tpm_init(); + TTPM_CHECK(TlclStartupIfNeeded(), 50); + TTPM_CHECK(tpm_continue_self_test(), 100); + TTPM_CHECK(tpm_self_test_full(), 1000); + TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100); + TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); + TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100); + TTPM_CHECK(tpm_extend(0, in, out), 200); + TTPM_CHECK(tpm_set_global_lock(), 50); + TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100); + printf("done\n"); + return 0; +} + +#define TPM_MAX_NV_WRITES_NOOWNER 64 + +static int test_write_limit(void) +{ + printf("Testing writelimit ...\n"); + int i; + uint32_t result; + + tpm_init(); + TPM_CHECK(TlclStartupIfNeeded()); + TPM_CHECK(tpm_self_test_full()); + TPM_CHECK(tpm_tsc_physical_presence(PRESENCE)); + TPM_CHECK(tpm_force_clear()); + TPM_CHECK(tpm_physical_enable()); + TPM_CHECK(tpm_physical_set_deactivated(0)); + + for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) { + printf("\twriting %d\n", i); + result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)); + switch (result) { + case TPM_SUCCESS: + break; + case TPM_MAXNVWRITES: + assert(i >= TPM_MAX_NV_WRITES_NOOWNER); + default: + error("\tunexpected error code %d (0x%x)\n", + result, result); + } + } + + /* Reset write count */ + TPM_CHECK(tpm_force_clear()); + TPM_CHECK(tpm_physical_enable()); + TPM_CHECK(tpm_physical_set_deactivated(0)); + + /* Try writing again. */ + TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i))); + printf("\tdone\n"); + return 0; +} + +#define VOIDTEST(XFUNC) \ + int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \ + char * const argv[]) \ + { \ + return test_##XFUNC(); \ + } + +#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 cmd_tbl_t 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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *c; + + printf("argc = %d, argv = ", argc); + do { + int i = 0; + + for (i = 0; i < argc; i++) + printf(" %s", argv[i]); + printf("\n------\n"); + } while (0); + 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/cmd/trace.c b/cmd/trace.c new file mode 100644 index 0000000..1e62a1a --- /dev/null +++ b/cmd/trace.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +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 = getenv_ulong("profsize", 16, 0); + *buff = map_sysmem(getenv_ulong("profbase", 16, 0), + *buff_size); + *buff_ptr = getenv_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, used; + unsigned int needed; + 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 (%#x bytes needed)\n", needed); + used = min(avail, needed); + printf("Function trace dumped to %08lx, size %#zx\n", + (ulong)map_to_sysmem(buff + buff_ptr), used); + setenv_hex("profbase", map_to_sysmem(buff)); + setenv_hex("profsize", buff_size); + setenv_hex("profoffset", buff_ptr + used); + + return 0; +} + +static int create_call_list(int argc, char * const argv[]) +{ + size_t buff_size, avail, buff_ptr, used; + unsigned int needed; + 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 (%#x bytes needed)\n", needed); + used = min(avail, needed); + printf("Call list dumped to %08lx, size %#zx\n", + (ulong)map_to_sysmem(buff + buff_ptr), used); + + setenv_hex("profbase", map_to_sysmem(buff)); + setenv_hex("profsize", buff_size); + setenv_hex("profoffset", buff_ptr + used); + + return 0; +} + +int do_trace(cmd_tbl_t *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 [ ] - dump function list into buffer\n" + "trace calls [ ] " + "- dump function call trace into buffer" +); diff --git a/cmd/tsi148.c b/cmd/tsi148.c new file mode 100644 index 0000000..ea96d0f --- /dev/null +++ b/cmd/tsi148.c @@ -0,0 +1,472 @@ +/* + * (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 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#include + +#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(cmd_tbl_t *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/cmd/ubi.c b/cmd/ubi.c new file mode 100644 index 0000000..753a4db --- /dev/null +++ b/cmd/ubi.c @@ -0,0 +1,685 @@ +/* + * Unsorted Block Image commands + * + * Copyright (C) 2008 Samsung Electronics + * Kyungmin Park + * + * Copyright 2008-2009 Stefan Roese , 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef ubi_msg +#define ubi_msg(fmt, ...) printf("UBI: " fmt "\n", ##__VA_ARGS__) + +#define DEV_TYPE_NONE 0 +#define DEV_TYPE_NAND 1 +#define DEV_TYPE_ONENAND 2 +#define DEV_TYPE_NOR 3 + +/* Private own data */ +static struct ubi_device *ubi; +static char buffer[80]; +static int ubi_initialized; + +struct selected_dev { + char part_name[80]; + int selected; + int nr; + struct mtd_info *mtd_info; +}; + +static struct selected_dev ubi_dev; + +#ifdef CONFIG_CMD_UBIFS +int ubifs_is_mounted(void); +void cmd_ubifs_umount(void); +#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) +{ + 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 = UBI_VOL_NUM_AUTO; + req.alignment = 1; + req.bytes = size; + + strcpy(req.name, volume); + req.name_len = strlen(volume); + req.name[req.name_len] = '\0'; + req.padding1 = 0; + /* 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_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 < 0 || 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; + + 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; + } + + 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; + 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); + + free(tbuf); + return err; +} + +static int ubi_dev_scan(struct mtd_info *info, char *ubidev, + const char *vid_header_offset) +{ + struct mtd_device *dev; + struct part_info *part; + struct mtd_partition mtd_part; + char ubi_mtd_param_buffer[80]; + u8 pnum; + int err; + + if (find_dev_and_part(ubidev, &dev, &pnum, &part) != 0) + return 1; + + sprintf(buffer, "mtd=%d", pnum); + memset(&mtd_part, 0, sizeof(mtd_part)); + mtd_part.name = buffer; + mtd_part.size = part->size; + mtd_part.offset = part->offset; + add_mtd_partitions(info, &mtd_part, 1); + + strcpy(ubi_mtd_param_buffer, buffer); + if (vid_header_offset) + sprintf(ubi_mtd_param_buffer, "mtd=%d,%s", pnum, + vid_header_offset); + err = ubi_mtd_param_parse(ubi_mtd_param_buffer, NULL); + if (err) { + del_mtd_partitions(info); + return -err; + } + + err = ubi_init(); + if (err) { + del_mtd_partitions(info); + return -err; + } + + ubi_initialized = 1; + + return 0; +} + +int ubi_part(char *part_name, const char *vid_header_offset) +{ + int err = 0; + char mtd_dev[16]; + struct mtd_device *dev; + struct part_info *part; + u8 pnum; + + if (mtdparts_init() != 0) { + printf("Error initializing mtdparts!\n"); + return 1; + } + +#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 + + /* todo: get dev number for NAND... */ + ubi_dev.nr = 0; + + /* + * Call ubi_exit() before re-initializing the UBI subsystem + */ + if (ubi_initialized) { + ubi_exit(); + del_mtd_partitions(ubi_dev.mtd_info); + } + + /* + * Search the mtd device number where this partition + * is located + */ + if (find_dev_and_part(part_name, &dev, &pnum, &part)) { + printf("Partition %s not found!\n", part_name); + return 1; + } + sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num); + ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev); + if (IS_ERR(ubi_dev.mtd_info)) { + printf("Partition %s not found on device %s!\n", part_name, + mtd_dev); + return 1; + } + + ubi_dev.selected = 1; + + strcpy(ubi_dev.part_name, part_name); + err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name, + vid_header_offset); + if (err) { + printf("UBI init error %d\n", err); + ubi_dev.selected = 0; + return err; + } + + ubi = ubi_devices[0]; + + return 0; +} + +static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int64_t size = 0; + ulong addr = 0; + + if (argc < 2) + return CMD_RET_USAGE; + + if (strcmp(argv[1], "part") == 0) { + const char *vid_header_offset = NULL; + + /* Print current partition */ + if (argc == 2) { + if (!ubi_dev.selected) { + printf("Error, no UBI device/partition selected!\n"); + return 1; + } + + printf("Device %d: %s, partition %s\n", + ubi_dev.nr, ubi_dev.mtd_info->name, ubi_dev.part_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_dev.selected)) { + printf("Error, no UBI device/partition 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 */ + + /* Use maximum available size */ + size = 0; + + /* 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) { + 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); + } + + if (strncmp(argv[1], "remove", 6) == 0) { + /* E.g., remove volume */ + if (argc == 3) + return ubi_remove_vol(argv[2]); + } + + 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) { + printf("Read %lld bytes from volume %s to %lx\n", size, + argv[3], addr); + + return ubi_volume_read(argv[3], (char *)addr, size); + } + } + + printf("Please see usage\n"); + return 1; +} + +U_BOOT_CMD( + ubi, 6, 1, do_ubi, + "ubi commands", + "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]" + " - create volume name with 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" + "[Legends]\n" + " volume: character name\n" + " size: specified in bytes\n" + " type: s[tatic] or d[ynamic] (default=dynamic)" +); diff --git a/cmd/ubifs.c b/cmd/ubifs.c new file mode 100644 index 0000000..5e9d357 --- /dev/null +++ b/cmd/ubifs.c @@ -0,0 +1,165 @@ +/* + * (C) Copyright 2008 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +/* + * UBIFS command support + */ + +#undef DEBUG + +#include +#include +#include +#include + +static int ubifs_initialized; +static int ubifs_mounted; + +static int do_ubifs_mount(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + char *vol_name; + int ret; + + if (argc != 2) + return CMD_RET_USAGE; + + vol_name = argv[1]; + 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 0; +} + +int ubifs_is_mounted(void) +{ + return ubifs_mounted; +} + +void cmd_ubifs_umount(void) +{ + uboot_ubifs_umount(); + ubifs_mounted = 0; + ubifs_initialized = 0; +} + +static int do_ubifs_umount(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + if (argc != 1) + return CMD_RET_USAGE; + + if (ubifs_initialized == 0) { + printf("No UBIFS volume mounted!\n"); + return -1; + } + + cmd_ubifs_umount(); + + return 0; +} + +static int do_ubifs_ls(cmd_tbl_t *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(cmd_tbl_t *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", + "\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", + " [bytes]\n" + " - load file 'filename' to address 'addr'" +); diff --git a/cmd/universe.c b/cmd/universe.c new file mode 100644 index 0000000..c931036 --- /dev/null +++ b/cmd/universe.c @@ -0,0 +1,368 @@ +/* + * (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#include + +#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(cmd_tbl_t *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/cmd/unzip.c b/cmd/unzip.c new file mode 100644 index 0000000..0686be6 --- /dev/null +++ b/cmd/unzip.c @@ -0,0 +1,88 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +static int do_unzip(cmd_tbl_t *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: %ld = 0x%lX\n", src_len, src_len); + setenv_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(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + block_dev_desc_t *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 = get_device(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", + " 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/cmd/usb.c b/cmd/usb.c new file mode 100644 index 0000000..c7b642c --- /dev/null +++ b/cmd/usb.c @@ -0,0 +1,853 @@ +/* + * (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. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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) +{ + 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)); + } + printf(" - PacketSize: %d Configurations: %d\n", + dev->descriptor.bMaxPacketSize0, + 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 char *portspeed(int speed) +{ + char *speed_str; + + switch (speed) { + case USB_SPEED_SUPER: + speed_str = "5 Gb/s"; + break; + case USB_SPEED_HIGH: + speed_str = "480 Mb/s"; + break; + case USB_SPEED_LOW: + speed_str = "1.5 Mb/s"; + break; + default: + speed_str = "12 Mb/s"; + break; + } + + return speed_str; +} + +/* 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); +#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, we only want real devices */ + if (device_get_uclass_id(child) != UCLASS_USB_EMUL) { + 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]); +} + +void usb_show_tree(void) +{ +#ifdef CONFIG_DM_USB + struct udevice *bus; + + for (uclass_first_device(UCLASS_USB, &bus); + bus; + uclass_next_device(&bus)) { + struct usb_device *udev; + struct udevice *dev; + + device_find_first_child(bus, &dev); + if (dev && device_active(dev)) { + udev = dev_get_parent_priv(dev); + usb_show_subtree(udev); + } + } +#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(cmd_tbl_t *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) +{ +#ifdef 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 */ +#ifndef CONFIG_DM_USB +# ifdef CONFIG_USB_STORAGE + /* try to recognize storage devices immediately */ + usb_stor_curr_dev = usb_stor_scan(1); +# endif +# 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 show_info(struct udevice *dev) +{ + struct udevice *child; + struct usb_device *udev; + + udev = dev_get_parent_priv(dev); + usb_display_desc(udev); + usb_display_config(udev); + for (device_find_first_child(dev, &child); + child; + device_find_next_child(&child)) { + if (device_active(child)) + show_info(child); + } +} + +static int usb_device_info(void) +{ + struct udevice *bus; + + for (uclass_first_device(UCLASS_USB, &bus); + bus; + uclass_next_device(&bus)) { + struct udevice *hub; + + device_find_first_child(bus, &hub); + if (device_get_uclass_id(hub) == UCLASS_USB_HUB && + device_active(hub)) { + show_info(hub); + } + } + + return 0; +} +#endif + +/****************************************************************************** + * usb command intepreter + */ +static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct usb_device *udev = NULL; + int i; + extern char usb_started; +#ifdef CONFIG_USB_STORAGE + block_dev_desc_t *stor_dev; +#endif + + 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_device_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(); + + if (strncmp(argv[1], "part", 4) == 0) { + int devno, ok = 0; + if (argc == 2) { + for (devno = 0; ; ++devno) { + stor_dev = usb_stor_get_dev(devno); + if (stor_dev == NULL) + break; + if (stor_dev->type != DEV_TYPE_UNKNOWN) { + ok++; + if (devno) + printf("\n"); + debug("print_part of %x\n", devno); + print_part(stor_dev); + } + } + } else { + devno = simple_strtoul(argv[2], NULL, 16); + stor_dev = usb_stor_get_dev(devno); + if (stor_dev != NULL && + stor_dev->type != DEV_TYPE_UNKNOWN) { + ok++; + debug("print_part of %x\n", devno); + print_part(stor_dev); + } + } + if (!ok) { + printf("\nno USB devices available\n"); + return 1; + } + return 0; + } + if (strcmp(argv[1], "read") == 0) { + if (usb_stor_curr_dev < 0) { + printf("no current device selected\n"); + return 1; + } + if (argc == 5) { + unsigned long addr = simple_strtoul(argv[2], NULL, 16); + unsigned long blk = simple_strtoul(argv[3], NULL, 16); + unsigned long cnt = simple_strtoul(argv[4], NULL, 16); + unsigned long n; + printf("\nUSB read: device %d block # %ld, count %ld" + " ... ", usb_stor_curr_dev, blk, cnt); + stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + n = stor_dev->block_read(stor_dev, blk, cnt, + (ulong *)addr); + printf("%ld blocks read: %s\n", n, + (n == cnt) ? "OK" : "ERROR"); + if (n == cnt) + return 0; + return 1; + } + } + if (strcmp(argv[1], "write") == 0) { + if (usb_stor_curr_dev < 0) { + printf("no current device selected\n"); + return 1; + } + if (argc == 5) { + unsigned long addr = simple_strtoul(argv[2], NULL, 16); + unsigned long blk = simple_strtoul(argv[3], NULL, 16); + unsigned long cnt = simple_strtoul(argv[4], NULL, 16); + unsigned long n; + printf("\nUSB write: device %d block # %ld, count %ld" + " ... ", usb_stor_curr_dev, blk, cnt); + stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + n = stor_dev->block_write(stor_dev, blk, cnt, + (ulong *)addr); + printf("%ld blocks write: %s\n", n, + (n == cnt) ? "OK" : "ERROR"); + if (n == cnt) + return 0; + return 1; + } + } + if (strncmp(argv[1], "dev", 3) == 0) { + if (argc == 3) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + printf("\nUSB device %d: ", dev); + stor_dev = usb_stor_get_dev(dev); + if (stor_dev == NULL) { + printf("unknown device\n"); + return 1; + } + printf("\n Device %d: ", dev); + dev_print(stor_dev); + if (stor_dev->type == DEV_TYPE_UNKNOWN) + return 1; + usb_stor_curr_dev = dev; + printf("... is now current device\n"); + return 0; + } else { + printf("\nUSB device %d: ", usb_stor_curr_dev); + stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + dev_print(stor_dev); + if (stor_dev->type == DEV_TYPE_UNKNOWN) + return 1; + return 0; + } + return 0; + } +#endif /* CONFIG_USB_STORAGE */ + return CMD_RET_USAGE; +} + +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/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c new file mode 100644 index 0000000..0415591 --- /dev/null +++ b/cmd/usb_mass_storage.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * Lukasz Majewski + * + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int ums_read_sector(struct ums *ums_dev, + ulong start, lbaint_t blkcnt, void *buf) +{ + block_dev_desc_t *block_dev = &ums_dev->block_dev; + lbaint_t blkstart = start + ums_dev->start_sector; + + return block_dev->block_read(block_dev, blkstart, blkcnt, buf); +} + +static int ums_write_sector(struct ums *ums_dev, + ulong start, lbaint_t blkcnt, const void *buf) +{ + block_dev_desc_t *block_dev = &ums_dev->block_dev; + lbaint_t blkstart = start + ums_dev->start_sector; + + return block_dev->block_write(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 = 0; + ums_count = 0; +} + +#define UMS_NAME_LEN 16 + +static int ums_init(const char *devtype, const char *devnums) +{ + char *s, *t, *devnum, *name; + block_dev_desc_t *block_dev; + int ret; + struct ums *ums_new; + + s = strdup(devnums); + if (!s) + return -1; + + t = s; + ums_count = 0; + + for (;;) { + devnum = strsep(&t, ","); + if (!devnum) + break; + + ret = get_device(devtype, devnum, &block_dev); + if (ret < 0) + goto cleanup; + + /* f_mass_storage.c assumes SECTOR_SIZE sectors */ + if (block_dev->blksz != SECTOR_SIZE) { + ret = -1; + goto cleanup; + } + + ums_new = realloc(ums, (ums_count + 1) * sizeof(*ums)); + if (!ums_new) { + ret = -1; + goto cleanup; + } + ums = ums_new; + + ums[ums_count].read_sector = ums_read_sector; + ums[ums_count].write_sector = ums_write_sector; + ums[ums_count].start_sector = 0; + ums[ums_count].num_sectors = block_dev->lba; + name = malloc(UMS_NAME_LEN); + if (!name) { + ret = -1; + 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 %d, hwpart %d, sector %#x, count %#x\n", + ums_count, ums[ums_count].block_dev.dev, + ums[ums_count].block_dev.hwpart, + ums[ums_count].start_sector, + ums[ums_count].num_sectors); + + ums_count++; + } + + if (!ums_count) + ret = -1; + else + ret = 0; + +cleanup: + free(s); + + if (ret < 0) + ums_fini(); + + return ret; +} + +int do_usb_mass_storage(cmd_tbl_t *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 (board_usb_init(controller_index, USB_INIT_DEVICE)) { + error("Couldn't init USB controller."); + rc = CMD_RET_FAILURE; + goto cleanup_ums_init; + } + + rc = fsg_init(ums, ums_count); + if (rc) { + error("fsg_init failed"); + rc = CMD_RET_FAILURE; + goto cleanup_board; + } + + rc = g_dnl_register("usb_dnl_ums"); + if (rc) { + error("g_dnl_register failed"); + 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; + } + } + +cleanup_register: + g_dnl_unregister(); +cleanup_board: + board_usb_cleanup(controller_index, USB_INIT_DEVICE); +cleanup_ums_init: + ums_fini(); + + return rc; +} + +U_BOOT_CMD(ums, 4, 1, do_usb_mass_storage, + "Use the UMS [USB Mass Storage]", + " [] e.g. ums 0 mmc 0\n" + " devtype defaults to mmc" +); diff --git a/cmd/version.c b/cmd/version.c new file mode 100644 index 0000000..1be0667 --- /dev/null +++ b/cmd/version.c @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#ifdef CONFIG_SYS_COREBOOT +#include +#endif + +const char __weak version_string[] = U_BOOT_VERSION_STRING; + +static int do_version(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + printf("\n%s\n", version_string); +#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/cmd/ximg.c b/cmd/ximg.c new file mode 100644 index 0000000..d033c15 --- /dev/null +++ b/cmd/ximg.c @@ -0,0 +1,275 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2003 + * Kai-Uwe Bloem, Auerswald GmbH & Co KG, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +/* + * Multi Image extract + */ +#include +#include +#include +#include +#include +#if defined(CONFIG_BZIP2) +#include +#endif +#include +#include + +#ifndef CONFIG_SYS_XIMG_LEN +/* use 8MByte as default max gunzip size */ +#define CONFIG_SYS_XIMG_LEN 0x800000 +#endif + +static int +do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + ulong addr = load_addr; + ulong dest = 0; + ulong data, len; + int verify; + int part = 0; +#if defined(CONFIG_IMAGE_FORMAT_LEGACY) + 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 = getenv_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_IMAGE_FORMAT_LEGACY) + 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)) { + 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 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; + } + + 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_IMAGE_FORMAT_LEGACY) + 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, len); + + setenv_hex("fileaddr", data); + setenv_hex("filesize", len); + + return 0; +} + +#ifdef CONFIG_SYS_LONGHELP +static char imgextract_help_text[] = + "addr part [dest]\n" + " - extract from legacy image at and copy to " +#if defined(CONFIG_FIT) + "\n" + "addr uname [dest]\n" + " - extract subimage from FIT image at and copy to " +#endif + ""; +#endif + +U_BOOT_CMD( + imxtract, 4, 1, do_imgextract, + "extract a part of a multi-image", imgextract_help_text +); diff --git a/cmd/yaffs2.c b/cmd/yaffs2.c new file mode 100644 index 0000000..9244606 --- /dev/null +++ b/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 + +#include +#include + +#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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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(cmd_tbl_t *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/cmd/zfs.c b/cmd/zfs.c new file mode 100644 index 0000000..0aed29e --- /dev/null +++ b/cmd/zfs.c @@ -0,0 +1,171 @@ +/* + * + * ZFS filesystem porting to Uboot by + * Jorgen Lundman + * + * zfsfs support + * made from existing GRUB Sources by Sun, GNU and others. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) +#include +#endif + +#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_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(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *filename = NULL; + int dev; + int part; + ulong addr = 0; + disk_partition_t info; + block_dev_desc_t *dev_desc; + char buf[12]; + 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 = getenv("bootfile"); + switch (argc) { + case 3: + addr_str = getenv("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 = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) + return 1; + + dev = dev_desc->dev; + 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 */ + load_addr = addr; + + printf("%llu bytes read\n", zfile.size); + setenv_hex("filesize", zfile.size); + + return 0; +} + + +int zfs_print(const char *entry, const struct zfs_dirhook_info *data) +{ + printf("%s %s\n", + data->dir ? " " : " ", + entry); + return 0; /* 0 continue, 1 stop */ +} + + + +static int do_zfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const char *filename = "/"; + int part; + block_dev_desc_t *dev_desc; + disk_partition_t info; + struct device_s vdev; + + if (argc < 2) + return cmd_usage(cmdtp); + + if (argc == 4) + filename = argv[3]; + + part = get_device_and_partition(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 /)", + " [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", + " [addr] [filename] [bytes]\n" + " - load binary file '/DATASET/@/$dir/$file' from 'dev' on 'interface'\n" + " to address 'addr' from ZFS filesystem"); diff --git a/cmd/zip.c b/cmd/zip.c new file mode 100644 index 0000000..7fcd9d5 --- /dev/null +++ b/cmd/zip.c @@ -0,0 +1,42 @@ +/* + * (C) Copyright 2012 + * Lei Wen , Marvell Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +static int do_zip(cmd_tbl_t *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: %ld = 0x%lX\n", dst_len, dst_len); + setenv_hex("filesize", dst_len); + + return 0; +} + +U_BOOT_CMD( + zip, 5, 1, do_zip, + "zip a memory region", + "srcaddr srcsize dstaddr [dstsize]" +); -- cgit v0.10.2