diff options
55 files changed, 1534 insertions, 723 deletions
@@ -358,12 +358,26 @@ config FIT_ENABLE_SHA256_SUPPORT help Enable this to support SHA256 checksum of FIT image contents. A SHA256 checksum is a 256-bit (32-byte) hash value used to check that - the image contents have not been corrupted. SHA256 is recommended - for use in secure applications since (as at 2016) there is no known - feasible attack that could produce a 'collision' with differing - input data. Use this for the highest security. Note that only the - SHA256 variant is supported: SHA512 and others are not currently - supported in U-Boot. + the image contents have not been corrupted. + +config FIT_ENABLE_SHA384_SUPPORT + bool "Support SHA384 checksum of FIT image contents" + default n + select SHA384 + help + Enable this to support SHA384 checksum of FIT image contents. A + SHA384 checksum is a 384-bit (48-byte) hash value used to check that + the image contents have not been corrupted. Use this for the highest + security. + +config FIT_ENABLE_SHA512_SUPPORT + bool "Support SHA512 checksum of FIT image contents" + default n + select SHA512 + help + Enable this to support SHA512 checksum of FIT image contents. A + SHA512 checksum is a 512-bit (64-byte) hash value used to check that + the image contents have not been corrupted. config FIT_SIGNATURE bool "Enable signature verification of FIT uImages" diff --git a/board/tbs/tbs2910/MAINTAINERS b/board/tbs/tbs2910/MAINTAINERS index a3ad2f712a..1e3c0d0ece 100644 --- a/board/tbs/tbs2910/MAINTAINERS +++ b/board/tbs/tbs2910/MAINTAINERS @@ -4,4 +4,5 @@ S: Maintained F: arch/arm/dts/imx6q-tbs2910.dts F: board/tbs/tbs2910/ F: configs/tbs2910_defconfig +F: doc/board/tbs/ F: include/configs/tbs2910.h @@ -135,11 +135,15 @@ static void netboot_update_env(void) env_set("netmask", tmp); } +#ifdef CONFIG_CMD_BOOTP if (net_hostname[0]) env_set("hostname", net_hostname); +#endif +#ifdef CONFIG_CMD_BOOTP if (net_root_path[0]) env_set("rootpath", net_root_path); +#endif if (net_ip.s_addr) { ip_to_string(net_ip, tmp); @@ -165,8 +169,10 @@ static void netboot_update_env(void) env_set("dnsip2", tmp); } #endif +#ifdef CONFIG_CMD_BOOTP if (net_nis_domain[0]) env_set("domain", net_nis_domain); +#endif #if defined(CONFIG_CMD_SNTP) && defined(CONFIG_BOOTP_TIMEOFFSET) if (net_ntp_time_offset) { diff --git a/common/hash.c b/common/hash.c index 8c00659d25..5c75848b7d 100644 --- a/common/hash.c +++ b/common/hash.c @@ -31,6 +31,7 @@ #include <u-boot/crc.h> #include <u-boot/sha1.h> #include <u-boot/sha256.h> +#include <u-boot/sha512.h> #include <u-boot/md5.h> #if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC) @@ -95,6 +96,65 @@ static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void } #endif +#if defined(CONFIG_SHA384) +static int hash_init_sha384(struct hash_algo *algo, void **ctxp) +{ + sha512_context *ctx = malloc(sizeof(sha512_context)); + sha384_starts(ctx); + *ctxp = ctx; + return 0; +} + +static int hash_update_sha384(struct hash_algo *algo, void *ctx, + const void *buf, unsigned int size, int is_last) +{ + sha384_update((sha512_context *)ctx, buf, size); + return 0; +} + +static int hash_finish_sha384(struct hash_algo *algo, void *ctx, void + *dest_buf, int size) +{ + if (size < algo->digest_size) + return -1; + + sha384_finish((sha512_context *)ctx, dest_buf); + free(ctx); + return 0; +} +#endif + +#if defined(CONFIG_SHA512) +static int hash_init_sha512(struct hash_algo *algo, void **ctxp) +{ + sha512_context *ctx = malloc(sizeof(sha512_context)); + sha512_starts(ctx); + *ctxp = ctx; + return 0; +} + +static int hash_update_sha512(struct hash_algo *algo, void *ctx, + const void *buf, unsigned int size, int is_last) +{ + sha512_update((sha512_context *)ctx, buf, size); + return 0; +} + +static int hash_finish_sha512(struct hash_algo *algo, void *ctx, void + *dest_buf, int size) +{ + if (size < algo->digest_size) + return -1; + + printf("hello world\n"); + + sha512_finish((sha512_context *)ctx, dest_buf); + free(ctx); + return 0; +} +#endif + + static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp) { uint16_t *ctx = malloc(sizeof(uint16_t)); @@ -196,6 +256,28 @@ static struct hash_algo hash_algo[] = { #endif }, #endif +#ifdef CONFIG_SHA384 + { + .name = "sha384", + .digest_size = SHA384_SUM_LEN, + .chunk_size = CHUNKSZ_SHA384, + .hash_func_ws = sha384_csum_wd, + .hash_init = hash_init_sha384, + .hash_update = hash_update_sha384, + .hash_finish = hash_finish_sha384, + }, +#endif +#ifdef CONFIG_SHA512 + { + .name = "sha512", + .digest_size = SHA512_SUM_LEN, + .chunk_size = CHUNKSZ_SHA512, + .hash_func_ws = sha512_csum_wd, + .hash_init = hash_init_sha512, + .hash_update = hash_update_sha512, + .hash_finish = hash_finish_sha512, + }, +#endif { .name = "crc16-ccitt", .digest_size = 2, @@ -218,7 +300,8 @@ static struct hash_algo hash_algo[] = { /* Try to minimize code size for boards that don't want much hashing */ #if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) || \ - defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH) + defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH) || \ + defined(CONFIG_SHA384) || defined(CONFIG_SHA512) #define multi_hash() 1 #else #define multi_hash() 0 diff --git a/common/image-fit.c b/common/image-fit.c index 1ece100a21..d54eff9033 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -32,6 +32,7 @@ DECLARE_GLOBAL_DATA_PTR; #include <u-boot/md5.h> #include <u-boot/sha1.h> #include <u-boot/sha256.h> +#include <u-boot/sha512.h> /*****************************************************************************/ /* New uImage format routines */ @@ -1206,6 +1207,14 @@ int calculate_hash(const void *data, int data_len, const char *algo, sha256_csum_wd((unsigned char *)data, data_len, (unsigned char *)value, CHUNKSZ_SHA256); *value_len = SHA256_SUM_LEN; + } else if (IMAGE_ENABLE_SHA384 && strcmp(algo, "sha384") == 0) { + sha384_csum_wd((unsigned char *)data, data_len, + (unsigned char *)value, CHUNKSZ_SHA384); + *value_len = SHA384_SUM_LEN; + } else if (IMAGE_ENABLE_SHA512 && strcmp(algo, "sha512") == 0) { + sha512_csum_wd((unsigned char *)data, data_len, + (unsigned char *)value, CHUNKSZ_SHA512); + *value_len = SHA512_SUM_LEN; } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) { md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5); *value_len = 16; diff --git a/common/image-sig.c b/common/image-sig.c index 498969d641..f3c209ae8b 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -40,7 +40,31 @@ struct checksum_algo checksum_algos[] = { .calculate_sign = EVP_sha256, #endif .calculate = hash_calculate, - } + }, +#ifdef CONFIG_SHA384 + { + .name = "sha384", + .checksum_len = SHA384_SUM_LEN, + .der_len = SHA384_DER_LEN, + .der_prefix = sha384_der_prefix, +#if IMAGE_ENABLE_SIGN + .calculate_sign = EVP_sha384, +#endif + .calculate = hash_calculate, + }, +#endif +#ifdef CONFIG_SHA512 + { + .name = "sha512", + .checksum_len = SHA512_SUM_LEN, + .der_len = SHA512_DER_LEN, + .der_prefix = sha512_der_prefix, +#if IMAGE_ENABLE_SIGN + .calculate_sign = EVP_sha512, +#endif + .calculate = hash_calculate, + }, +#endif }; diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 8ece9057b1..3eae65ebc1 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -412,7 +412,7 @@ config SPL_MD5_SUPPORT secure as it is possible (with a brute-force attack) to adjust the image while still retaining the same MD5 hash value. For secure applications where images may be changed maliciously, you should - consider SHA1 or SHA256. + consider SHA256 or SHA384. config SPL_SHA1_SUPPORT bool "Support SHA1" @@ -424,7 +424,7 @@ config SPL_SHA1_SUPPORT image contents have not been corrupted or maliciously altered. While SHA1 is fairly secure it is coming to the end of its life due to the expanding computing power available to brute-force - attacks. For more security, consider SHA256. + attacks. For more security, consider SHA256 or SHA384. config SPL_SHA256_SUPPORT bool "Support SHA256" @@ -433,12 +433,28 @@ config SPL_SHA256_SUPPORT help Enable this to support SHA256 in FIT images within SPL. A SHA256 checksum is a 256-bit (32-byte) hash value used to check that the - image contents have not been corrupted. SHA256 is recommended for - use in secure applications since (as at 2016) there is no known - feasible attack that could produce a 'collision' with differing - input data. Use this for the highest security. Note that only the - SHA256 variant is supported: SHA512 and others are not currently - supported in U-Boot. + image contents have not been corrupted. + +config SPL_SHA384_SUPPORT + bool "Support SHA384" + depends on SPL_FIT + select SHA384 + select SHA512_ALGO + help + Enable this to support SHA384 in FIT images within SPL. A SHA384 + checksum is a 384-bit (48-byte) hash value used to check that the + image contents have not been corrupted. Use this for the highest + security. + +config SPL_SHA512_SUPPORT + bool "Support SHA512" + depends on SPL_FIT + select SHA512 + select SHA512_ALGO + help + Enable this to support SHA512 in FIT images within SPL. A SHA512 + checksum is a 512-bit (64-byte) hash value used to check that the + image contents have not been corrupted. config SPL_FIT_IMAGE_TINY bool "Remove functionality from SPL FIT loading to reduce size" diff --git a/configs/P2041RDB_SECURE_BOOT_defconfig b/configs/P2041RDB_SECURE_BOOT_defconfig index b3e428025b..35a9d00e4b 100644 --- a/configs/P2041RDB_SECURE_BOOT_defconfig +++ b/configs/P2041RDB_SECURE_BOOT_defconfig @@ -46,7 +46,6 @@ CONFIG_PHY_VITESSE=y CONFIG_DM_ETH=y CONFIG_DM_MDIO=y CONFIG_PHY_GIGE=y -CONFIG_E1000=y CONFIG_FMAN_ENET=y CONFIG_MII=y CONFIG_SYS_QE_FMAN_FW_IN_NOR=y @@ -58,4 +57,3 @@ CONFIG_USB_STORAGE=y CONFIG_RSA=y CONFIG_SPL_RSA=y CONFIG_RSA_SOFTWARE_EXP=y -CONFIG_OF_LIBFDT=y diff --git a/configs/T1024RDB_NAND_defconfig b/configs/T1024RDB_NAND_defconfig index f6deee94e4..e3a955abf9 100644 --- a/configs/T1024RDB_NAND_defconfig +++ b/configs/T1024RDB_NAND_defconfig @@ -34,9 +34,9 @@ CONFIG_CMD_IMLS=y CONFIG_CMD_GREPENV=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_ALT_MEMTEST=y -CONFIG_CMD_DM=y CONFIG_SYS_MEMTEST_START=0x00200000 CONFIG_SYS_MEMTEST_END=0x00400000 +CONFIG_CMD_DM=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y diff --git a/configs/T1024RDB_SDCARD_defconfig b/configs/T1024RDB_SDCARD_defconfig index a0042d826b..b3abeeb817 100644 --- a/configs/T1024RDB_SDCARD_defconfig +++ b/configs/T1024RDB_SDCARD_defconfig @@ -32,9 +32,9 @@ CONFIG_CMD_IMLS=y CONFIG_CMD_GREPENV=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_ALT_MEMTEST=y -CONFIG_CMD_DM=y CONFIG_SYS_MEMTEST_START=0x00200000 CONFIG_SYS_MEMTEST_END=0x00400000 +CONFIG_CMD_DM=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y diff --git a/configs/T1024RDB_SECURE_BOOT_defconfig b/configs/T1024RDB_SECURE_BOOT_defconfig index 6ef2dfda57..fe3d28b373 100644 --- a/configs/T1024RDB_SECURE_BOOT_defconfig +++ b/configs/T1024RDB_SECURE_BOOT_defconfig @@ -19,9 +19,9 @@ CONFIG_CMD_IMLS=y CONFIG_CMD_GREPENV=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_ALT_MEMTEST=y -CONFIG_CMD_DM=y CONFIG_SYS_MEMTEST_START=0x00200000 CONFIG_SYS_MEMTEST_END=0x00400000 +CONFIG_CMD_DM=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y @@ -53,7 +53,6 @@ CONFIG_SPI_FLASH_STMICRO=y CONFIG_PHYLIB=y CONFIG_PHY_AQUANTIA=y CONFIG_PHY_REALTEK=y -CONFIG_E1000=y CONFIG_DM_ETH=y CONFIG_DM_MDIO=y CONFIG_FMAN_ENET=y @@ -67,4 +66,3 @@ CONFIG_USB_STORAGE=y CONFIG_RSA=y CONFIG_SPL_RSA=y CONFIG_RSA_SOFTWARE_EXP=y -CONFIG_OF_LIBFDT=y diff --git a/configs/T1024RDB_SPIFLASH_defconfig b/configs/T1024RDB_SPIFLASH_defconfig index a07c391d86..04e8cc6a44 100644 --- a/configs/T1024RDB_SPIFLASH_defconfig +++ b/configs/T1024RDB_SPIFLASH_defconfig @@ -34,9 +34,9 @@ CONFIG_CMD_IMLS=y CONFIG_CMD_GREPENV=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_ALT_MEMTEST=y -CONFIG_CMD_DM=y CONFIG_SYS_MEMTEST_START=0x00200000 CONFIG_SYS_MEMTEST_END=0x00400000 +CONFIG_CMD_DM=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y diff --git a/configs/T1024RDB_defconfig b/configs/T1024RDB_defconfig index 79fb3959e3..46c857d6c5 100644 --- a/configs/T1024RDB_defconfig +++ b/configs/T1024RDB_defconfig @@ -19,9 +19,9 @@ CONFIG_CMD_IMLS=y CONFIG_CMD_GREPENV=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_ALT_MEMTEST=y -CONFIG_CMD_DM=y CONFIG_SYS_MEMTEST_START=0x00200000 CONFIG_SYS_MEMTEST_END=0x00400000 +CONFIG_CMD_DM=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_SF=y diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index d74a2d0930..c5ca4da73a 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -99,7 +99,7 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_E1000=y diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig index 117953817d..644873d67c 100644 --- a/configs/am65x_hs_evm_a53_defconfig +++ b/configs/am65x_hs_evm_a53_defconfig @@ -101,7 +101,7 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_E1000=y diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig index e4547d9dcc..73ac3b319b 100644 --- a/configs/dra7xx_evm_defconfig +++ b/configs/dra7xx_evm_defconfig @@ -86,7 +86,7 @@ CONFIG_DM_SPI_FLASH=y CONFIG_SF_DEFAULT_MODE=0 CONFIG_SF_DEFAULT_SPEED=76800000 CONFIG_SPI_FLASH_SPANSION=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_MII=y diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index c08bcce903..40dc554e80 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -89,7 +89,7 @@ CONFIG_DM_SPI_FLASH=y CONFIG_SF_DEFAULT_MODE=0 CONFIG_SF_DEFAULT_SPEED=76800000 CONFIG_SPI_FLASH_SPANSION=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_MII=y diff --git a/configs/dra7xx_hs_evm_usb_defconfig b/configs/dra7xx_hs_evm_usb_defconfig index 879c2b650b..babd7029c0 100644 --- a/configs/dra7xx_hs_evm_usb_defconfig +++ b/configs/dra7xx_hs_evm_usb_defconfig @@ -87,7 +87,7 @@ CONFIG_SF_DEFAULT_MODE=0 CONFIG_SF_DEFAULT_SPEED=76800000 CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_DM_ETH=y CONFIG_PHY_GIGE=y CONFIG_MII=y diff --git a/configs/firefly-rk3399_defconfig b/configs/firefly-rk3399_defconfig index 5bb54f5835..5181510aac 100644 --- a/configs/firefly-rk3399_defconfig +++ b/configs/firefly-rk3399_defconfig @@ -18,8 +18,8 @@ CONFIG_TPL=y CONFIG_CMD_BOOTZ=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y -CONFIG_CMD_USB=y CONFIG_CMD_PCI=y +CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y CONFIG_SPL_OF_CONTROL=y diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig index 4deb4e219f..91a0572287 100644 --- a/configs/j721e_evm_a72_defconfig +++ b/configs/j721e_evm_a72_defconfig @@ -123,7 +123,7 @@ CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_TI_AM65_CPSW_NUSS=y diff --git a/configs/j721e_hs_evm_a72_defconfig b/configs/j721e_hs_evm_a72_defconfig index ae540a26a4..9aa3113642 100644 --- a/configs/j721e_hs_evm_a72_defconfig +++ b/configs/j721e_hs_evm_a72_defconfig @@ -113,7 +113,7 @@ CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_TI_AM65_CPSW_NUSS=y diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig index 5bc7f7f865..0379021c14 100644 --- a/configs/k2g_evm_defconfig +++ b/configs/k2g_evm_defconfig @@ -58,7 +58,7 @@ CONFIG_PHYLIB=y CONFIG_PHY_MARVELL=y CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ8XXX=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_DM_ETH=y CONFIG_MII=y CONFIG_DRIVER_TI_KEYSTONE_NET=y diff --git a/configs/rock-pi-e-rk3328_defconfig b/configs/rock-pi-e-rk3328_defconfig index 759838775f..e0941225a3 100644 --- a/configs/rock-pi-e-rk3328_defconfig +++ b/configs/rock-pi-e-rk3328_defconfig @@ -27,9 +27,9 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_TPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_POWER_SUPPORT=y -CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 CONFIG_SPL_ATF=y CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y CONFIG_TPL_DRIVERS_MISC_SUPPORT=y @@ -72,8 +72,8 @@ CONFIG_DM_PMIC=y CONFIG_PMIC_RK8XX=y CONFIG_SPL_DM_REGULATOR=y CONFIG_REGULATOR_PWM=y -CONFIG_SPL_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_FIXED=y +CONFIG_SPL_DM_REGULATOR_FIXED=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y CONFIG_RAM=y diff --git a/configs/rockpro64-rk3399_defconfig b/configs/rockpro64-rk3399_defconfig index 807747485a..ad0c6ab2b4 100644 --- a/configs/rockpro64-rk3399_defconfig +++ b/configs/rockpro64-rk3399_defconfig @@ -22,8 +22,8 @@ CONFIG_TPL=y CONFIG_CMD_BOOTZ=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y -CONFIG_CMD_USB=y CONFIG_CMD_PCI=y +CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y CONFIG_SPL_OF_CONTROL=y @@ -50,8 +50,8 @@ CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y -CONFIG_DM_RESET=y CONFIG_RAM_RK3399_LPDDR4=y +CONFIG_DM_RESET=y CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_ROCKCHIP_SPI=y diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig index 2ff0e160f7..fbd2293add 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -9,11 +9,15 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_PRE_CON_BUF_ADDR=0x7c000000 CONFIG_CMD_HDMIDETECT=y CONFIG_AHCI=y +CONFIG_ENV_VARS_UBOOT_CONFIG=y CONFIG_BOOTDELAY=3 +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="mmc rescan; if run bootcmd_up1; then run bootcmd_up2; else run bootcmd_mmc || run distro_bootcmd; fi" CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="echo PCI:; pci enum; pci 1; usb start; if hdmidet; then run set_con_hdmi; else run set_con_serial; fi" CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_SUPPORT_RAW_INITRD=y +CONFIG_DEFAULT_FDT_FILE="imx6q-tbs2910.dtb" CONFIG_BOUNCE_BUFFER=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_HUSH_PARSER=y @@ -28,6 +32,8 @@ CONFIG_SYS_MEMTEST_START=0x10000000 CONFIG_SYS_MEMTEST_END=0x2f400000 CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set CONFIG_CMD_MMC=y CONFIG_CMD_PART=y CONFIG_CMD_PCI=y @@ -39,6 +45,7 @@ CONFIG_CMD_MII=y CONFIG_CMD_PING=y CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y +CONFIG_CMD_SYSBOOT=y CONFIG_CMD_EXT2=y CONFIG_CMD_EXT4=y CONFIG_CMD_EXT4_WRITE=y @@ -86,5 +93,6 @@ CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_I2C_EDID=y CONFIG_VIDEO_IPUV3=y CONFIG_VIDEO=y +# CONFIG_GZIP is not set CONFIG_OF_LIBFDT_ASSUME_MASK=0xff # CONFIG_EFI_LOADER is not set diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index 4ed14f7030..b3e21ea903 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -63,7 +63,7 @@ CONFIG_SPI_FLASH_WINBOND=y CONFIG_PHY_MARVELL=y CONFIG_PHY_NATSEMI=y CONFIG_PHY_REALTEK=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_VITESSE=y CONFIG_PHY_FIXED=y CONFIG_PHY_GIGE=y diff --git a/configs/xilinx_zynqmp_virt_defconfig b/configs/xilinx_zynqmp_virt_defconfig index 7886d5a38f..2b4a0244fa 100644 --- a/configs/xilinx_zynqmp_virt_defconfig +++ b/configs/xilinx_zynqmp_virt_defconfig @@ -108,7 +108,7 @@ CONFIG_PHY_MICREL=y CONFIG_PHY_MICREL_KSZ90X1=y CONFIG_PHY_NATSEMI=y CONFIG_PHY_REALTEK=y -CONFIG_PHY_TI=y +CONFIG_PHY_TI_DP83867=y CONFIG_PHY_VITESSE=y CONFIG_PHY_XILINX_GMII2RGMII=y CONFIG_PHY_FIXED=y diff --git a/doc/board/index.rst b/doc/board/index.rst index 01b233f737..bb4473152a 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -18,5 +18,6 @@ Board-specific doc rockchip/index sifive/index st/index + tbs/index toradex/index xilinx/index diff --git a/doc/board/tbs/index.rst b/doc/board/tbs/index.rst new file mode 100644 index 0000000000..b677bc624f --- /dev/null +++ b/doc/board/tbs/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +TBS +=== + +.. toctree:: + :maxdepth: 2 + + tbs2910 diff --git a/doc/board/tbs/tbs2910.rst b/doc/board/tbs/tbs2910.rst new file mode 100644 index 0000000000..e97f2b6e61 --- /dev/null +++ b/doc/board/tbs/tbs2910.rst @@ -0,0 +1,191 @@ +TBS2910 Matrix ARM miniPC +========================= + +Building +-------- +To build u-boot for the TBS2910 Matrix ARM miniPC, you can use the following +procedure: + +First add the ARM toolchain to your PATH + +Then setup the ARCH and cross compilation environment variables. + +When this is done you can then build u-boot for the TBS2910 Matrix ARM miniPC +with the following commands: + +.. code-block:: none + + make mrproper + make tbs2910_defconfig + make + +Once the build is complete, you can find the resulting image as u-boot.imx in +the current directory. + +UART +---- +The UART voltage is at 3.3V and its settings are 115200bps 8N1 + +BOOT/UPDATE boot switch: +------------------------ +The BOOT/UPDATE switch (SW11) is connected to the BOOT_MODE0 and +BOOT_MODE1 SoC pins. It has "BOOT" and "UPDATE" markings both on +the PCB and on the plastic case. + +When set to the "UPDATE" position, the SoC will use the "Boot From Fuses" +configuration, and since BT_FUSE_SEL is 0, this makes the SOC jump to serial +downloader. + +When set in the "BOOT" position, the SoC will use the "Internal boot" +configuration, and since BT_FUSE_SEL is 0, it will then use the GPIO pins +for the boot configuration. + +SW6 binary DIP switch array on the PCB revision 2.1: +---------------------------------------------------- +On that PCB revision, SW6 has 8 positions. + +Switching a position to ON sets the corresponding +register to 1. + +See the following table for a correspondence between the switch positions and +registers: + +=============== ============ +Switch position Register +=============== ============ +1 BOOT_CFG2[3] +2 BOOT_CFG2[4] +3 BOOT_CFG2[5] +4 BOOT_CFG2[6] +5 BOOT_CFG1[4] +6 BOOT_CFG1[5] +7 BOOT_CFG1[6] +8 BOOT_CFG1[7] +=============== ============ + +For example: + + - To boot from the eMMC: 1:ON , 2:ON, 3:ON, 4:OFF, 5:OFF, 6:ON, 7:ON, 8:OFF + - To boot from the microSD slot: 1: ON, 2: OFF, 3: OFF, 4: OFF, 5:OFF, 6:OFF, + 7:ON, 8:OFF + - To boot from the SD slot: 1: OFF, 2: ON, 3: OFF, 4: OFF, 5:OFF, 6:OFF, 7:ON, + 8:OFF + - To boot from SATA: 1: OFF, 2: OFF, 3: OFF, 4: OFF, 5:OFF, 6:ON, 7:OFF, 8:OFF + +You can refer to the BOOT_CFG registers in the I.MX6Q reference manual for +additional details. + +SW6 binary DIP switch array on the PCB revision 2.3: +---------------------------------------------------- +On that PCB revision, SW6 has only 4 positions. + +Switching a position to ON sets the corresponding +register to 1. + +See the following table for a correspondence between the switch positions and +registers: + +=============== ============ +Switch position Register +=============== ============ +1 BOOT_CFG2[3] +2 BOOT_CFG2[4] +3 BOOT_CFG2[5] +4 BOOT_CFG1[5] +=============== ============ + +For example: + +- To boot from the eMMC: 1:ON, 2:ON, 3:ON, 4:ON +- To boot from the microSD slot: 1:ON, 2:OFF, 3:OFF, 4:OFF +- To boot from the SD slot: 1:OFF, 2:ON, 3:OFF, 4:OFF + +You can refer to the BOOT_CFG registers in the I.MX6Q reference manual for +additional details. + +Loading u-boot from USB: +------------------------ +If you need to load u-boot from USB, you can use the following instructions: + +First build imx_usb_loader, as we will need it to load u-boot from USB. This +can be done with the following commands: + +.. code-block:: none + + git clone git://github.com/boundarydevices/imx_usb_loader.git + cd imx_usb_loader + make + +This will create the resulting imx_usb binary. + +When this is done, you can copy the u-boot.imx image that you built earlier +in in the imx_usb_loader directory. + +You will then need to power off the TBS2910 Matrix ARM miniPC and make sure that +the boot switch is set to "UPDATE" + +Once this is done you can connect an USB cable between the computer that will +run imx_usb and the TBS2910 Matrix ARM miniPC. + +If you also need to access the u-boot console, you will also need to connect an +UART cable between the computer running imx_usb and the TBS2910 Matrix ARM +miniPC. + +Once everything is connected you can finally power on the TBS2910 Matrix ARM +miniPC. The SoC will then jump to the serial download and wait for you. + +Finlay, you can load u-boot through USB with with the following command: + +.. code-block:: none + + sudo ./imx_usb -v u-boot.imx + +The u-boot boot messages will then appear in the serial console. + +Install u-boot on the eMMC: +--------------------------- +To install u-boot on the eMMC, you first need to boot the TBS2910 Matrix ARM +miniPC. + +Once booted, you can flash u-boot.imx to mmcblk0boot0 with the +following commands: + +.. code-block:: none + + sudo echo 0 >/sys/block/mmcblk0boot0/force_ro + sudo dd if=u-boot.imx of=/dev/mmcblk0boot0 bs=1k seek=1; sync + +Note that the eMMC card node may vary, so adjust this as needed. + +Once the new u-boot version is installed, to boot on it you then need to power +off the TBS2910 Matrix ARM miniPC. + +Once it is off, you need make sure that the boot switch is set to "BOOT" and +that the SW6 switch is set to boot on the eMMC as described in the previous +sections. + +If you also need to access the u-boot console, you will also need to connect an +UART cable between the computer running imx_usb and the TBS2910 Matrix ARM +miniPC. + +You can then power up the TBS2910 Matrix ARM miniPC and U-Boot messages will +appear in the serial console. + +Booting a distribution: +----------------------- +When booting on the TBS2910 Matrix ARM miniPC, by default U-Boot will first try +to boot from hardcoded offsets from the start of the eMMC. This is for +compatibility with the stock GNU/Linux distribution. + +If that fails it will then try to boot from several interfaces using +'distro_bootcmd': It will first try to boot from the microSD slot, then the +SD slot, then the internal eMMC, then the SATA interface and finally the USB +interface. For more information on how to configure your distribution to boot, +see 'README.distro'. + +Links: +------ + - https://www.tbsdtv.com/download/document/tbs2910/TBS2910-Matrix-ARM-mini-PC-SCH_rev2.1.pdf + - The schematics for the revision 2.1 of the TBS2910 Matrix ARM miniPC. + - https://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf - The + SoC reference manual for additional details on the BOOT_CFG registers. diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index d1f049e62a..b0bd762ac3 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -243,6 +243,21 @@ config PHY_TERANETICS config PHY_TI bool "Texas Instruments Ethernet PHYs support" + ---help--- + Adds PHY registration support for TI PHYs. + +config PHY_TI_DP83867 + select PHY_TI + bool "Texas Instruments Ethernet DP83867 PHY support" + ---help--- + Adds support for the TI DP83867 1Gbit PHY. + +config PHY_TI_GENERIC + select PHY_TI + bool "Texas Instruments Generic Ethernet PHYs support" + ---help--- + Adds support for Generic TI PHYs that don't need special handling but + the PHY name is associated with a PHY ID. config PHY_VITESSE bool "Vitesse Ethernet PHYs support" diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 1d81516ecd..6e722331f1 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -25,7 +25,8 @@ obj-$(CONFIG_PHY_NATSEMI) += natsemi.o obj-$(CONFIG_PHY_REALTEK) += realtek.o obj-$(CONFIG_PHY_SMSC) += smsc.o obj-$(CONFIG_PHY_TERANETICS) += teranetics.o -obj-$(CONFIG_PHY_TI) += dp83867.o +obj-$(CONFIG_PHY_TI) += ti_phy_init.o +obj-$(CONFIG_PHY_TI_DP83867) += dp83867.o obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o obj-$(CONFIG_PHY_VITESSE) += vitesse.o diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index d435cc1e6c..eada4541c9 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -14,6 +14,7 @@ #include <dm.h> #include <dt-bindings/net/ti-dp83867.h> +#include "ti_phy_init.h" /* TI DP83867 */ #define DP83867_DEVADDR 0x1f @@ -430,7 +431,7 @@ static struct phy_driver DP83867_driver = { .shutdown = &genphy_shutdown, }; -int phy_ti_init(void) +int phy_dp83867_init(void) { phy_register(&DP83867_driver); return 0; diff --git a/drivers/net/phy/micrel_ksz8xxx.c b/drivers/net/phy/micrel_ksz8xxx.c index 98a0c83e68..60d42fe984 100644 --- a/drivers/net/phy/micrel_ksz8xxx.c +++ b/drivers/net/phy/micrel_ksz8xxx.c @@ -82,6 +82,21 @@ static struct phy_driver KSZ8051_driver = { .shutdown = &genphy_shutdown, }; +static int ksz8061_config(struct phy_device *phydev) +{ + return phy_write(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A); +} + +static struct phy_driver KSZ8061_driver = { + .name = "Micrel KSZ8061", + .uid = 0x00221570, + .mask = 0xfffff0, + .features = PHY_BASIC_FEATURES, + .config = &ksz8061_config, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + static int ksz8081_config(struct phy_device *phydev) { int ret; @@ -210,6 +225,7 @@ int phy_micrel_ksz8xxx_init(void) phy_register(&KSZ804_driver); phy_register(&KSZ8031_driver); phy_register(&KSZ8051_driver); + phy_register(&KSZ8061_driver); phy_register(&KSZ8081_driver); phy_register(&KS8721_driver); phy_register(&ksz8895_driver); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index cce09c47f9..67789897c2 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -786,17 +786,27 @@ static struct phy_device *get_phy_device_by_mask(struct mii_dev *bus, uint phy_mask, phy_interface_t interface) { - int i; struct phy_device *phydev; - + int devad[] = { + /* Clause-22 */ + MDIO_DEVAD_NONE, + /* Clause-45 */ + MDIO_MMD_PMAPMD, + MDIO_MMD_WIS, + MDIO_MMD_PCS, + MDIO_MMD_PHYXS, + MDIO_MMD_VEND1, + }; + int i, devad_cnt; + + devad_cnt = sizeof(devad)/sizeof(int); phydev = search_for_existing_phy(bus, phy_mask, interface); if (phydev) return phydev; - /* Try Standard (ie Clause 22) access */ - /* Otherwise we have to try Clause 45 */ - for (i = 0; i < 5; i++) { + /* try different access clauses */ + for (i = 0; i < devad_cnt; i++) { phydev = create_phy_by_mask(bus, phy_mask, - i ? i : MDIO_DEVAD_NONE, interface); + devad[i], interface); if (IS_ERR(phydev)) return NULL; if (phydev) diff --git a/drivers/net/phy/ti_phy_init.c b/drivers/net/phy/ti_phy_init.c new file mode 100644 index 0000000000..50eff77692 --- /dev/null +++ b/drivers/net/phy/ti_phy_init.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TI Generic PHY Init to register any TI Ethernet PHYs + * + * Author: Dan Murphy <dmurphy@ti.com> + * + * Copyright (C) 2019-20 Texas Instruments Inc. + */ + +#include <phy.h> +#include "ti_phy_init.h" + +#ifdef CONFIG_PHY_TI_GENERIC +static struct phy_driver dp83822_driver = { + .name = "TI DP83822", + .uid = 0x2000a240, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83826nc_driver = { + .name = "TI DP83826NC", + .uid = 0x2000a110, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83826c_driver = { + .name = "TI DP83826C", + .uid = 0x2000a130, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825s_driver = { + .name = "TI DP83825S", + .uid = 0x2000a140, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825i_driver = { + .name = "TI DP83825I", + .uid = 0x2000a150, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825m_driver = { + .name = "TI DP83825M", + .uid = 0x2000a160, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; + +static struct phy_driver dp83825cs_driver = { + .name = "TI DP83825CS", + .uid = 0x2000a170, + .mask = 0xfffffff0, + .features = PHY_BASIC_FEATURES, + .config = &genphy_config_aneg, + .startup = &genphy_startup, + .shutdown = &genphy_shutdown, +}; +#endif /* CONFIG_PHY_TI_GENERIC */ + +int phy_ti_init(void) +{ +#ifdef CONFIG_PHY_TI_DP83867 + phy_dp83867_init(); +#endif + +#ifdef CONFIG_PHY_TI_GENERIC + phy_register(&dp83822_driver); + phy_register(&dp83825s_driver); + phy_register(&dp83825i_driver); + phy_register(&dp83825m_driver); + phy_register(&dp83825cs_driver); + phy_register(&dp83826c_driver); + phy_register(&dp83826nc_driver); +#endif + return 0; +} diff --git a/drivers/net/phy/ti_phy_init.h b/drivers/net/phy/ti_phy_init.h new file mode 100644 index 0000000000..6c7f6c640a --- /dev/null +++ b/drivers/net/phy/ti_phy_init.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * TI Generic Ethernet PHY + * + * Author: Dan Murphy <dmurphy@ti.com> + * + * Copyright (C) 2019-20 Texas Instruments Inc. + */ + +#ifndef _TI_GEN_PHY_H +#define _TI_GEN_PHY_H + +int phy_dp83867_init(void); + +#endif /* _TI_GEN_PHY_H */ diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 0daeefa489..8a6f305893 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -70,6 +70,7 @@ #include <common.h> #include <cpu_func.h> +#include <dm.h> #include <log.h> #include <malloc.h> #include <net.h> @@ -96,8 +97,13 @@ #define DEBUG_TX 0 /* set to 1 to enable debug code */ #define DEBUG_RX 0 /* set to 1 to enable debug code */ -#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a) -#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) +#ifdef CONFIG_DM_ETH +#define bus_to_phys(devno, a) dm_pci_mem_to_phys((devno), (a)) +#define phys_to_bus(devno, a) dm_pci_phys_to_mem((devno), (a)) +#else +#define bus_to_phys(devno, a) pci_mem_to_phys((pci_dev_t)(devno), (a)) +#define phys_to_bus(devno, a) pci_phys_to_mem((pci_dev_t)(devno), (a)) +#endif /* Symbolic offsets to registers. */ /* Ethernet hardware address. */ @@ -191,8 +197,19 @@ #define RTL_STS_RXBADALIGN BIT(1) #define RTL_STS_RXSTATUSOK BIT(0) -static unsigned int cur_rx, cur_tx; -static int ioaddr; +struct rtl8139_priv { +#ifndef CONFIG_DM_ETH + struct eth_device dev; + pci_dev_t devno; +#else + struct udevice *devno; +#endif + unsigned int rxstatus; + unsigned int cur_rx; + unsigned int cur_tx; + unsigned long ioaddr; + unsigned char enetaddr[6]; +}; /* The RTL8139 can only transmit from a contiguous, aligned memory block. */ static unsigned char tx_buffer[TX_BUF_SIZE] __aligned(4); @@ -214,51 +231,52 @@ static unsigned char rx_ring[RX_BUF_LEN + 16] __aligned(4); #define EE_READ_CMD 6 #define EE_ERASE_CMD 7 -static void rtl8139_eeprom_delay(uintptr_t regbase) +static void rtl8139_eeprom_delay(struct rtl8139_priv *priv) { /* * Delay between EEPROM clock transitions. * No extra delay is needed with 33MHz PCI, but 66MHz may change this. */ - inl(regbase + RTL_REG_CFG9346); + inl(priv->ioaddr + RTL_REG_CFG9346); } -static int rtl8139_read_eeprom(unsigned int location, unsigned int addr_len) +static int rtl8139_read_eeprom(struct rtl8139_priv *priv, + unsigned int location, unsigned int addr_len) { unsigned int read_cmd = location | (EE_READ_CMD << addr_len); - uintptr_t ee_addr = ioaddr + RTL_REG_CFG9346; + uintptr_t ee_addr = priv->ioaddr + RTL_REG_CFG9346; unsigned int retval = 0; u8 dataval; int i; outb(EE_ENB & ~EE_CS, ee_addr); outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { dataval = (read_cmd & BIT(i)) ? EE_DATA_WRITE : 0; outb(EE_ENB | dataval, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); } outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); for (i = 16; i > 0; i--) { outb(EE_ENB | EE_SHIFT_CLK, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); retval <<= 1; retval |= inb(ee_addr) & EE_DATA_READ; outb(EE_ENB, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); } /* Terminate the EEPROM access. */ outb(~EE_CS, ee_addr); - rtl8139_eeprom_delay(ioaddr); + rtl8139_eeprom_delay(priv); return retval; } @@ -268,29 +286,29 @@ static const unsigned int rtl8139_rx_config = (RX_FIFO_THRESH << 13) | (RX_DMA_BURST << 8); -static void rtl8139_set_rx_mode(struct eth_device *dev) +static void rtl8139_set_rx_mode(struct rtl8139_priv *priv) { /* !IFF_PROMISC */ unsigned int rx_mode = RTL_REG_RXCONFIG_ACCEPTBROADCAST | RTL_REG_RXCONFIG_ACCEPTMULTICAST | RTL_REG_RXCONFIG_ACCEPTMYPHYS; - outl(rtl8139_rx_config | rx_mode, ioaddr + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config | rx_mode, priv->ioaddr + RTL_REG_RXCONFIG); - outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 0); - outl(0xffffffff, ioaddr + RTL_REG_MAR0 + 4); + outl(0xffffffff, priv->ioaddr + RTL_REG_MAR0 + 0); + outl(0xffffffff, priv->ioaddr + RTL_REG_MAR0 + 4); } -static void rtl8139_hw_reset(struct eth_device *dev) +static void rtl8139_hw_reset(struct rtl8139_priv *priv) { u8 reg; int i; - outb(RTL_REG_CHIPCMD_CMDRESET, ioaddr + RTL_REG_CHIPCMD); + outb(RTL_REG_CHIPCMD_CMDRESET, priv->ioaddr + RTL_REG_CHIPCMD); /* Give the chip 10ms to finish the reset. */ for (i = 0; i < 100; i++) { - reg = inb(ioaddr + RTL_REG_CHIPCMD); + reg = inb(priv->ioaddr + RTL_REG_CHIPCMD); if (!(reg & RTL_REG_CHIPCMD_CMDRESET)) break; @@ -298,25 +316,25 @@ static void rtl8139_hw_reset(struct eth_device *dev) } } -static void rtl8139_reset(struct eth_device *dev) +static void rtl8139_reset(struct rtl8139_priv *priv) { int i; - cur_rx = 0; - cur_tx = 0; + priv->cur_rx = 0; + priv->cur_tx = 0; - rtl8139_hw_reset(dev); + rtl8139_hw_reset(priv); for (i = 0; i < ETH_ALEN; i++) - outb(dev->enetaddr[i], ioaddr + RTL_REG_MAC0 + i); + outb(priv->enetaddr[i], priv->ioaddr + RTL_REG_MAC0 + i); /* Must enable Tx/Rx before setting transfer thresholds! */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - ioaddr + RTL_REG_CHIPCMD); + priv->ioaddr + RTL_REG_CHIPCMD); /* accept no frames yet! */ - outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); - outl((TX_DMA_BURST << 8) | 0x03000000, ioaddr + RTL_REG_TXCONFIG); + outl(rtl8139_rx_config, priv->ioaddr + RTL_REG_RXCONFIG); + outl((TX_DMA_BURST << 8) | 0x03000000, priv->ioaddr + RTL_REG_TXCONFIG); /* * The Linux driver changes RTL_REG_CONFIG1 here to use a different @@ -331,7 +349,7 @@ static void rtl8139_reset(struct eth_device *dev) debug_cond(DEBUG_RX, "rx ring address is %p\n", rx_ring); flush_cache((unsigned long)rx_ring, RX_BUF_LEN); - outl(phys_to_bus((int)rx_ring), ioaddr + RTL_REG_RXBUF); + outl(phys_to_bus(priv->devno, (int)rx_ring), priv->ioaddr + RTL_REG_RXBUF); /* * If we add multicast support, the RTL_REG_MAR0 register would have @@ -340,28 +358,27 @@ static void rtl8139_reset(struct eth_device *dev) * unicast. */ outb(RTL_REG_CHIPCMD_CMDRXENB | RTL_REG_CHIPCMD_CMDTXENB, - ioaddr + RTL_REG_CHIPCMD); + priv->ioaddr + RTL_REG_CHIPCMD); - outl(rtl8139_rx_config, ioaddr + RTL_REG_RXCONFIG); + outl(rtl8139_rx_config, priv->ioaddr + RTL_REG_RXCONFIG); /* Start the chip's Tx and Rx process. */ - outl(0, ioaddr + RTL_REG_RXMISSED); + outl(0, priv->ioaddr + RTL_REG_RXMISSED); - rtl8139_set_rx_mode(dev); + rtl8139_set_rx_mode(priv); /* Disable all known interrupts by setting the interrupt mask. */ - outw(0, ioaddr + RTL_REG_INTRMASK); + outw(0, priv->ioaddr + RTL_REG_INTRMASK); } -static int rtl8139_send(struct eth_device *dev, void *packet, int length) +static int rtl8139_send_common(struct rtl8139_priv *priv, + void *packet, int length) { unsigned int len = length; unsigned long txstatus; unsigned int status; int i = 0; - ioaddr = dev->iobase; - memcpy(tx_buffer, packet, length); debug_cond(DEBUG_TX, "sending %d bytes\n", len); @@ -374,13 +391,13 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) tx_buffer[len++] = '\0'; flush_cache((unsigned long)tx_buffer, length); - outl(phys_to_bus((unsigned long)tx_buffer), - ioaddr + RTL_REG_TXADDR0 + cur_tx * 4); + outl(phys_to_bus(priv->devno, (unsigned long)tx_buffer), + priv->ioaddr + RTL_REG_TXADDR0 + priv->cur_tx * 4); outl(((TX_FIFO_THRESH << 11) & 0x003f0000) | len, - ioaddr + RTL_REG_TXSTATUS0 + cur_tx * 4); + priv->ioaddr + RTL_REG_TXSTATUS0 + priv->cur_tx * 4); do { - status = inw(ioaddr + RTL_REG_INTRSTATUS); + status = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* * Only acknlowledge interrupt sources we can properly * handle here - the RTL_REG_INTRSTATUS_RXOVERFLOW/ @@ -389,26 +406,26 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) */ status &= RTL_REG_INTRSTATUS_TXOK | RTL_REG_INTRSTATUS_TXERR | RTL_REG_INTRSTATUS_PCIERR; - outw(status, ioaddr + RTL_REG_INTRSTATUS); + outw(status, priv->ioaddr + RTL_REG_INTRSTATUS); if (status) break; udelay(10); } while (i++ < RTL_TIMEOUT); - txstatus = inl(ioaddr + RTL_REG_TXSTATUS0 + cur_tx * 4); + txstatus = inl(priv->ioaddr + RTL_REG_TXSTATUS0 + priv->cur_tx * 4); if (!(status & RTL_REG_INTRSTATUS_TXOK)) { debug_cond(DEBUG_TX, "tx timeout/error (%d usecs), status %hX txstatus %lX\n", 10 * i, status, txstatus); - rtl8139_reset(dev); + rtl8139_reset(priv); return 0; } - cur_tx = (cur_tx + 1) % NUM_TX_DESC; + priv->cur_tx = (priv->cur_tx + 1) % NUM_TX_DESC; debug_cond(DEBUG_TX, "tx done, status %hX txstatus %lX\n", status, txstatus); @@ -416,28 +433,26 @@ static int rtl8139_send(struct eth_device *dev, void *packet, int length) return length; } -static int rtl8139_recv(struct eth_device *dev) +static int rtl8139_recv_common(struct rtl8139_priv *priv, unsigned char *rxdata, + uchar **packetp) { const unsigned int rxstat = RTL_REG_INTRSTATUS_RXFIFOOVER | RTL_REG_INTRSTATUS_RXOVERFLOW | RTL_REG_INTRSTATUS_RXOK; unsigned int rx_size, rx_status; unsigned int ring_offs; - unsigned int status; int length = 0; - ioaddr = dev->iobase; - - if (inb(ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) + if (inb(priv->ioaddr + RTL_REG_CHIPCMD) & RTL_REG_CHIPCMD_RXBUFEMPTY) return 0; - status = inw(ioaddr + RTL_REG_INTRSTATUS); + priv->rxstatus = inw(priv->ioaddr + RTL_REG_INTRSTATUS); /* See below for the rest of the interrupt acknowledges. */ - outw(status & ~rxstat, ioaddr + RTL_REG_INTRSTATUS); + outw(priv->rxstatus & ~rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); - debug_cond(DEBUG_RX, "%s: int %hX ", __func__, status); + debug_cond(DEBUG_RX, "%s: int %hX ", __func__, priv->rxstatus); - ring_offs = cur_rx % RX_BUF_LEN; + ring_offs = priv->cur_rx % RX_BUF_LEN; /* ring_offs is guaranteed being 4-byte aligned */ rx_status = le32_to_cpu(*(unsigned int *)(rx_ring + ring_offs)); rx_size = rx_status >> 16; @@ -450,59 +465,61 @@ static int rtl8139_recv(struct eth_device *dev) (rx_size > ETH_FRAME_LEN + 4)) { printf("rx error %hX\n", rx_status); /* this clears all interrupts still pending */ - rtl8139_reset(dev); + rtl8139_reset(priv); return 0; } /* Received a good packet */ length = rx_size - 4; /* no one cares about the FCS */ if (ring_offs + 4 + rx_size - 4 > RX_BUF_LEN) { - unsigned char rxdata[RX_BUF_LEN]; int semi_count = RX_BUF_LEN - ring_offs - 4; memcpy(rxdata, rx_ring + ring_offs + 4, semi_count); memcpy(&rxdata[semi_count], rx_ring, rx_size - 4 - semi_count); - net_process_received_packet(rxdata, length); + *packetp = rxdata; debug_cond(DEBUG_RX, "rx packet %d+%d bytes", semi_count, rx_size - 4 - semi_count); } else { - net_process_received_packet(rx_ring + ring_offs + 4, length); + *packetp = rx_ring + ring_offs + 4; debug_cond(DEBUG_RX, "rx packet %d bytes", rx_size - 4); } + + return length; +} + +static int rtl8139_free_pkt_common(struct rtl8139_priv *priv, unsigned int len) +{ + const unsigned int rxstat = RTL_REG_INTRSTATUS_RXFIFOOVER | + RTL_REG_INTRSTATUS_RXOVERFLOW | + RTL_REG_INTRSTATUS_RXOK; + unsigned int rx_size = len + 4; + flush_cache((unsigned long)rx_ring, RX_BUF_LEN); - cur_rx = ROUND(cur_rx + rx_size + 4, 4); - outw(cur_rx - 16, ioaddr + RTL_REG_RXBUFPTR); + priv->cur_rx = ROUND(priv->cur_rx + rx_size + 4, 4); + outw(priv->cur_rx - 16, priv->ioaddr + RTL_REG_RXBUFPTR); /* * See RTL8139 Programming Guide V0.1 for the official handling of * Rx overflow situations. The document itself contains basically * no usable information, except for a few exception handling rules. */ - outw(status & rxstat, ioaddr + RTL_REG_INTRSTATUS); + outw(priv->rxstatus & rxstat, priv->ioaddr + RTL_REG_INTRSTATUS); - return length; + return 0; } -static int rtl8139_init(struct eth_device *dev, bd_t *bis) +static int rtl8139_init_common(struct rtl8139_priv *priv) { - unsigned short *ap = (unsigned short *)dev->enetaddr; - int addr_len, i; u8 reg; - ioaddr = dev->iobase; - /* Bring the chip out of low-power mode. */ - outb(0x00, ioaddr + RTL_REG_CONFIG1); + outb(0x00, priv->ioaddr + RTL_REG_CONFIG1); - addr_len = rtl8139_read_eeprom(0, 8) == 0x8129 ? 8 : 6; - for (i = 0; i < 3; i++) - *ap++ = le16_to_cpu(rtl8139_read_eeprom(i + 7, addr_len)); - - rtl8139_reset(dev); + rtl8139_reset(priv); - reg = inb(ioaddr + RTL_REG_MEDIASTATUS); + reg = inb(priv->ioaddr + RTL_REG_MEDIASTATUS); if (reg & RTL_REG_MEDIASTATUS_MSRLINKFAIL) { printf("Cable not connected or other link failure\n"); return -1; @@ -511,27 +528,82 @@ static int rtl8139_init(struct eth_device *dev, bd_t *bis) return 0; } -static void rtl8139_stop(struct eth_device *dev) +static void rtl8139_stop_common(struct rtl8139_priv *priv) { - ioaddr = dev->iobase; + rtl8139_hw_reset(priv); +} - rtl8139_hw_reset(dev); +static void rtl8139_get_hwaddr(struct rtl8139_priv *priv) +{ + unsigned short *ap = (unsigned short *)priv->enetaddr; + int i, addr_len; + + /* Bring the chip out of low-power mode. */ + outb(0x00, priv->ioaddr + RTL_REG_CONFIG1); + + addr_len = rtl8139_read_eeprom(priv, 0, 8) == 0x8129 ? 8 : 6; + for (i = 0; i < 3; i++) + *ap++ = le16_to_cpu(rtl8139_read_eeprom(priv, i + 7, addr_len)); } -static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, - int join) +static void rtl8139_name(char *str, int card_number) { - return 0; + sprintf(str, "RTL8139#%u", card_number); } static struct pci_device_id supported[] = { - { PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139 }, - { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139 }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_8139) }, { } }; +#ifndef CONFIG_DM_ETH +static int rtl8139_bcast_addr(struct eth_device *dev, const u8 *bcast_mac, + int join) +{ + return 0; +} + +static int rtl8139_init(struct eth_device *dev, bd_t *bis) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + return rtl8139_init_common(priv); +} + +static void rtl8139_stop(struct eth_device *dev) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + return rtl8139_stop_common(priv); +} + +static int rtl8139_send(struct eth_device *dev, void *packet, int length) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + + return rtl8139_send_common(priv, packet, length); +} + +static int rtl8139_recv(struct eth_device *dev) +{ + struct rtl8139_priv *priv = container_of(dev, struct rtl8139_priv, dev); + unsigned char rxdata[RX_BUF_LEN]; + uchar *packet; + int ret; + + ret = rtl8139_recv_common(priv, rxdata, &packet); + if (ret) { + net_process_received_packet(packet, ret); + rtl8139_free_pkt_common(priv, ret); + } + + return ret; +} + int rtl8139_initialize(bd_t *bis) { + struct rtl8139_priv *priv; struct eth_device *dev; int card_number = 0; pci_dev_t devno; @@ -549,23 +621,31 @@ int rtl8139_initialize(bd_t *bis) debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); - dev = (struct eth_device *)malloc(sizeof(*dev)); - if (!dev) { + priv = calloc(1, sizeof(*priv)); + if (!priv) { printf("Can not allocate memory of rtl8139\n"); break; } - memset(dev, 0, sizeof(*dev)); - sprintf(dev->name, "RTL8139#%d", card_number); + priv->devno = devno; + priv->ioaddr = (unsigned long)bus_to_phys(devno, iobase); + + dev = &priv->dev; + + rtl8139_name(dev->name, card_number); - dev->priv = (void *)devno; - dev->iobase = (int)bus_to_phys(iobase); + dev->iobase = priv->ioaddr; /* Non-DM compatibility */ dev->init = rtl8139_init; dev->halt = rtl8139_stop; dev->send = rtl8139_send; dev->recv = rtl8139_recv; dev->mcast = rtl8139_bcast_addr; + rtl8139_get_hwaddr(priv); + + /* Non-DM compatibility */ + memcpy(priv->dev.enetaddr, priv->enetaddr, 6); + eth_register(dev); card_number++; @@ -577,3 +657,123 @@ int rtl8139_initialize(bd_t *bis) return card_number; } +#else /* DM_ETH */ +static int rtl8139_start(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct rtl8139_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + return rtl8139_init_common(priv); +} + +static void rtl8139_stop(struct udevice *dev) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + + rtl8139_stop_common(priv); +} + +static int rtl8139_send(struct udevice *dev, void *packet, int length) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + int ret; + + ret = rtl8139_send_common(priv, packet, length); + + return ret ? 0 : -ETIMEDOUT; +} + +static int rtl8139_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + static unsigned char rxdata[RX_BUF_LEN]; + + return rtl8139_recv_common(priv, rxdata, packetp); +} + +static int rtl8139_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + + rtl8139_free_pkt_common(priv, length); + + return 0; +} + +static int rtl8139_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct rtl8139_priv *priv = dev_get_priv(dev); + + memcpy(priv->enetaddr, plat->enetaddr, sizeof(plat->enetaddr)); + + rtl8139_reset(priv); + + return 0; +} + +static int rtl8139_read_rom_hwaddr(struct udevice *dev) +{ + struct rtl8139_priv *priv = dev_get_priv(dev); + + rtl8139_get_hwaddr(priv); + + return 0; +} + +static int rtl8139_bind(struct udevice *dev) +{ + static int card_number; + char name[16]; + + rtl8139_name(name, card_number++); + + return device_set_name(dev, name); +} + +static int rtl8139_probe(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_platdata(dev); + struct rtl8139_priv *priv = dev_get_priv(dev); + u32 iobase; + + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase); + iobase &= ~0xf; + + debug("rtl8139: REALTEK RTL8139 @0x%x\n", iobase); + + priv->devno = dev; + priv->ioaddr = (unsigned long)bus_to_phys(dev, iobase); + + rtl8139_get_hwaddr(priv); + memcpy(plat->enetaddr, priv->enetaddr, sizeof(priv->enetaddr)); + + dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x20); + + return 0; +} + +static const struct eth_ops rtl8139_ops = { + .start = rtl8139_start, + .send = rtl8139_send, + .recv = rtl8139_recv, + .stop = rtl8139_stop, + .free_pkt = rtl8139_free_pkt, + .write_hwaddr = rtl8139_write_hwaddr, + .read_rom_hwaddr = rtl8139_read_rom_hwaddr, +}; + +U_BOOT_DRIVER(eth_rtl8139) = { + .name = "eth_rtl8139", + .id = UCLASS_ETH, + .bind = rtl8139_bind, + .probe = rtl8139_probe, + .ops = &rtl8139_ops, + .priv_auto_alloc_size = sizeof(struct rtl8139_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; + +U_BOOT_PCI_DEVICE(eth_rtl8139, supported); +#endif diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 75058fdadc..fb4fae20e5 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -240,6 +240,9 @@ enum RTL8169_register_content { /*_TBICSRBit*/ TBILinkOK = 0x02000000, + + /* FuncEvent/Misc */ + RxDv_Gated_En = 0x80000, }; static struct { @@ -1210,6 +1213,19 @@ static int rtl8169_eth_probe(struct udevice *dev) return ret; } + /* + * WAR for DHCP failure after rebooting from kernel. + * Clear RxDv_Gated_En bit which was set by kernel driver. + * Without this, U-Boot can't get an IP via DHCP. + * Register (FuncEvent, aka MISC) and RXDV_GATED_EN bit are from + * the r8169.c kernel driver. + */ + + u32 val = RTL_R32(FuncEvent); + debug("%s: FuncEvent/Misc (0xF0) = 0x%08X\n", __func__, val); + val &= ~RxDv_Gated_En; + RTL_W32(FuncEvent, val); + return 0; } diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile index 4a34813804..d4be0c7350 100644 --- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -8,10 +8,6 @@ extra-$(CONFIG_SMC91111) += smc91111_eeprom extra-$(CONFIG_SPI_FLASH_ATMEL) += atmel_df_pow2 extra-$(CONFIG_PPC) += sched -ifndef CONFIG_DM_ETH -extra-$(CONFIG_SMC911X) += smc911x_eeprom -endif - # # Some versions of make do not handle trailing white spaces properly; # leading to build failures. The problem was found with GNU Make 3.80. diff --git a/examples/standalone/smc911x_eeprom.c b/examples/standalone/smc911x_eeprom.c deleted file mode 100644 index 9bd9a6efa3..0000000000 --- a/examples/standalone/smc911x_eeprom.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * smc911x_eeprom.c - EEPROM interface to SMC911x parts. - * Only tested on SMSC9118 though ... - * - * Copyright 2004-2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - * - * Based on smc91111_eeprom.c which: - * Heavily borrowed from the following peoples GPL'ed software: - * - Wolfgang Denk, DENX Software Engineering, wd@denx.de - * Das U-Boot - * - Ladislav Michl ladis@linux-mips.org - * A rejected patch on the U-Boot mailing list - */ - -#include <common.h> -#include <console.h> -#include <exports.h> -#include <net.h> -#include <linux/ctype.h> -#include <linux/types.h> -#include "../drivers/net/smc911x.h" - -#define DRIVERNAME "smc911x" - -#if defined (CONFIG_SMC911X_32_BIT) && \ - defined (CONFIG_SMC911X_16_BIT) -#error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \ - CONFIG_SMC911X_16_BIT shall be set" -#endif - -struct chip_id { - u16 id; - char *name; -}; - -static const struct chip_id chip_ids[] = { - { CHIP_89218, "LAN89218" }, - { CHIP_9115, "LAN9115" }, - { CHIP_9116, "LAN9116" }, - { CHIP_9117, "LAN9117" }, - { CHIP_9118, "LAN9118" }, - { CHIP_9211, "LAN9211" }, - { CHIP_9215, "LAN9215" }, - { CHIP_9216, "LAN9216" }, - { CHIP_9217, "LAN9217" }, - { CHIP_9218, "LAN9218" }, - { CHIP_9220, "LAN9220" }, - { CHIP_9221, "LAN9221" }, - { 0, NULL }, -}; - -#if defined (CONFIG_SMC911X_32_BIT) -static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) -{ - return *(volatile u32*)(dev->iobase + offset); -} - -static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) -{ - *(volatile u32*)(dev->iobase + offset) = val; -} -#elif defined (CONFIG_SMC911X_16_BIT) -static u32 smc911x_reg_read(struct eth_device *dev, u32 offset) -{ - volatile u16 *addr_16 = (u16 *)(dev->iobase + offset); - return (*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16); -} -static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val) -{ - *(volatile u16 *)(dev->iobase + offset) = (u16)val; - *(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16); -} -#else -#error "SMC911X: undefined bus width" -#endif /* CONFIG_SMC911X_16_BIT */ - -static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg) -{ - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - smc911x_reg_write(dev, MAC_CSR_CMD, - MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg); - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - - return smc911x_reg_read(dev, MAC_CSR_DATA); -} - -static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data) -{ - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; - smc911x_reg_write(dev, MAC_CSR_DATA, data); - smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg); - while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) - ; -} - -static int smc911x_detect_chip(struct eth_device *dev) -{ - unsigned long val, i; - - val = smc911x_reg_read(dev, BYTE_TEST); - if (val == 0xffffffff) { - /* Special case -- no chip present */ - return -1; - } else if (val != 0x87654321) { - printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val); - return -1; - } - - val = smc911x_reg_read(dev, ID_REV) >> 16; - for (i = 0; chip_ids[i].id != 0; i++) { - if (chip_ids[i].id == val) break; - } - if (!chip_ids[i].id) { - printf(DRIVERNAME ": Unknown chip ID %04lx\n", val); - return -1; - } - - dev->priv = (void *)&chip_ids[i]; - - return 0; -} - -static void smc911x_reset(struct eth_device *dev) -{ - int timeout; - - /* - * Take out of PM setting first - * Device is already wake up if PMT_CTRL_READY bit is set - */ - if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) { - /* Write to the bytetest will take out of powerdown */ - smc911x_reg_write(dev, BYTE_TEST, 0x0); - - timeout = 10; - - while (timeout-- && - !(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY)) - udelay(10); - if (timeout < 0) { - printf(DRIVERNAME - ": timeout waiting for PM restore\n"); - return; - } - } - - /* Disable interrupts */ - smc911x_reg_write(dev, INT_EN, 0); - - smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST); - - timeout = 1000; - while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) - udelay(10); - - if (timeout < 0) { - printf(DRIVERNAME ": reset timeout\n"); - return; - } - - /* Reset the FIFO level and flow control settings */ - smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN); - smc911x_reg_write(dev, AFC_CFG, 0x0050287F); - - /* Set to LED outputs */ - smc911x_reg_write(dev, GPIO_CFG, 0x70070000); -} - -/** - * smsc_ctrlc - detect press of CTRL+C (common ctrlc() isnt exported!?) - */ -static int smsc_ctrlc(void) -{ - return (tstc() && getc() == 0x03); -} - -/** - * usage - dump usage information - */ -static void usage(void) -{ - puts( - "MAC/EEPROM Commands:\n" - " P : Print the MAC addresses\n" - " D : Dump the EEPROM contents\n" - " M : Dump the MAC contents\n" - " C : Copy the MAC address from the EEPROM to the MAC\n" - " W : Write a register in the EEPROM or in the MAC\n" - " Q : Quit\n" - "\n" - "Some commands take arguments:\n" - " W <E|M> <register> <value>\n" - " E: EEPROM M: MAC\n" - ); -} - -/** - * dump_regs - dump the MAC registers - * - * Registers 0x00 - 0x50 are FIFOs. The 0x50+ are the control registers - * and they're all 32bits long. 0xB8+ are reserved, so don't bother. - */ -static void dump_regs(struct eth_device *dev) -{ - u8 i, j = 0; - for (i = 0x50; i < 0xB8; i += sizeof(u32)) - printf("%02x: 0x%08x %c", i, - smc911x_reg_read(dev, i), - (j++ % 2 ? '\n' : ' ')); -} - -/** - * do_eeprom_cmd - handle eeprom communication - */ -static int do_eeprom_cmd(struct eth_device *dev, int cmd, u8 reg) -{ - if (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) { - printf("eeprom_cmd: busy at start (E2P_CMD = 0x%08x)\n", - smc911x_reg_read(dev, E2P_CMD)); - return -1; - } - - smc911x_reg_write(dev, E2P_CMD, E2P_CMD_EPC_BUSY | cmd | reg); - - while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) - if (smsc_ctrlc()) { - printf("eeprom_cmd: timeout (E2P_CMD = 0x%08x)\n", - smc911x_reg_read(dev, E2P_CMD)); - return -1; - } - - return 0; -} - -/** - * read_eeprom_reg - read specified register in EEPROM - */ -static u8 read_eeprom_reg(struct eth_device *dev, u8 reg) -{ - int ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_READ, reg); - return (ret ? : smc911x_reg_read(dev, E2P_DATA)); -} - -/** - * write_eeprom_reg - write specified value into specified register in EEPROM - */ -static int write_eeprom_reg(struct eth_device *dev, u8 value, u8 reg) -{ - int ret; - - /* enable erasing/writing */ - ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN, reg); - if (ret) - goto done; - - /* erase the eeprom reg */ - ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE, reg); - if (ret) - goto done; - - /* write the eeprom reg */ - smc911x_reg_write(dev, E2P_DATA, value); - ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE, reg); - if (ret) - goto done; - - /* disable erasing/writing */ - ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWDS, reg); - - done: - return ret; -} - -/** - * skip_space - find first non-whitespace in given pointer - */ -static char *skip_space(char *buf) -{ - while (isblank(buf[0])) - ++buf; - return buf; -} - -/** - * write_stuff - handle writing of MAC registers / eeprom - */ -static void write_stuff(struct eth_device *dev, char *line) -{ - char dest; - char *endp; - u8 reg; - u32 value; - - /* Skip over the "W " part of the command */ - line = skip_space(line + 1); - - /* Figure out destination */ - switch (line[0]) { - case 'E': - case 'M': - dest = line[0]; - break; - default: - invalid_usage: - printf("ERROR: Invalid write usage\n"); - usage(); - return; - } - - /* Get the register to write */ - line = skip_space(line + 1); - reg = simple_strtoul(line, &endp, 16); - if (line == endp) - goto invalid_usage; - - /* Get the value to write */ - line = skip_space(endp); - value = simple_strtoul(line, &endp, 16); - if (line == endp) - goto invalid_usage; - - /* Check for trailing cruft */ - line = skip_space(endp); - if (line[0]) - goto invalid_usage; - - /* Finally, execute the command */ - if (dest == 'E') { - printf("Writing EEPROM register %02x with %02x\n", reg, value); - write_eeprom_reg(dev, value, reg); - } else { - printf("Writing MAC register %02x with %08x\n", reg, value); - smc911x_reg_write(dev, reg, value); - } -} - -/** - * copy_from_eeprom - copy MAC address in eeprom to address registers - */ -static void copy_from_eeprom(struct eth_device *dev) -{ - ulong addrl = - read_eeprom_reg(dev, 0x01) | - read_eeprom_reg(dev, 0x02) << 8 | - read_eeprom_reg(dev, 0x03) << 16 | - read_eeprom_reg(dev, 0x04) << 24; - ulong addrh = - read_eeprom_reg(dev, 0x05) | - read_eeprom_reg(dev, 0x06) << 8; - smc911x_set_mac_csr(dev, ADDRL, addrl); - smc911x_set_mac_csr(dev, ADDRH, addrh); - puts("EEPROM contents copied to MAC\n"); -} - -/** - * print_macaddr - print MAC address registers and MAC address in eeprom - */ -static void print_macaddr(struct eth_device *dev) -{ - puts("Current MAC Address in MAC: "); - ulong addrl = smc911x_get_mac_csr(dev, ADDRL); - ulong addrh = smc911x_get_mac_csr(dev, ADDRH); - printf("%02x:%02x:%02x:%02x:%02x:%02x\n", - (u8)(addrl), (u8)(addrl >> 8), (u8)(addrl >> 16), - (u8)(addrl >> 24), (u8)(addrh), (u8)(addrh >> 8)); - - puts("Current MAC Address in EEPROM: "); - int i; - for (i = 1; i < 6; ++i) - printf("%02x:", read_eeprom_reg(dev, i)); - printf("%02x\n", read_eeprom_reg(dev, i)); -} - -/** - * dump_eeprom - dump the whole content of the EEPROM - */ -static void dump_eeprom(struct eth_device *dev) -{ - int i; - puts("EEPROM:\n"); - for (i = 0; i < 7; ++i) - printf("%02x: 0x%02x\n", i, read_eeprom_reg(dev, i)); -} - -/** - * smc911x_init - get the MAC/EEPROM up and ready for use - */ -static int smc911x_init(struct eth_device *dev) -{ - /* See if there is anything there */ - if (smc911x_detect_chip(dev)) - return 1; - - smc911x_reset(dev); - - /* Make sure we set EEDIO/EECLK to the EEPROM */ - if (smc911x_reg_read(dev, GPIO_CFG) & GPIO_CFG_EEPR_EN) { - while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) - if (smsc_ctrlc()) { - printf("init: timeout (E2P_CMD = 0x%08x)\n", - smc911x_reg_read(dev, E2P_CMD)); - return 1; - } - smc911x_reg_write(dev, GPIO_CFG, - smc911x_reg_read(dev, GPIO_CFG) & ~GPIO_CFG_EEPR_EN); - } - - return 0; -} - -/** - * getline - consume a line of input and handle some escape sequences - */ -static char *getline(void) -{ - static char buffer[100]; - char c; - size_t i; - - i = 0; - while (1) { - buffer[i] = '\0'; - while (!tstc()) - continue; - - c = getc(); - /* Convert to uppercase */ - if (c >= 'a' && c <= 'z') - c -= ('a' - 'A'); - - switch (c) { - case '\r': /* Enter/Return key */ - case '\n': - puts("\n"); - return buffer; - - case 0x03: /* ^C - break */ - return NULL; - - case 0x5F: - case 0x08: /* ^H - backspace */ - case 0x7F: /* DEL - backspace */ - if (i) { - puts("\b \b"); - i--; - } - break; - - default: - /* Ignore control characters */ - if (c < 0x20) - break; - /* Queue up all other characters */ - buffer[i++] = c; - printf("%c", c); - break; - } - } -} - -/** - * smc911x_eeprom - our application's main() function - */ -int smc911x_eeprom(int argc, char *const argv[]) -{ - /* Avoid initializing on stack as gcc likes to call memset() */ - struct eth_device dev; - dev.iobase = CONFIG_SMC911X_BASE; - - /* Print the ABI version */ - app_startup(argv); - if (XF_VERSION != get_version()) { - printf("Expects ABI version %d\n", XF_VERSION); - printf("Actual U-Boot ABI version %lu\n", get_version()); - printf("Can't run\n\n"); - return 1; - } - - /* Initialize the MAC/EEPROM somewhat */ - puts("\n"); - if (smc911x_init(&dev)) - return 1; - - /* Dump helpful usage information */ - puts("\n"); - usage(); - puts("\n"); - - while (1) { - char *line; - - /* Send the prompt and wait for a line */ - puts("eeprom> "); - line = getline(); - - /* Got a ctrl+c */ - if (!line) - return 0; - - /* Eat leading space */ - line = skip_space(line); - - /* Empty line, try again */ - if (!line[0]) - continue; - - /* Only accept 1 letter commands */ - if (line[0] && line[1] && !isblank(line[1])) - goto unknown_cmd; - - /* Now parse the command */ - switch (line[0]) { - case 'W': write_stuff(&dev, line); break; - case 'D': dump_eeprom(&dev); break; - case 'M': dump_regs(&dev); break; - case 'C': copy_from_eeprom(&dev); break; - case 'P': print_macaddr(&dev); break; - unknown_cmd: - default: puts("ERROR: Unknown command!\n\n"); - case '?': - case 'H': usage(); break; - case 'Q': return 0; - } - } -} diff --git a/include/configs/tbs2910.h b/include/configs/tbs2910.h index 7376b91f55..17de122852 100644 --- a/include/configs/tbs2910.h +++ b/include/configs/tbs2910.h @@ -76,6 +76,7 @@ #define CONFIG_BOARD_SIZE_LIMIT 392192 /* (CONFIG_ENV_OFFSET - 1024) */ #define CONFIG_EXTRA_ENV_SETTINGS \ + BOOTENV \ "bootargs_mmc1=console=ttymxc0,115200 di0_primary console=tty1\0" \ "bootargs_mmc2=video=mxcfb0:dev=hdmi,1920x1080M@60 " \ "video=mxcfb1:off video=mxcfb2:off fbmem=28M\0" \ @@ -92,6 +93,13 @@ "bootm 0x10800000 0x10d00000\0" \ "console=ttymxc0\0" \ "fan=gpio set 92\0" \ + "fdt_addr=0x13000000\0" \ + "fdt_addr_r=0x13000000\0" \ + "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \ + "kernel_addr_r=0x10008000\0" \ + "pxefile_addr_r=0x10008000\0" \ + "ramdisk_addr_r=0x18000000\0" \ + "scriptaddr=0x14000000\0" \ "set_con_serial=setenv stdout serial; " \ "setenv stderr serial\0" \ "set_con_hdmi=setenv stdout serial,vga; " \ @@ -100,12 +108,14 @@ "stdin=serial,usbkbd\0" \ "stdout=serial,vga\0" -#define CONFIG_BOOTCOMMAND \ - "mmc rescan; " \ - "if run bootcmd_up1; then " \ - "run bootcmd_up2; " \ - "else " \ - "run bootcmd_mmc; " \ - "fi" +/* Enable distro boot */ +#define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 0) \ + func(MMC, mmc, 1) \ + func(MMC, mmc, 2) \ + func(SATA, sata, 0) \ + func(USB, usb, 0) + +#include <config_distro_bootcmd.h> #endif /* __TBS2910_CONFIG_H * */ diff --git a/include/hash.h b/include/hash.h index 835962e7f6..97bb3ed5d9 100644 --- a/include/hash.h +++ b/include/hash.h @@ -12,7 +12,11 @@ struct cmd_tbl; * Maximum digest size for all algorithms we support. Having this value * avoids a malloc() or C99 local declaration in common/cmd_hash.c. */ +#if defined(CONFIG_SHA384) || defined(CONFIG_SHA512) +#define HASH_MAX_DIGEST_SIZE 64 +#else #define HASH_MAX_DIGEST_SIZE 32 +#endif enum { HASH_FLAG_VERIFY = 1 << 0, /* Enable verify mode */ diff --git a/include/image.h b/include/image.h index ad81dad444..ebd581a594 100644 --- a/include/image.h +++ b/include/image.h @@ -32,8 +32,12 @@ struct fdt_region; #define CONFIG_FIT_VERBOSE 1 /* enable fit_format_{error,warning}() */ #define CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT 1 #define CONFIG_FIT_ENABLE_SHA256_SUPPORT +#define CONFIG_FIT_ENABLE_SHA384_SUPPORT +#define CONFIG_FIT_ENABLE_SHA512_SUPPORT #define CONFIG_SHA1 #define CONFIG_SHA256 +#define CONFIG_SHA384 +#define CONFIG_SHA512 #define IMAGE_ENABLE_IGNORE 0 #define IMAGE_INDENT_STRING "" @@ -92,6 +96,20 @@ struct fdt_region; #define IMAGE_ENABLE_SHA256 0 #endif +#if defined(CONFIG_FIT_ENABLE_SHA384_SUPPORT) || \ + defined(CONFIG_SPL_SHA384_SUPPORT) +#define IMAGE_ENABLE_SHA384 1 +#else +#define IMAGE_ENABLE_SHA384 0 +#endif + +#if defined(CONFIG_FIT_ENABLE_SHA512_SUPPORT) || \ + defined(CONFIG_SPL_SHA512_SUPPORT) +#define IMAGE_ENABLE_SHA512 1 +#else +#define IMAGE_ENABLE_SHA512 0 +#endif + #endif /* IMAGE_ENABLE_FIT */ #ifdef CONFIG_SYS_BOOT_GET_CMDLINE diff --git a/include/net.h b/include/net.h index 00a8ec0c78..1bf9867f8c 100644 --- a/include/net.h +++ b/include/net.h @@ -897,9 +897,6 @@ int is_serverip_in_cmd(void); */ int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len); -/* get a random source port */ -unsigned int random_port(void); - /** * update_tftp - Update firmware over TFTP (via DFU) * diff --git a/include/phy.h b/include/phy.h index b5de14cbfc..fedd146091 100644 --- a/include/phy.h +++ b/include/phy.h @@ -170,6 +170,13 @@ struct fixed_link { int asym_pause; }; +/** + * phy_read - Convenience function for reading a given PHY register + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to read + * @return: value for success or negative errno for failure + */ static inline int phy_read(struct phy_device *phydev, int devad, int regnum) { struct mii_dev *bus = phydev->bus; @@ -182,6 +189,14 @@ static inline int phy_read(struct phy_device *phydev, int devad, int regnum) return bus->read(bus, phydev->addr, devad, regnum); } +/** + * phy_write - Convenience function for writing a given PHY register + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to write + * @val: value to write to @regnum + * @return: 0 for success or negative errno for failure + */ static inline int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val) { @@ -195,6 +210,13 @@ static inline int phy_write(struct phy_device *phydev, int devad, int regnum, return bus->write(bus, phydev->addr, devad, regnum, val); } +/** + * phy_mmd_start_indirect - Convenience function for writing MMD registers + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to write + * @return: None + */ static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum) { @@ -209,6 +231,14 @@ static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad, (devad | MII_MMD_CTRL_NOINCR)); } +/** + * phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * @return: Value for success or negative errno for failure + */ static inline int phy_read_mmd(struct phy_device *phydev, int devad, int regnum) { @@ -233,6 +263,15 @@ static inline int phy_read_mmd(struct phy_device *phydev, int devad, return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA); } +/** + * phy_write_mmd - Convenience function for writing a register + * on an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * @val: value to write to @regnum + * @return: 0 for success or negative errno for failure + */ static inline int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val) { @@ -257,6 +296,60 @@ static inline int phy_write_mmd(struct phy_device *phydev, int devad, return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val); } +/** + * phy_set_bits_mmd - Convenience function for setting bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to set + * @return: 0 for success or negative errno for failure + */ +static inline int phy_set_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + int value, ret; + + value = phy_read_mmd(phydev, devad, regnum); + if (value < 0) + return value; + + value |= val; + + ret = phy_write_mmd(phydev, devad, regnum, value); + if (ret < 0) + return ret; + + return 0; +} + +/** + * phy_clear_bits_mmd - Convenience function for clearing bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to clear + * @return: 0 for success or negative errno for failure + */ +static inline int phy_clear_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + int value, ret; + + value = phy_read_mmd(phydev, devad, regnum); + if (value < 0) + return value; + + value &= ~val; + + ret = phy_write_mmd(phydev, devad, regnum, value); + if (ret < 0) + return ret; + + return 0; +} + #ifdef CONFIG_PHYLIB_10G extern struct phy_driver gen10g_driver; @@ -275,26 +368,23 @@ static inline int is_10g_interface(phy_interface_t interface) /** * phy_init() - Initializes the PHY drivers - * * This function registers all available PHY drivers * - * @return 0 if OK, -ve on error + * @return: 0 if OK, -ve on error */ int phy_init(void); /** * phy_reset() - Resets the specified PHY - * * Issues a reset of the PHY and waits for it to complete * * @phydev: PHY to reset - * @return 0 if OK, -ve on error + * @return: 0 if OK, -ve on error */ int phy_reset(struct phy_device *phydev); /** * phy_find_by_mask() - Searches for a PHY on the specified MDIO bus - * * The function checks the PHY addresses flagged in phy_mask and returns a * phy_device pointer if it detects a PHY. * This function should only be called if just one PHY is expected to be present @@ -304,7 +394,7 @@ int phy_reset(struct phy_device *phydev); * @bus: MII/MDIO bus to scan * @phy_mask: bitmap of PYH addresses to scan * @interface: type of MAC-PHY interface - * @return pointer to phy_device if a PHY is found, or NULL otherwise + * @return: pointer to phy_device if a PHY is found, or NULL otherwise */ struct phy_device *phy_find_by_mask(struct mii_dev *bus, unsigned phy_mask, phy_interface_t interface); @@ -320,7 +410,6 @@ void phy_connect_dev(struct phy_device *phydev, struct udevice *dev); /** * phy_connect() - Creates a PHY device for the Ethernet interface - * * Creates a PHY device for the PHY at the given address, if one doesn't exist * already, and associates it with the Ethernet device. * The function may be called with addr <= 0, in this case addr value is ignored @@ -332,7 +421,7 @@ void phy_connect_dev(struct phy_device *phydev, struct udevice *dev); * @addr: PHY address on MDIO bus * @dev: Ethernet device to associate to the PHY * @interface: type of MAC-PHY interface - * @return pointer to phy_device if a PHY is found, or NULL otherwise + * @return: pointer to phy_device if a PHY is found, or NULL otherwise */ struct phy_device *phy_connect(struct mii_dev *bus, int addr, struct udevice *dev, @@ -356,7 +445,6 @@ void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev); /** * phy_connect() - Creates a PHY device for the Ethernet interface - * * Creates a PHY device for the PHY at the given address, if one doesn't exist * already, and associates it with the Ethernet device. * The function may be called with addr <= 0, in this case addr value is ignored @@ -368,7 +456,7 @@ void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev); * @addr: PHY address on MDIO bus * @dev: Ethernet device to associate to the PHY * @interface: type of MAC-PHY interface - * @return pointer to phy_device if a PHY is found, or NULL otherwise + * @return: pointer to phy_device if a PHY is found, or NULL otherwise */ struct phy_device *phy_connect(struct mii_dev *bus, int addr, struct eth_device *dev, @@ -428,7 +516,7 @@ int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id); * phy_get_interface_by_name() - Look up a PHY interface name * * @str: PHY interface name, e.g. "mii" - * @return PHY_INTERFACE_MODE_... value, or -1 if not found + * @return: PHY_INTERFACE_MODE_... value, or -1 if not found */ int phy_get_interface_by_name(const char *str); @@ -436,6 +524,7 @@ int phy_get_interface_by_name(const char *str); * phy_interface_is_rgmii - Convenience function for testing if a PHY interface * is RGMII (all variants) * @phydev: the phy_device struct + * @return: true if MII bus is RGMII or false if it is not */ static inline bool phy_interface_is_rgmii(struct phy_device *phydev) { @@ -447,6 +536,7 @@ static inline bool phy_interface_is_rgmii(struct phy_device *phydev) * phy_interface_is_sgmii - Convenience function for testing if a PHY interface * is SGMII (all variants) * @phydev: the phy_device struct + * @return: true if MII bus is SGMII or false if it is not */ static inline bool phy_interface_is_sgmii(struct phy_device *phydev) { diff --git a/include/u-boot/rsa-checksum.h b/include/u-boot/rsa-checksum.h index 02b814d34e..54e6a73744 100644 --- a/include/u-boot/rsa-checksum.h +++ b/include/u-boot/rsa-checksum.h @@ -10,6 +10,7 @@ #include <image.h> #include <u-boot/sha1.h> #include <u-boot/sha256.h> +#include <u-boot/sha512.h> /** * hash_calculate() - Calculate hash over the data diff --git a/include/u-boot/sha512.h b/include/u-boot/sha512.h new file mode 100644 index 0000000000..516729d775 --- /dev/null +++ b/include/u-boot/sha512.h @@ -0,0 +1,38 @@ +#ifndef _SHA512_H +#define _SHA512_H + +#define SHA384_SUM_LEN 48 +#define SHA384_DER_LEN 19 +#define SHA512_SUM_LEN 64 +#define SHA512_DER_LEN 19 +#define SHA512_BLOCK_SIZE 128 + +#define CHUNKSZ_SHA384 (16 * 1024) +#define CHUNKSZ_SHA512 (16 * 1024) + +typedef struct { + uint64_t state[SHA512_SUM_LEN / 8]; + uint64_t count[2]; + uint8_t buf[SHA512_BLOCK_SIZE]; +} sha512_context; + +extern const uint8_t sha512_der_prefix[]; + +void sha512_starts(sha512_context * ctx); +void sha512_update(sha512_context *ctx, const uint8_t *input, uint32_t length); +void sha512_finish(sha512_context * ctx, uint8_t digest[SHA512_SUM_LEN]); + +void sha512_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz); + +extern const uint8_t sha384_der_prefix[]; + +void sha384_starts(sha512_context * ctx); +void sha384_update(sha512_context *ctx, const uint8_t *input, uint32_t length); +void sha384_finish(sha512_context * ctx, uint8_t digest[SHA384_SUM_LEN]); + +void sha384_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz); + + +#endif /* _SHA512_H */ diff --git a/lib/Kconfig b/lib/Kconfig index af5c38afd9..fc7d68487b 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -345,6 +345,29 @@ config SHA256 The SHA256 algorithm produces a 256-bit (32-byte) hash value (digest). +config SHA512_ALGO + bool "Enable SHA512 algorithm" + help + This option enables support of internal SHA512 algorithm. + +config SHA512 + bool "Enable SHA512 support" + depends on SHA512_ALGO + help + This option enables support of hashing using SHA512 algorithm. + The hash is calculated in software. + The SHA512 algorithm produces a 512-bit (64-byte) hash value + (digest). + +config SHA384 + bool "Enable SHA384 support" + depends on SHA512_ALGO + help + This option enables support of hashing using SHA384 algorithm. + The hash is calculated in software. + The SHA384 algorithm produces a 384-bit (48-byte) hash value + (digest). + config SHA_HW_ACCEL bool "Enable hashing using hardware" help diff --git a/lib/Makefile b/lib/Makefile index dc5761966c..1dc06c57d5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_$(SPL_)MD5) += md5.o obj-$(CONFIG_$(SPL_)RSA) += rsa/ obj-$(CONFIG_SHA1) += sha1.o obj-$(CONFIG_SHA256) += sha256.o +obj-$(CONFIG_SHA512_ALGO) += sha512.o obj-$(CONFIG_$(SPL_)ZLIB) += zlib/ obj-$(CONFIG_$(SPL_)ZSTD) += zstd/ diff --git a/lib/sha512.c b/lib/sha512.c new file mode 100644 index 0000000000..f1e2acf0fb --- /dev/null +++ b/lib/sha512.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * FIPS-180-2 compliant SHA-512 and SHA-384 implementation + * + * SHA-512 code by Jean-Luc Cooke <jlcooke@certainkey.com> + * + * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> + * Copyright (c) 2003 Kyle McMartin <kyle@debian.org> + * Copyright (c) 2020 Reuben Dowle <reuben.dowle@4rf.com> + */ + +#ifndef USE_HOSTCC +#include <common.h> +#include <linux/string.h> +#else +#include <string.h> +#endif /* USE_HOSTCC */ +#include <watchdog.h> +#include <u-boot/sha512.h> + +const uint8_t sha384_der_prefix[SHA384_DER_LEN] = { + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, + 0x00, 0x04, 0x30 +}; + +const uint8_t sha512_der_prefix[SHA512_DER_LEN] = { + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40 +}; + +#define SHA384_H0 0xcbbb9d5dc1059ed8ULL +#define SHA384_H1 0x629a292a367cd507ULL +#define SHA384_H2 0x9159015a3070dd17ULL +#define SHA384_H3 0x152fecd8f70e5939ULL +#define SHA384_H4 0x67332667ffc00b31ULL +#define SHA384_H5 0x8eb44a8768581511ULL +#define SHA384_H6 0xdb0c2e0d64f98fa7ULL +#define SHA384_H7 0x47b5481dbefa4fa4ULL + +#define SHA512_H0 0x6a09e667f3bcc908ULL +#define SHA512_H1 0xbb67ae8584caa73bULL +#define SHA512_H2 0x3c6ef372fe94f82bULL +#define SHA512_H3 0xa54ff53a5f1d36f1ULL +#define SHA512_H4 0x510e527fade682d1ULL +#define SHA512_H5 0x9b05688c2b3e6c1fULL +#define SHA512_H6 0x1f83d9abfb41bd6bULL +#define SHA512_H7 0x5be0cd19137e2179ULL + +static inline uint64_t Ch(uint64_t x, uint64_t y, uint64_t z) +{ + return z ^ (x & (y ^ z)); +} + +static inline uint64_t Maj(uint64_t x, uint64_t y, uint64_t z) +{ + return (x & y) | (z & (x | y)); +} + +static const uint64_t sha512_K[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +static inline uint64_t ror64(uint64_t word, unsigned int shift) +{ + return (word >> (shift & 63)) | (word << ((-shift) & 63)); +} + +#define e0(x) (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39)) +#define e1(x) (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41)) +#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7)) +#define s1(x) (ror64(x,19) ^ ror64(x,61) ^ (x >> 6)) + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) { \ + (n) = ( (unsigned long long) (b)[(i) ] << 56 ) \ + | ( (unsigned long long) (b)[(i) + 1] << 48 ) \ + | ( (unsigned long long) (b)[(i) + 2] << 40 ) \ + | ( (unsigned long long) (b)[(i) + 3] << 32 ) \ + | ( (unsigned long long) (b)[(i) + 4] << 24 ) \ + | ( (unsigned long long) (b)[(i) + 5] << 16 ) \ + | ( (unsigned long long) (b)[(i) + 6] << 8 ) \ + | ( (unsigned long long) (b)[(i) + 7] ); \ +} +#endif +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) { \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif + +static inline void LOAD_OP(int I, uint64_t *W, const uint8_t *input) +{ + GET_UINT64_BE(W[I], input, I*8); +} + +static inline void BLEND_OP(int I, uint64_t *W) +{ + W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]); +} + +static void +sha512_transform(uint64_t *state, const uint8_t *input) +{ + uint64_t a, b, c, d, e, f, g, h, t1, t2; + + int i; + uint64_t W[16]; + + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + + /* now iterate */ + for (i=0; i<80; i+=8) { + if (!(i & 8)) { + int j; + + if (i < 16) { + /* load the input */ + for (j = 0; j < 16; j++) + LOAD_OP(i + j, W, input); + } else { + for (j = 0; j < 16; j++) { + BLEND_OP(i + j, W); + } + } + } + + t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[(i & 15)]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + } + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + + /* erase our data */ + a = b = c = d = e = f = g = h = t1 = t2 = 0; +} + +static void sha512_block_fn(sha512_context *sst, const uint8_t *src, + int blocks) +{ + while (blocks--) { + sha512_transform(sst->state, src); + src += SHA512_BLOCK_SIZE; + } +} + +static void sha512_base_do_update(sha512_context *sctx, + const uint8_t *data, + unsigned int len) +{ + unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE; + + sctx->count[0] += len; + if (sctx->count[0] < len) + sctx->count[1]++; + + if (unlikely((partial + len) >= SHA512_BLOCK_SIZE)) { + int blocks; + + if (partial) { + int p = SHA512_BLOCK_SIZE - partial; + + memcpy(sctx->buf + partial, data, p); + data += p; + len -= p; + + sha512_block_fn(sctx, sctx->buf, 1); + } + + blocks = len / SHA512_BLOCK_SIZE; + len %= SHA512_BLOCK_SIZE; + + if (blocks) { + sha512_block_fn(sctx, data, blocks); + data += blocks * SHA512_BLOCK_SIZE; + } + partial = 0; + } + if (len) + memcpy(sctx->buf + partial, data, len); +} + +static void sha512_base_do_finalize(sha512_context *sctx) +{ + const int bit_offset = SHA512_BLOCK_SIZE - sizeof(uint64_t[2]); + uint64_t *bits = (uint64_t *)(sctx->buf + bit_offset); + unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE; + + sctx->buf[partial++] = 0x80; + if (partial > bit_offset) { + memset(sctx->buf + partial, 0x0, SHA512_BLOCK_SIZE - partial); + partial = 0; + + sha512_block_fn(sctx, sctx->buf, 1); + } + + memset(sctx->buf + partial, 0x0, bit_offset - partial); + bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61); + bits[1] = cpu_to_be64(sctx->count[0] << 3); + sha512_block_fn(sctx, sctx->buf, 1); +} + +#if defined(CONFIG_SHA384) +void sha384_starts(sha512_context * ctx) +{ + ctx->state[0] = SHA384_H0; + ctx->state[1] = SHA384_H1; + ctx->state[2] = SHA384_H2; + ctx->state[3] = SHA384_H3; + ctx->state[4] = SHA384_H4; + ctx->state[5] = SHA384_H5; + ctx->state[6] = SHA384_H6; + ctx->state[7] = SHA384_H7; + ctx->count[0] = ctx->count[1] = 0; +} + +void sha384_update(sha512_context *ctx, const uint8_t *input, uint32_t length) +{ + sha512_base_do_update(ctx, input, length); +} + +void sha384_finish(sha512_context * ctx, uint8_t digest[SHA384_SUM_LEN]) +{ + int i; + + sha512_base_do_finalize(ctx); + for(i=0; i<SHA384_SUM_LEN / sizeof(uint64_t); i++) + PUT_UINT64_BE(ctx->state[i], digest, i * 8); +} + +/* + * Output = SHA-512( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha384_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + sha512_context ctx; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + const unsigned char *end; + unsigned char *curr; + int chunk; +#endif + + sha384_starts(&ctx); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + curr = (unsigned char *)input; + end = input + ilen; + while (curr < end) { + chunk = end - curr; + if (chunk > chunk_sz) + chunk = chunk_sz; + sha384_update(&ctx, curr, chunk); + curr += chunk; + WATCHDOG_RESET(); + } +#else + sha384_update(&ctx, input, ilen); +#endif + + sha384_finish(&ctx, output); +} + +#endif + +#if defined(CONFIG_SHA512) +void sha512_starts(sha512_context * ctx) +{ + ctx->state[0] = SHA512_H0; + ctx->state[1] = SHA512_H1; + ctx->state[2] = SHA512_H2; + ctx->state[3] = SHA512_H3; + ctx->state[4] = SHA512_H4; + ctx->state[5] = SHA512_H5; + ctx->state[6] = SHA512_H6; + ctx->state[7] = SHA512_H7; + ctx->count[0] = ctx->count[1] = 0; +} + +void sha512_update(sha512_context *ctx, const uint8_t *input, uint32_t length) +{ + sha512_base_do_update(ctx, input, length); +} + +void sha512_finish(sha512_context * ctx, uint8_t digest[SHA512_SUM_LEN]) +{ + int i; + + sha512_base_do_finalize(ctx); + for(i=0; i<SHA512_SUM_LEN / sizeof(uint64_t); i++) + PUT_UINT64_BE(ctx->state[i], digest, i * 8); +} + +/* + * Output = SHA-512( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha512_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + sha512_context ctx; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + const unsigned char *end; + unsigned char *curr; + int chunk; +#endif + + sha512_starts(&ctx); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + curr = (unsigned char *)input; + end = input + ilen; + while (curr < end) { + chunk = end - curr; + if (chunk > chunk_sz) + chunk = chunk_sz; + sha512_update(&ctx, curr, chunk); + curr += chunk; + WATCHDOG_RESET(); + } +#else + sha512_update(&ctx, input, ilen); +#endif + + sha512_finish(&ctx, output); +} +#endif @@ -36,6 +36,16 @@ char *net_dns_env_var; /* The envvar to store the answer in */ static int dns_our_port; +/* + * make port a little random (1024-17407) + * This keeps the math somewhat trivial to compute, and seems to work with + * all supported protocols/clients/servers + */ +static unsigned int random_port(void) +{ + return 1024 + (get_timer(0) % 0x4000); +} + static void dns_send(void) { struct header *header; @@ -456,6 +456,7 @@ restart: net_dev_exists = 1; net_boot_file_size = 0; switch (protocol) { +#ifdef CONFIG_CMD_TFTPBOOT case TFTPGET: #ifdef CONFIG_CMD_TFTPPUT case TFTPPUT: @@ -463,6 +464,7 @@ restart: /* always use ARP to get server ethernet address */ tftp_start(protocol); break; +#endif #ifdef CONFIG_CMD_TFTPSRV case TFTPSRV: tftp_start_server(); @@ -480,13 +482,13 @@ restart: dhcp_request(); /* Basically same as BOOTP */ break; #endif - +#if defined(CONFIG_CMD_BOOTP) case BOOTP: bootp_reset(); net_ip.s_addr = 0; bootp_request(); break; - +#endif #if defined(CONFIG_CMD_RARP) case RARP: rarp_try = 0; @@ -1562,20 +1564,6 @@ int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len) return 1; } -#if defined(CONFIG_CMD_NFS) || \ - defined(CONFIG_CMD_SNTP) || \ - defined(CONFIG_CMD_DNS) -/* - * make port a little random (1024-17407) - * This keeps the math somewhat trivial to compute, and seems to work with - * all supported protocols/clients/servers - */ -unsigned int random_port(void) -{ - return 1024 + (get_timer(0) % 0x4000); -} -#endif - void ip_to_string(struct in_addr x, char *s) { x.s_addr = ntohl(x.s_addr); diff --git a/net/tftp.c b/net/tftp.c index 180140e495..c05b7b5532 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -70,6 +70,7 @@ enum { TFTP_ERR_UNEXPECTED_OPCODE = 4, TFTP_ERR_UNKNOWN_TRANSFER_ID = 5, TFTP_ERR_FILE_ALREADY_EXISTS = 6, + TFTP_ERR_OPTION_NEGOTIATION = 8, }; static struct in_addr tftp_remote_ip; @@ -113,6 +114,7 @@ static int tftp_put_final_block_sent; #define STATE_OACK 5 #define STATE_RECV_WRQ 6 #define STATE_SEND_WRQ 7 +#define STATE_INVALID_OPTION 8 /* default TFTP block size */ #define TFTP_BLOCK_SIZE 512 @@ -233,9 +235,11 @@ static void tftp_timeout_handler(void); static void show_block_marker(void) { + ulong pos; + #ifdef CONFIG_TFTP_TSIZE if (tftp_tsize) { - ulong pos = tftp_cur_block * tftp_block_size + + pos = tftp_cur_block * tftp_block_size + tftp_block_wrap_offset; if (pos > tftp_tsize) pos = tftp_tsize; @@ -247,9 +251,11 @@ static void show_block_marker(void) } else #endif { - if (((tftp_cur_block - 1) % 10) == 0) + pos = (tftp_cur_block - 1) + + (tftp_block_wrap * TFTP_SEQUENCE_SIZE); + if ((pos % 10) == 0) putc('#'); - else if ((tftp_cur_block % (10 * HASHES_PER_LINE)) == 0) + else if (((pos + 1) % (10 * HASHES_PER_LINE)) == 0) puts("\n\t "); } } @@ -282,9 +288,8 @@ static void update_block_number(void) tftp_block_wrap++; tftp_block_wrap_offset += tftp_block_size * TFTP_SEQUENCE_SIZE; timeout_count = 0; /* we've done well, reset the timeout */ - } else { - show_block_marker(); } + show_block_marker(); } /* The TFTP get or put is complete */ @@ -315,6 +320,7 @@ static void tftp_send(void) uchar *xp; int len = 0; ushort *s; + bool err_pkt = false; /* * We will always be sending some sort of packet, so @@ -385,6 +391,7 @@ static void tftp_send(void) strcpy((char *)pkt, "File too large"); pkt += 14 /*strlen("File too large")*/ + 1; len = pkt - xp; + err_pkt = true; break; case STATE_BAD_MAGIC: @@ -396,11 +403,28 @@ static void tftp_send(void) strcpy((char *)pkt, "File has bad magic"); pkt += 18 /*strlen("File has bad magic")*/ + 1; len = pkt - xp; + err_pkt = true; + break; + + case STATE_INVALID_OPTION: + xp = pkt; + s = (ushort *)pkt; + *s++ = htons(TFTP_ERROR); + *s++ = htons(TFTP_ERR_OPTION_NEGOTIATION); + pkt = (uchar *)s; + strcpy((char *)pkt, "Option Negotiation Failed"); + /* strlen("Option Negotiation Failed") + NULL*/ + pkt += 25 + 1; + len = pkt - xp; + err_pkt = true; break; } net_send_udp_packet(net_server_ethaddr, tftp_remote_ip, tftp_remote_port, tftp_our_port, len); + + if (err_pkt) + net_set_state(NETLOOP_FAIL); } #ifdef CONFIG_CMD_TFTPPUT @@ -421,6 +445,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, __be16 proto; __be16 *s; int i; + u16 timeout_val_rcvd; if (dest != tftp_our_port) { return; @@ -477,8 +502,14 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, #endif case TFTP_OACK: - debug("Got OACK: %s %s\n", - pkt, pkt + strlen((char *)pkt) + 1); + debug("Got OACK: "); + for (i = 0; i < len; i++) { + if (pkt[i] == '\0') + debug(" "); + else + debug("%c", pkt[i]); + } + debug("\n"); tftp_state = STATE_OACK; tftp_remote_port = src; /* @@ -487,15 +518,32 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, * something like "len-8" may give a *huge* number */ for (i = 0; i+8 < len; i++) { - if (strcmp((char *)pkt + i, "blksize") == 0) { + if (strcasecmp((char *)pkt + i, "blksize") == 0) { tftp_block_size = (unsigned short) simple_strtoul((char *)pkt + i + 8, NULL, 10); - debug("Blocksize ack: %s, %d\n", + debug("Blocksize oack: %s, %d\n", (char *)pkt + i + 8, tftp_block_size); + if (tftp_block_size > tftp_block_size_option) { + printf("Invalid blk size(=%d)\n", + tftp_block_size); + tftp_state = STATE_INVALID_OPTION; + } + } + if (strcasecmp((char *)pkt + i, "timeout") == 0) { + timeout_val_rcvd = (unsigned short) + simple_strtoul((char *)pkt + i + 8, + NULL, 10); + debug("Timeout oack: %s, %d\n", + (char *)pkt + i + 8, timeout_val_rcvd); + if (timeout_val_rcvd != (timeout_ms / 1000)) { + printf("Invalid timeout val(=%d s)\n", + timeout_val_rcvd); + tftp_state = STATE_INVALID_OPTION; + } } #ifdef CONFIG_TFTP_TSIZE - if (strcmp((char *)pkt+i, "tsize") == 0) { + if (strcasecmp((char *)pkt + i, "tsize") == 0) { tftp_tsize = simple_strtoul((char *)pkt + i + 6, NULL, 10); debug("size = %s, %d\n", @@ -504,7 +552,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, #endif } #ifdef CONFIG_CMD_TFTPPUT - if (tftp_put_active) { + if (tftp_put_active && tftp_state == STATE_OACK) { /* Get ready to send the first block */ tftp_state = STATE_DATA; tftp_cur_block++; @@ -518,10 +566,8 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, len -= 2; tftp_cur_block = ntohs(*(__be16 *)pkt); - update_block_number(); - if (tftp_state == STATE_SEND_RRQ) - debug("Server did not acknowledge timeout option!\n"); + debug("Server did not acknowledge any options!\n"); if (tftp_state == STATE_SEND_RRQ || tftp_state == STATE_OACK || tftp_state == STATE_RECV_WRQ) { @@ -545,6 +591,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, break; } + update_block_number(); tftp_prev_block = tftp_cur_block; timeout_count_max = tftp_timeout_count_max; net_set_timeout_handler(timeout_ms, tftp_timeout_handler); diff --git a/tools/Makefile b/tools/Makefile index 879c3fd4a7..51123fd929 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -107,6 +107,7 @@ dumpimage-mkimage-objs := aisimage.o \ lib/crc16.o \ lib/sha1.o \ lib/sha256.o \ + lib/sha512.o \ common/hash.o \ ublimage.o \ zynqimage.o \ @@ -225,6 +226,7 @@ HOSTCFLAGS_crc8.o := -pedantic HOSTCFLAGS_md5.o := -pedantic HOSTCFLAGS_sha1.o := -pedantic HOSTCFLAGS_sha256.o := -pedantic +HOSTCFLAGS_sha512.o := -pedantic -DCONFIG_SHA512 -DCONFIG_SHA384 quiet_cmd_wrap = WRAP $@ cmd_wrap = echo "\#include <../$(patsubst $(obj)/%,%,$@)>" >$@ |