diff options
author | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2012-09-30 23:49:17 +0200 |
---|---|---|
committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2012-09-30 23:49:17 +0200 |
commit | 1c27059a2f7158a9c9a8778535b030935d75179d (patch) | |
tree | bf577d5c9f0da21c5d57feed1091214e54c39dec /common | |
parent | 8f0732ac3dc3bdbbcada313dc4b4b38d5d2c376a (diff) | |
parent | 4668a086bb0a769b741e3a4ffab85f1c41c7cdb8 (diff) | |
download | u-boot-imx-1c27059a2f7158a9c9a8778535b030935d75179d.zip u-boot-imx-1c27059a2f7158a9c9a8778535b030935d75179d.tar.gz u-boot-imx-1c27059a2f7158a9c9a8778535b030935d75179d.tar.bz2 |
Merge remote-tracking branch 'u-boot/master'
Diffstat (limited to 'common')
38 files changed, 1874 insertions, 1041 deletions
diff --git a/common/Makefile b/common/Makefile index 3d62775..125b2be 100644 --- a/common/Makefile +++ b/common/Makefile @@ -34,6 +34,7 @@ COBJS-$(CONFIG_SYS_HUSH_PARSER) += hush.o COBJS-y += s_record.o COBJS-$(CONFIG_SERIAL_MULTI) += serial.o COBJS-y += xyzModem.o +COBJS-y += cmd_disk.o # core command COBJS-y += cmd_boot.o @@ -86,7 +87,13 @@ COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += cmd_eeprom.o COBJS-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o COBJS-$(CONFIG_CMD_ELF) += cmd_elf.o COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o +COBJS-$(CONFIG_CMD_EXT4) += cmd_ext4.o COBJS-$(CONFIG_CMD_EXT2) += cmd_ext2.o +ifdef CONFIG_CMD_EXT4 +COBJS-y += cmd_ext_common.o +else +COBJS-$(CONFIG_CMD_EXT2) += cmd_ext_common.o +endif COBJS-$(CONFIG_CMD_FAT) += cmd_fat.o COBJS-$(CONFIG_CMD_FDC)$(CONFIG_CMD_FDOS) += cmd_fdc.o COBJS-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.o @@ -129,6 +136,7 @@ COBJS-$(CONFIG_CMD_NAND) += cmd_nand.o COBJS-$(CONFIG_CMD_NET) += cmd_net.o COBJS-$(CONFIG_CMD_ONENAND) += cmd_onenand.o COBJS-$(CONFIG_CMD_OTP) += cmd_otp.o +COBJS-$(CONFIG_CMD_PART) += cmd_part.o ifdef CONFIG_PCI COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o endif @@ -162,6 +170,7 @@ endif COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o COBJS-$(CONFIG_YAFFS2) += cmd_yaffs2.o COBJS-$(CONFIG_CMD_SPL) += cmd_spl.o +COBJS-$(CONFIG_CMD_ZIP) += cmd_zip.o COBJS-$(CONFIG_CMD_ZFS) += cmd_zfs.o # others @@ -184,6 +193,7 @@ COBJS-$(CONFIG_MENU) += menu.o COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o COBJS-$(CONFIG_UPDATE_TFTP) += update.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o +COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o endif ifdef CONFIG_SPL_BUILD diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index 42f08fd..23bd8a5 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -216,15 +216,15 @@ int do_bdinfo(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) print_num("flashstart ", bd->bi_flashstart); print_num("CONFIG_SYS_MONITOR_BASE ", CONFIG_SYS_MONITOR_BASE); print_num("CONFIG_ENV_ADDR ", CONFIG_ENV_ADDR); - printf("CONFIG_SYS_RELOC_MONITOR_BASE = 0x%lx (%d)\n", CONFIG_SYS_RELOC_MONITOR_BASE, + printf("CONFIG_SYS_RELOC_MONITOR_BASE = 0x%x (%d)\n", CONFIG_SYS_RELOC_MONITOR_BASE, CONFIG_SYS_MONITOR_LEN); - printf("CONFIG_SYS_MALLOC_BASE = 0x%lx (%d)\n", CONFIG_SYS_MALLOC_BASE, + printf("CONFIG_SYS_MALLOC_BASE = 0x%x (%d)\n", CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN); - printf("CONFIG_SYS_INIT_SP_OFFSET = 0x%lx (%d)\n", CONFIG_SYS_INIT_SP_OFFSET, + printf("CONFIG_SYS_INIT_SP_OFFSET = 0x%x (%d)\n", CONFIG_SYS_INIT_SP_OFFSET, CONFIG_SYS_STACK_SIZE); - printf("CONFIG_SYS_PROM_OFFSET = 0x%lx (%d)\n", CONFIG_SYS_PROM_OFFSET, + printf("CONFIG_SYS_PROM_OFFSET = 0x%x (%d)\n", CONFIG_SYS_PROM_OFFSET, CONFIG_SYS_PROM_SIZE); - printf("CONFIG_SYS_GBL_DATA_OFFSET = 0x%lx (%d)\n", CONFIG_SYS_GBL_DATA_OFFSET, + printf("CONFIG_SYS_GBL_DATA_OFFSET = 0x%x (%d)\n", CONFIG_SYS_GBL_DATA_OFFSET, GENERATED_GBL_DATA_SIZE); #if defined(CONFIG_CMD_NET) diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 45e726a..83fa5d7 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -564,6 +564,13 @@ int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, break; case BOOTM_STATE_OS_GO: disable_interrupts(); +#ifdef CONFIG_NETCONSOLE + /* + * Stop the ethernet stack if NetConsole could have + * left it up + */ + eth_halt(); +#endif arch_preboot_os(); boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images); break; @@ -622,6 +629,11 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ iflag = disable_interrupts(); +#ifdef CONFIG_NETCONSOLE + /* Stop the ethernet stack if NetConsole could have left it up */ + eth_halt(); +#endif + #if defined(CONFIG_CMD_USB) /* * turn off USB to prevent the host controller from writing to the @@ -1599,6 +1611,11 @@ static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ disable_interrupts(); +#ifdef CONFIG_NETCONSOLE + /* Stop the ethernet stack if NetConsole could have left it up */ + eth_halt(); +#endif + #if defined(CONFIG_CMD_USB) /* * turn off USB to prevent the host controller from writing to the diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c new file mode 100644 index 0000000..62fb890 --- /dev/null +++ b/common/cmd_dfu.c @@ -0,0 +1,81 @@ +/* + * cmd_dfu.c -- dfu command + * + * Copyright (C) 2012 Samsung Electronics + * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com> + * Lukasz Majewski <l.majewski@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <malloc.h> +#include <dfu.h> +#include <asm/errno.h> +#include <g_dnl.h> + +static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const char *str_env; + char s[] = "dfu"; + char *env_bkp; + int ret; + + if (argc < 3) + return CMD_RET_USAGE; + + str_env = getenv("dfu_alt_info"); + if (str_env == NULL) { + printf("%s: \"dfu_alt_info\" env variable not defined!\n", + __func__); + return CMD_RET_FAILURE; + } + + env_bkp = strdup(str_env); + ret = dfu_config_entities(env_bkp, argv[1], + (int)simple_strtoul(argv[2], NULL, 10)); + if (ret) + return CMD_RET_FAILURE; + + if (strcmp(argv[3], "list") == 0) { + dfu_show_entities(); + goto done; + } + + board_usb_init(); + g_dnl_register(s); + while (1) { + if (ctrlc()) + goto exit; + + usb_gadget_handle_interrupts(); + } +exit: + g_dnl_unregister(); +done: + dfu_free_entities(); + free(env_bkp); + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, + "Device Firmware Upgrade", + "<interface> <dev> [list]\n" + " - device firmware upgrade on a device <dev>\n" + " attached to interface <interface>\n" + " [list] - list available alt settings" +); diff --git a/common/cmd_disk.c b/common/cmd_disk.c new file mode 100644 index 0000000..ee4e215 --- /dev/null +++ b/common/cmd_disk.c @@ -0,0 +1,144 @@ +/* + * (C) Copyright 2000-2011 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ +#include <common.h> +#include <command.h> +#include <part.h> + +#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \ + defined(CONFIG_USB_STORAGE) +int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, + char *const argv[]) +{ + int dev, part; + ulong addr = CONFIG_SYS_LOAD_ADDR; + ulong cnt; + disk_partition_t info; + image_header_t *hdr; + block_dev_desc_t *dev_desc; + +#if defined(CONFIG_FIT) + const void *fit_hdr = NULL; +#endif + + bootstage_mark(BOOTSTAGE_ID_IDE_START); + if (argc > 3) { + bootstage_error(BOOTSTAGE_ID_IDE_ADDR); + return CMD_RET_USAGE; + } + bootstage_mark(BOOTSTAGE_ID_IDE_ADDR); + + if (argc > 1) + addr = simple_strtoul(argv[1], NULL, 16); + + bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE); + + part = get_device_and_partition(intf, (argc == 3) ? argv[2] : NULL, + &dev_desc, &info, 1); + if (part < 0) { + bootstage_error(BOOTSTAGE_ID_IDE_TYPE); + return 1; + } + + dev = dev_desc->dev; + bootstage_mark(BOOTSTAGE_ID_IDE_TYPE); + + printf("\nLoading from %s device %d, partition %d: " + "Name: %.32s Type: %.32s\n", intf, dev, part, info.name, + info.type); + + debug("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", + info.start, info.size, info.blksz); + + if (dev_desc->block_read(dev, info.start, 1, (ulong *) addr) != 1) { + printf("** Read error on %d:%d\n", dev, part); + bootstage_error(BOOTSTAGE_ID_IDE_PART_READ); + return 1; + } + bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ); + + switch (genimg_get_format((void *) addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *) addr; + + bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT); + + if (!image_check_hcrc(hdr)) { + puts("\n** Bad Header Checksum **\n"); + bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM); + return 1; + } + bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM); + + image_print_contents(hdr); + + cnt = image_get_image_size(hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *) addr; + puts("Fit image detected...\n"); + + cnt = fit_get_size(fit_hdr); + break; +#endif + default: + bootstage_error(BOOTSTAGE_ID_IDE_FORMAT); + puts("** Unknown image type\n"); + return 1; + } + + cnt += info.blksz - 1; + cnt /= info.blksz; + cnt -= 1; + + if (dev_desc->block_read(dev, info.start + 1, cnt, + (ulong *)(addr + info.blksz)) != cnt) { + printf("** Read error on %d:%d\n", dev, part); + bootstage_error(BOOTSTAGE_ID_IDE_READ); + return 1; + } + bootstage_mark(BOOTSTAGE_ID_IDE_READ); + +#if defined(CONFIG_FIT) + /* This cannot be done earlier, + * we need complete FIT image in RAM first */ + if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) { + if (!fit_check_format(fit_hdr)) { + bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ); + puts("** Bad FIT image format\n"); + return 1; + } + bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK); + fit_print_contents(fit_hdr); + } +#endif + + flush_cache(addr, (cnt+1)*info.blksz); + + /* Loading ok, update default load address */ + load_addr = addr; + + return bootm_maybe_autostart(cmdtp, argv[0]); +} +#endif diff --git a/common/cmd_ext2.c b/common/cmd_ext2.c index 79b1e2f..c27d9c7 100644 --- a/common/cmd_ext2.c +++ b/common/cmd_ext2.c @@ -1,4 +1,9 @@ /* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * (C) Copyright 2004 * esd gmbh <www.esd-electronics.com> * Reinhard Arlt <reinhard.arlt@esd-electronics.com> @@ -33,225 +38,35 @@ * Ext2fs support */ #include <common.h> -#include <part.h> -#include <config.h> -#include <command.h> -#include <image.h> -#include <linux/ctype.h> -#include <asm/byteorder.h> -#include <ext2fs.h> -#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) -#include <usb.h> -#endif - -#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION) -#error DOS or EFI partition support must be selected -#endif - -/* #define EXT2_DEBUG */ - -#ifdef EXT2_DEBUG -#define PRINTF(fmt,args...) printf (fmt ,##args) -#else -#define PRINTF(fmt,args...) -#endif +#include <ext_common.h> int do_ext2ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *filename = "/"; - int dev=0; - int part=1; - char *ep; - block_dev_desc_t *dev_desc=NULL; - int part_length; - - if (argc < 3) - return CMD_RET_USAGE; - - dev = (int)simple_strtoul (argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - - if (dev_desc == NULL) { - printf ("\n** Block device %s %d not supported\n", argv[1], dev); - return 1; - } - - if (*ep) { - if (*ep != ':') { - puts ("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } - - if (argc == 4) - filename = argv[3]; - - PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename); - - if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) { - printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part); - ext2fs_close(); - return 1; - } - - if (!ext2fs_mount(part_length)) { - printf ("** Bad ext2 partition or disk - %s %d:%d **\n", argv[1], dev, part); - ext2fs_close(); - return 1; - } - - if (ext2fs_ls (filename)) { - printf ("** Error ext2fs_ls() **\n"); - ext2fs_close(); - return 1; - }; - - ext2fs_close(); + if (do_ext_ls(cmdtp, flag, argc, argv)) + return -1; return 0; } -U_BOOT_CMD( - ext2ls, 4, 1, do_ext2ls, - "list files in a directory (default /)", - "<interface> <dev[:part]> [directory]\n" - " - list files from 'dev' on 'interface' in a 'directory'" -); - /****************************************************************************** * Ext2fs boot command intepreter. Derived from diskboot */ int do_ext2load (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *filename = NULL; - char *ep; - int dev, part = 1; - ulong addr = 0, part_length; - int filelen; - disk_partition_t info; - block_dev_desc_t *dev_desc = NULL; - char buf [12]; - unsigned long count; - char *addr_str; - - switch (argc) { - case 3: - addr_str = getenv("loadaddr"); - if (addr_str != NULL) - addr = simple_strtoul (addr_str, NULL, 16); - else - addr = CONFIG_SYS_LOAD_ADDR; - - filename = getenv ("bootfile"); - count = 0; - break; - case 4: - addr = simple_strtoul (argv[3], NULL, 16); - filename = getenv ("bootfile"); - count = 0; - break; - case 5: - addr = simple_strtoul (argv[3], NULL, 16); - filename = argv[4]; - count = 0; - break; - case 6: - addr = simple_strtoul (argv[3], NULL, 16); - filename = argv[4]; - count = simple_strtoul (argv[5], NULL, 16); - break; - - default: - return CMD_RET_USAGE; - } - - if (!filename) { - puts ("** No boot file defined **\n"); - return 1; - } - - dev = (int)simple_strtoul (argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc==NULL) { - printf ("** Block device %s %d not supported\n", argv[1], dev); - return 1; - } - if (*ep) { - if (*ep != ':') { - puts ("** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } - - PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part); - - if (part != 0) { - if (get_partition_info (dev_desc, part, &info)) { - printf ("** Bad partition %d **\n", part); - return 1; - } - - if (strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) { - printf ("** Invalid partition type \"%.32s\"" - " (expect \"" BOOT_PART_TYPE "\")\n", - info.type); - return 1; - } - printf ("Loading file \"%s\" " - "from %s device %d:%d (%.32s)\n", - filename, - argv[1], dev, part, info.name); - } else { - printf ("Loading file \"%s\" from %s device %d\n", - filename, argv[1], dev); - } - - - if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) { - printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part); - ext2fs_close(); - return 1; - } - - if (!ext2fs_mount(part_length)) { - printf ("** Bad ext2 partition or disk - %s %d:%d **\n", - argv[1], dev, part); - ext2fs_close(); - return 1; - } - - filelen = ext2fs_open(filename); - if (filelen < 0) { - printf("** File not found %s\n", filename); - ext2fs_close(); - return 1; - } - if ((count < filelen) && (count != 0)) { - filelen = count; - } - - if (ext2fs_read((char *)addr, filelen) != filelen) { - printf("** Unable to read \"%s\" from %s %d:%d **\n", - filename, argv[1], dev, part); - ext2fs_close(); - return 1; - } - - ext2fs_close(); - - /* Loading ok, update default load address */ - load_addr = addr; - - printf ("%d bytes read\n", filelen); - sprintf(buf, "%X", filelen); - setenv("filesize", buf); + if (do_ext_load(cmdtp, flag, argc, argv)) + return -1; return 0; } U_BOOT_CMD( + ext2ls, 4, 1, do_ext2ls, + "list files in a directory (default /)", + "<interface> <dev[:part]> [directory]\n" + " - list files from 'dev' on 'interface' in a 'directory'" +); + +U_BOOT_CMD( ext2load, 6, 0, do_ext2load, "load binary file from a Ext2 filesystem", "<interface> <dev[:part]> [addr] [filename] [bytes]\n" diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c new file mode 100644 index 0000000..ca46561 --- /dev/null +++ b/common/cmd_ext4.c @@ -0,0 +1,145 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * + * Ext4fs support + * made from existing cmd_ext2.c file of Uboot + * + * (C) Copyright 2004 + * esd gmbh <www.esd-electronics.com> + * Reinhard Arlt <reinhard.arlt@esd-electronics.com> + * + * made from cmd_reiserfs by + * + * (C) Copyright 2003 - 2004 + * Sysgo Real-Time Solutions, AG <www.elinos.com> + * Pavel Bartusek <pba@sysgo.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* + * Changelog: + * 0.1 - Newly created file for ext4fs support. Taken from cmd_ext2.c + * file in uboot. Added ext4fs ls load and write support. + */ + +#include <common.h> +#include <part.h> +#include <config.h> +#include <command.h> +#include <image.h> +#include <linux/ctype.h> +#include <asm/byteorder.h> +#include <ext_common.h> +#include <ext4fs.h> +#include <linux/stat.h> +#include <malloc.h> + +#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) +#include <usb.h> +#endif + +int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (do_ext_load(cmdtp, flag, argc, argv)) + return -1; + + return 0; +} + +int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + if (do_ext_ls(cmdtp, flag, argc, argv)) + return -1; + + return 0; +} + +#if defined(CONFIG_CMD_EXT4_WRITE) +int do_ext4_write(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + const char *filename = "/"; + int dev, part; + unsigned long ram_address; + unsigned long file_size; + disk_partition_t info; + block_dev_desc_t *dev_desc; + + if (argc < 6) + return cmd_usage(cmdtp); + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) + return 1; + + dev = dev_desc->dev; + + /* get the filename */ + filename = argv[3]; + + /* get the address in hexadecimal format (string to int) */ + ram_address = simple_strtoul(argv[4], NULL, 16); + + /* get the filesize in base 10 format */ + file_size = simple_strtoul(argv[5], NULL, 10); + + /* set the device as block device */ + ext4fs_set_blk_dev(dev_desc, &info); + + /* mount the filesystem */ + if (!ext4fs_mount(info.size)) { + printf("Bad ext4 partition %s %d:%lu\n", argv[1], dev, part); + goto fail; + } + + /* start write */ + if (ext4fs_write(filename, (unsigned char *)ram_address, file_size)) { + printf("** Error ext4fs_write() **\n"); + goto fail; + } + ext4fs_close(); + + return 0; + +fail: + ext4fs_close(); + + return 1; +} + +U_BOOT_CMD(ext4write, 6, 1, do_ext4_write, + "create a file in the root directory", + "<interface> <dev[:part]> [Absolute filename path] [Address] [sizebytes]\n" + " - create a file in / directory"); + +#endif + +U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls, + "list files in a directory (default /)", + "<interface> <dev[:part]> [directory]\n" + " - list files from 'dev' on 'interface' in a 'directory'"); + +U_BOOT_CMD(ext4load, 6, 0, do_ext4_load, + "load binary file from a Ext4 filesystem", + "<interface> <dev[:part]> [addr] [filename] [bytes]\n" + " - load binary file 'filename' from 'dev' on 'interface'\n" + " to address 'addr' from ext4 filesystem"); diff --git a/common/cmd_ext_common.c b/common/cmd_ext_common.c new file mode 100644 index 0000000..1952f4d --- /dev/null +++ b/common/cmd_ext_common.c @@ -0,0 +1,197 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT2/4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * + * Ext4fs support + * made from existing cmd_ext2.c file of Uboot + * + * (C) Copyright 2004 + * esd gmbh <www.esd-electronics.com> + * Reinhard Arlt <reinhard.arlt@esd-electronics.com> + * + * made from cmd_reiserfs by + * + * (C) Copyright 2003 - 2004 + * Sysgo Real-Time Solutions, AG <www.elinos.com> + * Pavel Bartusek <pba@sysgo.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* + * Changelog: + * 0.1 - Newly created file for ext4fs support. Taken from cmd_ext2.c + * file in uboot. Added ext4fs ls load and write support. + */ + +#include <common.h> +#include <part.h> +#include <config.h> +#include <command.h> +#include <image.h> +#include <linux/ctype.h> +#include <asm/byteorder.h> +#include <ext_common.h> +#include <ext4fs.h> +#include <linux/stat.h> +#include <malloc.h> + +#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) +#include <usb.h> +#endif + +#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION) +#error DOS or EFI partition support must be selected +#endif + +#define DOS_PART_MAGIC_OFFSET 0x1fe +#define DOS_FS_TYPE_OFFSET 0x36 +#define DOS_FS32_TYPE_OFFSET 0x52 + +int do_ext_load(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + char *filename = NULL; + int dev, part; + ulong addr = 0; + int filelen; + disk_partition_t info; + block_dev_desc_t *dev_desc; + char buf[12]; + unsigned long count; + const char *addr_str; + + count = 0; + addr = simple_strtoul(argv[3], NULL, 16); + filename = getenv("bootfile"); + switch (argc) { + case 3: + addr_str = getenv("loadaddr"); + if (addr_str != NULL) + addr = simple_strtoul(addr_str, NULL, 16); + else + addr = CONFIG_SYS_LOAD_ADDR; + + break; + case 4: + break; + case 5: + filename = argv[4]; + break; + case 6: + filename = argv[4]; + count = simple_strtoul(argv[5], NULL, 16); + break; + + default: + return cmd_usage(cmdtp); + } + + if (!filename) { + puts("** No boot file defined **\n"); + return 1; + } + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) + return 1; + + dev = dev_desc->dev; + printf("Loading file \"%s\" from %s device %d%c%c\n", + filename, argv[1], dev, + part ? ':' : ' ', part ? part + '0' : ' '); + + ext4fs_set_blk_dev(dev_desc, &info); + + if (!ext4fs_mount(info.size)) { + printf("** Bad ext2 partition or disk - %s %d:%d **\n", + argv[1], dev, part); + ext4fs_close(); + goto fail; + } + + filelen = ext4fs_open(filename); + if (filelen < 0) { + printf("** File not found %s\n", filename); + ext4fs_close(); + goto fail; + } + if ((count < filelen) && (count != 0)) + filelen = count; + + if (ext4fs_read((char *)addr, filelen) != filelen) { + printf("** Unable to read \"%s\" from %s %d:%d **\n", + filename, argv[1], dev, part); + ext4fs_close(); + goto fail; + } + + ext4fs_close(); + /* Loading ok, update default load address */ + load_addr = addr; + + printf("%d bytes read\n", filelen); + sprintf(buf, "%X", filelen); + setenv("filesize", buf); + + return 0; +fail: + return 1; +} + +int do_ext_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + const char *filename = "/"; + int dev; + int part; + block_dev_desc_t *dev_desc; + disk_partition_t info; + + if (argc < 2) + return cmd_usage(cmdtp); + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) + return 1; + + if (argc == 4) + filename = argv[3]; + + dev = dev_desc->dev; + ext4fs_set_blk_dev(dev_desc, &info); + + if (!ext4fs_mount(info.size)) { + printf("** Bad ext2 partition or disk - %s %d:%d **\n", + argv[1], dev, part); + ext4fs_close(); + goto fail; + } + + if (ext4fs_ls(filename)) { + printf("** Error extfs_ls() **\n"); + ext4fs_close(); + goto fail; + }; + + ext4fs_close(); + return 0; + +fail: + return 1; +} diff --git a/common/cmd_fat.c b/common/cmd_fat.c index 559a16d..5a5698b 100644 --- a/common/cmd_fat.c +++ b/common/cmd_fat.c @@ -37,43 +37,35 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { long size; unsigned long offset; - unsigned long count; + unsigned long count = 0; + unsigned long pos = 0; char buf [12]; block_dev_desc_t *dev_desc=NULL; - int dev=0; - int part=1; - char *ep; + disk_partition_t info; + int part, dev; if (argc < 5) { - printf( "usage: fatload <interface> <dev[:part]> " - "<addr> <filename> [bytes]\n"); + printf("usage: fatload <interface> [<dev[:part]>] " + "<addr> <filename> [bytes [pos]]\n"); return 1; } - dev = (int)simple_strtoul(argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc == NULL) { - puts("\n** Invalid boot device **\n"); + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } + + dev = dev_desc->dev; if (fat_register_device(dev_desc,part)!=0) { printf("\n** Unable to use %s %d:%d for fatload **\n", argv[1], dev, part); return 1; } offset = simple_strtoul(argv[3], NULL, 16); - if (argc == 6) + if (argc >= 6) count = simple_strtoul(argv[5], NULL, 16); - else - count = 0; - size = file_fat_read(argv[4], (unsigned char *)offset, count); + if (argc >= 7) + pos = simple_strtoul(argv[6], NULL, 16); + size = file_fat_read_at(argv[4], pos, (unsigned char *)offset, count); if(size==-1) { printf("\n** Unable to read \"%s\" from %s %d:%d **\n", @@ -91,39 +83,34 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( - fatload, 6, 0, do_fat_fsload, + fatload, 7, 0, do_fat_fsload, "load binary file from a dos filesystem", - "<interface> <dev[:part]> <addr> <filename> [bytes]\n" - " - load binary file 'filename' from 'dev' on 'interface'\n" - " to address 'addr' from dos filesystem" + "<interface> [<dev[:part]>] <addr> <filename> [bytes [pos]]\n" + " - Load binary file 'filename' from 'dev' on 'interface'\n" + " to address 'addr' from dos filesystem.\n" + " 'pos' gives the file position to start loading from.\n" + " If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n" + " 'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n" + " the load stops on end of file." ); int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *filename = "/"; - int ret; - int dev=0; - int part=1; - char *ep; + int ret, dev, part; block_dev_desc_t *dev_desc=NULL; + disk_partition_t info; - if (argc < 3) { - printf("usage: fatls <interface> <dev[:part]> [directory]\n"); + if (argc < 2) { + printf("usage: fatls <interface> [<dev[:part]>] [directory]\n"); return 0; } - dev = (int)simple_strtoul(argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc == NULL) { - puts("\n** Invalid boot device **\n"); + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } + + dev = dev_desc->dev; if (fat_register_device(dev_desc,part)!=0) { printf("\n** Unable to use %s %d:%d for fatls **\n", argv[1], dev, part); @@ -142,34 +129,26 @@ int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( fatls, 4, 1, do_fat_ls, "list files in a directory (default /)", - "<interface> <dev[:part]> [directory]\n" + "<interface> [<dev[:part]>] [directory]\n" " - list files from 'dev' on 'interface' in a 'directory'" ); int do_fat_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - int dev=0; - int part=1; - char *ep; - block_dev_desc_t *dev_desc=NULL; + int dev, part; + block_dev_desc_t *dev_desc; + disk_partition_t info; if (argc < 2) { - printf("usage: fatinfo <interface> <dev[:part]>\n"); + printf("usage: fatinfo <interface> [<dev[:part]>]\n"); return 0; } - dev = (int)simple_strtoul(argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc == NULL) { - puts("\n** Invalid boot device **\n"); + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } + + dev = dev_desc->dev; if (fat_register_device(dev_desc,part)!=0) { printf("\n** Unable to use %s %d:%d for fatinfo **\n", argv[1], dev, part); @@ -181,7 +160,7 @@ int do_fat_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( fatinfo, 3, 1, do_fat_fsinfo, "print information about filesystem", - "<interface> <dev[:part]>\n" + "<interface> [<dev[:part]>]\n" " - print information about filesystem from 'dev' on 'interface'" ); @@ -193,26 +172,19 @@ static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag, unsigned long addr; unsigned long count; block_dev_desc_t *dev_desc = NULL; + disk_partition_t info; int dev = 0; int part = 1; - char *ep; if (argc < 5) return cmd_usage(cmdtp); - dev = (int)simple_strtoul(argv[2], &ep, 16); - dev_desc = get_dev(argv[1], dev); - if (dev_desc == NULL) { - puts("\n** Invalid boot device **\n"); + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } + + dev = dev_desc->dev; + if (fat_register_device(dev_desc, part) != 0) { printf("\n** Unable to use %s %d:%d for fatwrite **\n", argv[1], dev, part); diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 9a5c53e..e2225c4 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -114,10 +114,21 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) } } + return CMD_RET_SUCCESS; + } + + if (!working_fdt) { + puts( + "No FDT memory address configured. Please configure\n" + "the FDT address via \"fdt addr <address>\" command.\n" + "Aborting!\n"); + return CMD_RET_FAILURE; + } + /* * Move the working_fdt */ - } else if (strncmp(argv[1], "mo", 2) == 0) { + if (strncmp(argv[1], "mo", 2) == 0) { struct fdt_header *newaddr; int len; int err; diff --git a/common/cmd_flash.c b/common/cmd_flash.c index 0e9b2e3..e55d366 100644 --- a/common/cmd_flash.c +++ b/common/cmd_flash.c @@ -443,7 +443,8 @@ int flash_sect_erase (ulong addr_first, ulong addr_last) rcode = flash_erase (info, s_first[bank], s_last[bank]); } } - printf ("Erased %d sectors\n", erased); + if (rcode == 0) + printf("Erased %d sectors\n", erased); } else if (rcode == 0) { puts ("Error: start and/or end address" " not on sector boundary\n"); diff --git a/common/cmd_ide.c b/common/cmd_ide.c index f5b6c7b..6e1e568 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -334,156 +334,7 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { - char *boot_device = NULL; - char *ep; - int dev, part = 0; - ulong addr, cnt; - disk_partition_t info; - image_header_t *hdr; - -#if defined(CONFIG_FIT) - const void *fit_hdr = NULL; -#endif - - bootstage_mark(BOOTSTAGE_ID_IDE_START); - switch (argc) { - case 1: - addr = CONFIG_SYS_LOAD_ADDR; - boot_device = getenv("bootdevice"); - break; - case 2: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = getenv("bootdevice"); - break; - case 3: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = argv[2]; - break; - default: - bootstage_error(BOOTSTAGE_ID_IDE_ADDR); - return CMD_RET_USAGE; - } - bootstage_mark(BOOTSTAGE_ID_IDE_ADDR); - - if (!boot_device) { - puts("\n** No boot device **\n"); - bootstage_error(BOOTSTAGE_ID_IDE_BOOT_DEVICE); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE); - - dev = simple_strtoul(boot_device, &ep, 16); - - if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { - printf("\n** Device %d not available\n", dev); - bootstage_error(BOOTSTAGE_ID_IDE_TYPE); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_IDE_TYPE); - - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - bootstage_error(BOOTSTAGE_ID_IDE_PART); - return 1; - } - part = simple_strtoul(++ep, NULL, 16); - } - bootstage_mark(BOOTSTAGE_ID_IDE_PART); - - if (get_partition_info(&ide_dev_desc[dev], part, &info)) { - bootstage_error(BOOTSTAGE_ID_IDE_PART_INFO); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_IDE_PART_INFO); - - if ((strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) - && - (strncmp((char *)info.type, BOOT_PART_COMP, sizeof(info.type)) != 0) - ) { - printf("\n** Invalid partition type \"%.32s\"" " (expect \"" - BOOT_PART_TYPE "\")\n", - info.type); - bootstage_error(BOOTSTAGE_ID_IDE_PART_TYPE); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_IDE_PART_TYPE); - - printf("\nLoading from IDE device %d, partition %d: " - "Name: %.32s Type: %.32s\n", dev, part, info.name, info.type); - - debug("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", - info.start, info.size, info.blksz); - - if (ide_dev_desc[dev]. - block_read(dev, info.start, 1, (ulong *) addr) != 1) { - printf("** Read error on %d:%d\n", dev, part); - bootstage_error(BOOTSTAGE_ID_IDE_PART_READ); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ); - - switch (genimg_get_format((void *) addr)) { - case IMAGE_FORMAT_LEGACY: - hdr = (image_header_t *) addr; - - bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT); - - if (!image_check_hcrc(hdr)) { - puts("\n** Bad Header Checksum **\n"); - bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM); - - image_print_contents(hdr); - - cnt = image_get_image_size(hdr); - break; -#if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - fit_hdr = (const void *) addr; - puts("Fit image detected...\n"); - - cnt = fit_get_size(fit_hdr); - break; -#endif - default: - bootstage_error(BOOTSTAGE_ID_IDE_FORMAT); - puts("** Unknown image type\n"); - return 1; - } - - cnt += info.blksz - 1; - cnt /= info.blksz; - cnt -= 1; - - if (ide_dev_desc[dev].block_read(dev, info.start + 1, cnt, - (ulong *)(addr + info.blksz)) != cnt) { - printf("** Read error on %d:%d\n", dev, part); - bootstage_error(BOOTSTAGE_ID_IDE_READ); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_IDE_READ); - -#if defined(CONFIG_FIT) - /* This cannot be done earlier, we need complete FIT image in RAM first */ - if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) { - if (!fit_check_format(fit_hdr)) { - bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ); - puts("** Bad FIT image format\n"); - return 1; - } - bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK); - fit_print_contents(fit_hdr); - } -#endif - - /* Loading ok, update default load address */ - - load_addr = addr; - - return bootm_maybe_autostart(cmdtp, argv[0]); + return common_diskboot(cmdtp, "ide", argc, argv); } /* ------------------------------------------------------------------------- */ diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index 750509d..79a1088 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -144,8 +144,7 @@ int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( mmcinfo, 1, 0, do_mmcinfo, "display MMC info", - " - device number of the device to dislay info of\n" - "" + "- dislay info of the current MMC device" ); int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 4367f5a..e24ed7f 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -231,12 +231,18 @@ print: #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK static void print_status(ulong start, ulong end, ulong erasesize, int status) { + /* + * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is + * not the same as others. Instead of bit 1 being lock, it is + * #lock_tight. To make the driver support either format, ignore bit 1 + * and use only bit 0 and bit 2. + */ printf("%08lx - %08lx: %08lx blocks %s%s%s\n", start, end - 1, (end - start) / erasesize, ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), - ((status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), + (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""), ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); } @@ -749,11 +755,18 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) return 0; } - if (strcmp(cmd, "unlock") == 0) { + if (strncmp(cmd, "unlock", 5) == 0) { + int allexcept = 0; + + s = strchr(cmd, '.'); + + if (s && !strcmp(s, ".allexcept")) + allexcept = 1; + if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0) return 1; - if (!nand_unlock(&nand_info[dev], off, size)) { + if (!nand_unlock(&nand_info[dev], off, size, allexcept)) { puts("NAND flash successfully unlocked\n"); } else { puts("Error unlocking NAND flash, " @@ -807,7 +820,7 @@ U_BOOT_CMD( "\n" "nand lock [tight] [status]\n" " bring nand to lock state or display locked pages\n" - "nand unlock [offset] [size] - unlock section" + "nand unlock[.allexcept] [offset] [size] - unlock section" #endif #ifdef CONFIG_ENV_OFFSET_OOB "\n" diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index fd05e72..3474bc6 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -198,31 +198,20 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag, #endif /* - * Set a new environment variable, - * or replace or delete an existing one. + * Perform consistency checking before setting, replacing, or deleting an + * environment variable, then (if successful) apply the changes to internals so + * to make them effective. Code for this function was taken out of + * _do_env_set(), which now calls it instead. + * Also called as a callback function by himport_r(). + * Returns 0 in case of success, 1 in case of failure. + * When (flag & H_FORCE) is set, do not print out any error message and force + * overwriting of write-once variables. */ -int _do_env_set(int flag, int argc, char * const argv[]) + +int env_check_apply(const char *name, const char *oldval, + const char *newval, int flag) { - int i, len; int console = -1; - char *name, *value, *s; - ENTRY e, *ep; - - name = argv[1]; - - if (strchr(name, '=')) { - printf("## Error: illegal character '=' in variable name" - "\"%s\"\n", name); - return 1; - } - - env_id++; - /* - * search if variable with this name already exists - */ - e.key = name; - e.data = NULL; - hsearch_r(e, FIND, &ep, &env_htab); /* Check for console redirection */ if (strcmp(name, "stdin") == 0) @@ -233,60 +222,75 @@ int _do_env_set(int flag, int argc, char * const argv[]) console = stderr; if (console != -1) { - if (argc < 3) { /* Cannot delete it! */ - printf("Can't delete \"%s\"\n", name); + if ((newval == NULL) || (*newval == '\0')) { + /* We cannot delete stdin/stdout/stderr */ + if ((flag & H_FORCE) == 0) + printf("Can't delete \"%s\"\n", name); return 1; } #ifdef CONFIG_CONSOLE_MUX - i = iomux_doenv(console, argv[2]); - if (i) - return i; + if (iomux_doenv(console, newval)) + return 1; #else /* Try assigning specified device */ - if (console_assign(console, argv[2]) < 0) + if (console_assign(console, newval) < 0) return 1; #ifdef CONFIG_SERIAL_MULTI - if (serial_assign(argv[2]) < 0) + if (serial_assign(newval) < 0) return 1; #endif #endif /* CONFIG_CONSOLE_MUX */ } /* - * Some variables like "ethaddr" and "serial#" can be set only - * once and cannot be deleted; also, "ver" is readonly. + * Some variables like "ethaddr" and "serial#" can be set only once and + * cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined. */ - if (ep) { /* variable exists */ #ifndef CONFIG_ENV_OVERWRITE + if (oldval != NULL && /* variable exists */ + (flag & H_FORCE) == 0) { /* and we are not forced */ if (strcmp(name, "serial#") == 0 || (strcmp(name, "ethaddr") == 0 #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR) - && strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0 + && strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0 #endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */ )) { printf("Can't overwrite \"%s\"\n", name); return 1; } + } #endif + /* + * When we change baudrate, or we are doing an env default -a + * (which will erase all variables prior to calling this), + * we want the baudrate to actually change - for real. + */ + if (oldval != NULL || /* variable exists */ + (flag & H_NOCLEAR) == 0) { /* or env is clear */ /* * Switch to new baudrate if new baudrate is supported */ if (strcmp(name, "baudrate") == 0) { - int baudrate = simple_strtoul(argv[2], NULL, 10); + int baudrate = simple_strtoul(newval, NULL, 10); int i; for (i = 0; i < N_BAUDRATES; ++i) { if (baudrate == baudrate_table[i]) break; } if (i == N_BAUDRATES) { - printf("## Baudrate %d bps not supported\n", - baudrate); + if ((flag & H_FORCE) == 0) + printf("## Baudrate %d bps not " + "supported\n", baudrate); return 1; } + if (gd->baudrate == baudrate) { + /* If unchanged, we just say it's OK */ + return 0; + } printf("## Switch baudrate to %d bps and" - "press ENTER ...\n", baudrate); + "press ENTER ...\n", baudrate); udelay(50000); gd->baudrate = baudrate; #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2) @@ -300,9 +304,62 @@ int _do_env_set(int flag, int argc, char * const argv[]) } } + /* + * Some variables should be updated when the corresponding + * entry in the environment is changed + */ + if (strcmp(name, "loadaddr") == 0) { + load_addr = simple_strtoul(newval, NULL, 16); + return 0; + } +#if defined(CONFIG_CMD_NET) + else if (strcmp(name, "bootfile") == 0) { + copy_filename(BootFile, newval, sizeof(BootFile)); + return 0; + } +#endif + return 0; +} + +/* + * Set a new environment variable, + * or replace or delete an existing one. +*/ +int _do_env_set(int flag, int argc, char * const argv[]) +{ + int i, len; + char *name, *value, *s; + ENTRY e, *ep; + + name = argv[1]; + value = argv[2]; + + if (strchr(name, '=')) { + printf("## Error: illegal character '='" + "in variable name \"%s\"\n", name); + return 1; + } + + env_id++; + /* + * search if variable with this name already exists + */ + e.key = name; + e.data = NULL; + hsearch_r(e, FIND, &ep, &env_htab); + + /* + * Perform requested checks. Notice how since we are overwriting + * a single variable, we need to set H_NOCLEAR + */ + if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) { + debug("check function did not approve, refusing\n"); + return 1; + } + /* Delete only ? */ if (argc < 3 || argv[2] == NULL) { - int rc = hdelete_r(name, &env_htab); + int rc = hdelete_r(name, &env_htab, 0); return !rc; } @@ -337,20 +394,6 @@ int _do_env_set(int flag, int argc, char * const argv[]) return 1; } - /* - * Some variables should be updated when the corresponding - * entry in the environment is changed - */ - if (strcmp(argv[1], "loadaddr") == 0) { - load_addr = simple_strtoul(argv[2], NULL, 16); - return 0; - } -#if defined(CONFIG_CMD_NET) - else if (strcmp(argv[1], "bootfile") == 0) { - copy_filename(BootFile, argv[2], sizeof(BootFile)); - return 0; - } -#endif return 0; } @@ -613,14 +656,41 @@ int envmatch(uchar *s1, int i2) return -1; } -static int do_env_default(cmd_tbl_t *cmdtp, int flag, +static int do_env_default(cmd_tbl_t *cmdtp, int __flag, int argc, char * const argv[]) { - if (argc != 2 || strcmp(argv[1], "-f") != 0) - return CMD_RET_USAGE; + int all = 0, flag = 0; - set_default_env("## Resetting to default environment\n"); - return 0; + debug("Initial value for argc=%d\n", argc); + while (--argc > 0 && **++argv == '-') { + char *arg = *argv; + + while (*++arg) { + switch (*arg) { + case 'a': /* default all */ + all = 1; + break; + case 'f': /* force */ + flag |= H_FORCE; + break; + default: + return cmd_usage(cmdtp); + } + } + } + debug("Final value for argc=%d\n", argc); + if (all && (argc == 0)) { + /* Reset the whole environment */ + set_default_env("## Resetting to default environment\n"); + return 0; + } + if (!all && (argc > 0)) { + /* Reset individual variables */ + set_default_vars(argc, argv); + return 0; + } + + return cmd_usage(cmdtp); } static int do_env_delete(cmd_tbl_t *cmdtp, int flag, @@ -872,7 +942,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag, addr = (char *)ep->data; } - if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) { + if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR, + 0, NULL, 0 /* do_apply */) == 0) { error("Environment import failed: errno = %d\n", errno); return 1; } @@ -950,15 +1021,20 @@ U_BOOT_CMD( #if defined(CONFIG_CMD_ASKENV) "ask name [message] [size] - ask for environment variable\nenv " #endif - "default -f - reset default environment\n" + "default [-f] -a - [forcibly] reset default environment\n" + "env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n" #if defined(CONFIG_CMD_EDITENV) "env edit name - edit environment variable\n" #endif +#if defined(CONFIG_CMD_EXPORTENV) "env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n" +#endif #if defined(CONFIG_CMD_GREPENV) "env grep string [...] - search environment\n" #endif +#if defined(CONFIG_CMD_IMPORTENV) "env import [-d] [-t | -b | -c] addr [size] - import environment\n" +#endif "env print [name ...] - print environment\n" #if defined(CONFIG_CMD_RUN) "env run var [...] - run commands in an environment variable\n" diff --git a/common/cmd_part.c b/common/cmd_part.c new file mode 100644 index 0000000..d997597 --- /dev/null +++ b/common/cmd_part.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * made from cmd_ext2, which was: + * + * (C) Copyright 2004 + * esd gmbh <www.esd-electronics.com> + * Reinhard Arlt <reinhard.arlt@esd-electronics.com> + * + * made from cmd_reiserfs by + * + * (C) Copyright 2003 - 2004 + * Sysgo Real-Time Solutions, AG <www.elinos.com> + * Pavel Bartusek <pba@sysgo.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <config.h> +#include <command.h> +#include <part.h> +#include <vsprintf.h> + +#ifndef CONFIG_PARTITION_UUIDS +#error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_PART to be enabled +#endif + +int do_part_uuid(int argc, char * const argv[]) +{ + int part; + block_dev_desc_t *dev_desc; + disk_partition_t info; + + if (argc < 2) + return CMD_RET_USAGE; + if (argc > 3) + return CMD_RET_USAGE; + + part = get_device_and_partition(argv[0], argv[1], &dev_desc, &info, 0); + if (part < 0) + return 1; + + if (argc > 2) + setenv(argv[2], info.uuid); + else + printf("%s\n", info.uuid); + + return 0; +} + +int do_part_list(int argc, char * const argv[]) +{ + int ret; + block_dev_desc_t *desc; + + if (argc != 2) + return CMD_RET_USAGE; + + ret = get_device(argv[0], argv[1], &desc); + if (ret < 0) + return 1; + + print_part(desc); + + return 0; +} + +int do_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc < 2) + return CMD_RET_USAGE; + + if (!strcmp(argv[1], "uuid")) + return do_part_uuid(argc - 2, argv + 2); + else if (!strcmp(argv[1], "list")) + return do_part_list(argc - 2, argv + 2); + + return CMD_RET_USAGE; +} + +U_BOOT_CMD( + part, 5, 1, do_part, + "disk partition related commands", + "part uuid <interface> <dev>:<part>\n" + " - print partition UUID\n" + "part uuid <interface> <dev>:<part> <varname>\n" + " - set environment variable to partition UUID\n" + "part list <interface> <dev>\n" + " - print a device's partition table" +); diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index 6b31dea..ee75db9 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -450,6 +450,7 @@ struct pxe_label { char *kernel; char *append; char *initrd; + char *fdt; int attempted; int localboot; struct list_head list; @@ -517,6 +518,9 @@ static void label_destroy(struct pxe_label *label) if (label->initrd) free(label->initrd); + if (label->fdt) + free(label->fdt); + free(label); } @@ -541,6 +545,9 @@ static void label_print(void *data) if (label->initrd) printf("\t\tinitrd: %s\n", label->initrd); + + if (label->fdt) + printf("\tfdt: %s\n", label->fdt); } /* @@ -628,10 +635,29 @@ static void label_boot(struct pxe_label *label) bootm_argv[1] = getenv("kernel_addr_r"); /* - * fdt usage is optional. If there is an fdt_addr specified, we will - * pass it along to bootm, and adjust argc appropriately. + * fdt usage is optional: + * It handles the following scenarios. All scenarios are exclusive + * + * Scenario 1: If fdt_addr_r specified and "fdt" label is defined in + * pxe file, retrieve fdt blob from server. Pass fdt_addr_r to bootm, + * and adjust argc appropriately. + * + * Scenario 2: If there is an fdt_addr specified, pass it along to + * bootm, and adjust argc appropriately. + * + * Scenario 3: fdt blob is not available. */ - bootm_argv[3] = getenv("fdt_addr"); + bootm_argv[3] = getenv("fdt_addr_r"); + + /* if fdt label is defined then get fdt from server */ + if (bootm_argv[3] && label->fdt) { + if (get_relfile_envaddr(label->fdt, "fdt_addr_r") < 0) { + printf("Skipping %s for failure retrieving fdt\n", + label->name); + return; + } + } else + bootm_argv[3] = getenv("fdt_addr"); if (bootm_argv[3]) bootm_argc = 4; @@ -658,6 +684,7 @@ enum token_type { T_DEFAULT, T_PROMPT, T_INCLUDE, + T_FDT, T_INVALID }; @@ -685,6 +712,7 @@ static const struct token keywords[] = { {"append", T_APPEND}, {"initrd", T_INITRD}, {"include", T_INCLUDE}, + {"fdt", T_FDT}, {NULL, T_INVALID} }; @@ -1074,6 +1102,11 @@ static int parse_label(char **c, struct pxe_menu *cfg) err = parse_sliteral(c, &label->initrd); break; + case T_FDT: + if (!label->fdt) + err = parse_sliteral(c, &label->fdt); + break; + case T_LOCALBOOT: err = parse_integer(c, &label->localboot); break; diff --git a/common/cmd_reiser.c b/common/cmd_reiser.c index fbb9484..e658618 100644 --- a/common/cmd_reiser.c +++ b/common/cmd_reiser.c @@ -50,43 +50,27 @@ int do_reiserls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *filename = "/"; - int dev=0; - int part=1; - char *ep; + int dev, part; block_dev_desc_t *dev_desc=NULL; - int part_length; + disk_partition_t info; if (argc < 3) return CMD_RET_USAGE; - dev = (int)simple_strtoul (argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - - if (dev_desc == NULL) { - printf ("\n** Block device %s %d not supported\n", argv[1], dev); + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) return 1; - } - - if (*ep) { - if (*ep != ':') { - puts ("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } if (argc == 4) { filename = argv[3]; } + dev = dev_desc->dev; PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename); - if ((part_length = reiserfs_set_blk_dev(dev_desc, part)) == 0) { - printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part); - return 1; - } + reiserfs_set_blk_dev(dev_desc, &info); - if (!reiserfs_mount(part_length)) { + if (!reiserfs_mount(info.size)) { printf ("** Bad Reiserfs partition or disk - %s %d:%d **\n", argv[1], dev, part); return 1; } @@ -112,9 +96,8 @@ U_BOOT_CMD( int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *filename = NULL; - char *ep; - int dev, part = 0; - ulong addr = 0, part_length, filelen; + int dev, part; + ulong addr = 0, filelen; disk_partition_t info; block_dev_desc_t *dev_desc = NULL; char buf [12]; @@ -157,49 +140,19 @@ int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; } - dev = (int)simple_strtoul (argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc==NULL) { - printf ("\n** Block device %s %d not supported\n", argv[1], dev); + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts ("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } - PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part); + dev = dev_desc->dev; - if (part != 0) { - if (get_partition_info (dev_desc, part, &info)) { - printf ("** Bad partition %d **\n", part); - return 1; - } + printf("Loading file \"%s\" from %s device %d%c%c\n", + filename, argv[1], dev, + part ? ':' : ' ', part ? part + '0' : ' '); - if (strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) { - printf ("\n** Invalid partition type \"%.32s\"" - " (expect \"" BOOT_PART_TYPE "\")\n", - info.type); - return 1; - } - PRINTF ("\nLoading from block device %s device %d, partition %d: " - "Name: %.32s Type: %.32s File:%s\n", - argv[1], dev, part, info.name, info.type, filename); - } else { - PRINTF ("\nLoading from block device %s device %d, File:%s\n", - argv[1], dev, filename); - } - - - if ((part_length = reiserfs_set_blk_dev(dev_desc, part)) == 0) { - printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part); - return 1; - } + reiserfs_set_blk_dev(dev_desc, &info); - if (!reiserfs_mount(part_length)) { + if (!reiserfs_mount(info.size)) { printf ("** Bad Reiserfs partition or disk - %s %d:%d **\n", argv[1], dev, part); return 1; } diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index d15b567..22d0119 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -206,128 +206,7 @@ block_dev_desc_t * scsi_get_dev(int dev) */ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *boot_device = NULL; - char *ep; - int dev, part = 0; - ulong addr, cnt; - disk_partition_t info; - image_header_t *hdr; -#if defined(CONFIG_FIT) - const void *fit_hdr = NULL; -#endif - - switch (argc) { - case 1: - addr = CONFIG_SYS_LOAD_ADDR; - boot_device = getenv ("bootdevice"); - break; - case 2: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = getenv ("bootdevice"); - break; - case 3: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = argv[2]; - break; - default: - return CMD_RET_USAGE; - } - - if (!boot_device) { - puts ("\n** No boot device **\n"); - return 1; - } - - dev = simple_strtoul(boot_device, &ep, 16); - printf("booting from dev %d\n",dev); - if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { - printf ("\n** Device %d not available\n", dev); - return 1; - } - - if (*ep) { - if (*ep != ':') { - puts ("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = simple_strtoul(++ep, NULL, 16); - } - if (get_partition_info (&scsi_dev_desc[dev], part, &info)) { - printf("error reading partinfo\n"); - return 1; - } - if ((strncmp((char *)(info.type), BOOT_PART_TYPE, sizeof(info.type)) != 0) && - (strncmp((char *)(info.type), BOOT_PART_COMP, sizeof(info.type)) != 0)) { - printf ("\n** Invalid partition type \"%.32s\"" - " (expect \"" BOOT_PART_TYPE "\")\n", - info.type); - return 1; - } - - printf ("\nLoading from SCSI device %d, partition %d: " - "Name: %.32s Type: %.32s\n", - dev, part, info.name, info.type); - - debug ("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", - info.start, info.size, info.blksz); - - if (scsi_read (dev, info.start, 1, (ulong *)addr) != 1) { - printf ("** Read error on %d:%d\n", dev, part); - return 1; - } - - switch (genimg_get_format ((void *)addr)) { - case IMAGE_FORMAT_LEGACY: - hdr = (image_header_t *)addr; - - if (!image_check_hcrc (hdr)) { - puts ("\n** Bad Header Checksum **\n"); - return 1; - } - - image_print_contents (hdr); - cnt = image_get_image_size (hdr); - break; -#if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - fit_hdr = (const void *)addr; - puts ("Fit image detected...\n"); - - cnt = fit_get_size (fit_hdr); - break; -#endif - default: - puts ("** Unknown image type\n"); - return 1; - } - - cnt += info.blksz - 1; - cnt /= info.blksz; - cnt -= 1; - - if (scsi_read (dev, info.start+1, cnt, - (ulong *)(addr+info.blksz)) != cnt) { - printf ("** Read error on %d:%d\n", dev, part); - return 1; - } - -#if defined(CONFIG_FIT) - /* This cannot be done earlier, we need complete FIT image in RAM first */ - if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) { - if (!fit_check_format (fit_hdr)) { - puts ("** Bad FIT image format\n"); - return 1; - } - fit_print_contents (fit_hdr); - } -#endif - - /* Loading ok, update default load address */ - load_addr = addr; - - flush_cache (addr, (cnt+1)*info.blksz); - - return bootm_maybe_autostart(cmdtp, argv[0]); + return common_diskboot(cmdtp, "scsi", argc, argv); } /********************************************************************************* diff --git a/common/cmd_usb.c b/common/cmd_usb.c index a8e3ae5..181e727 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -355,143 +355,7 @@ void usb_show_tree(struct usb_device *dev) #ifdef CONFIG_USB_STORAGE int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *boot_device = NULL; - char *ep; - int dev, part = 1; - ulong addr, cnt; - disk_partition_t info; - image_header_t *hdr; - block_dev_desc_t *stor_dev; -#if defined(CONFIG_FIT) - const void *fit_hdr = NULL; -#endif - - switch (argc) { - case 1: - addr = CONFIG_SYS_LOAD_ADDR; - boot_device = getenv("bootdevice"); - break; - case 2: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = getenv("bootdevice"); - break; - case 3: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = argv[2]; - break; - default: - return CMD_RET_USAGE; - } - - if (!boot_device) { - puts("\n** No boot device **\n"); - return 1; - } - - dev = simple_strtoul(boot_device, &ep, 16); - stor_dev = usb_stor_get_dev(dev); - if (stor_dev == NULL || stor_dev->type == DEV_TYPE_UNKNOWN) { - printf("\n** Device %d not available\n", dev); - return 1; - } - if (stor_dev->block_read == NULL) { - printf("storage device not initialized. Use usb scan\n"); - return 1; - } - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = simple_strtoul(++ep, NULL, 16); - } - - if (get_partition_info(stor_dev, part, &info)) { - /* try to boot raw .... */ - strncpy((char *)&info.type[0], BOOT_PART_TYPE, - sizeof(BOOT_PART_TYPE)); - strncpy((char *)&info.name[0], "Raw", 4); - info.start = 0; - info.blksz = 0x200; - info.size = 2880; - printf("error reading partinfo...try to boot raw\n"); - } - if ((strncmp((char *)info.type, BOOT_PART_TYPE, - sizeof(info.type)) != 0) && - (strncmp((char *)info.type, BOOT_PART_COMP, - sizeof(info.type)) != 0)) { - printf("\n** Invalid partition type \"%.32s\"" - " (expect \"" BOOT_PART_TYPE "\")\n", - info.type); - return 1; - } - printf("\nLoading from USB device %d, partition %d: " - "Name: %.32s Type: %.32s\n", - dev, part, info.name, info.type); - - debug("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", - info.start, info.size, info.blksz); - - if (stor_dev->block_read(dev, info.start, 1, (ulong *)addr) != 1) { - printf("** Read error on %d:%d\n", dev, part); - return 1; - } - - switch (genimg_get_format((void *)addr)) { - case IMAGE_FORMAT_LEGACY: - hdr = (image_header_t *)addr; - - if (!image_check_hcrc(hdr)) { - puts("\n** Bad Header Checksum **\n"); - return 1; - } - - image_print_contents(hdr); - - cnt = image_get_image_size(hdr); - break; -#if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - fit_hdr = (const void *)addr; - puts("Fit image detected...\n"); - - cnt = fit_get_size(fit_hdr); - break; -#endif - default: - puts("** Unknown image type\n"); - return 1; - } - - cnt += info.blksz - 1; - cnt /= info.blksz; - cnt -= 1; - - if (stor_dev->block_read(dev, info.start+1, cnt, - (ulong *)(addr+info.blksz)) != cnt) { - printf("\n** Read error on %d:%d\n", dev, part); - return 1; - } - -#if defined(CONFIG_FIT) - /* This cannot be done earlier, we need complete FIT image in RAM - * first - */ - if (genimg_get_format((void *)addr) == IMAGE_FORMAT_FIT) { - if (!fit_check_format(fit_hdr)) { - puts("** Bad FIT image format\n"); - return 1; - } - fit_print_contents(fit_hdr); - } -#endif - - /* Loading ok, update default load address */ - load_addr = addr; - - flush_cache(addr, (cnt+1)*info.blksz); - - return bootm_maybe_autostart(cmdtp, argv[0]); + return common_diskboot(cmdtp, "usb", argc, argv); } #endif /* CONFIG_USB_STORAGE */ diff --git a/common/cmd_zfs.c b/common/cmd_zfs.c index a6ea2c0..d580f7b 100644 --- a/common/cmd_zfs.c +++ b/common/cmd_zfs.c @@ -49,12 +49,11 @@ static int do_zfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { char *filename = NULL; - char *ep; int dev; - unsigned long part = 1; + int part; ulong addr = 0; - ulong part_length; disk_partition_t info; + block_dev_desc_t *dev_desc; char buf[12]; unsigned long count; const char *addr_str; @@ -95,48 +94,17 @@ static int do_zfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } - dev = (int)simple_strtoul(argv[2], &ep, 16); - zfs_dev_desc = get_dev(argv[1], dev); - if (zfs_dev_desc == NULL) { - printf("** Block device %s %d not supported\n", argv[1], dev); + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts("** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = simple_strtoul(++ep, NULL, 16); - } + dev = dev_desc->dev; + printf("Loading file \"%s\" from %s device %d%c%c\n", + filename, argv[1], dev, + part ? ':' : ' ', part ? part + '0' : ' '); - if (part != 0) { - if (get_partition_info(zfs_dev_desc, part, &info)) { - printf("** Bad partition %lu **\n", part); - return 1; - } - - if (strncmp((char *)info.type, BOOT_PART_TYPE, - strlen(BOOT_PART_TYPE)) != 0) { - printf("** Invalid partition type \"%s\" (expect \"" BOOT_PART_TYPE "\")\n", - info.type); - return 1; - } - printf("Loading file \"%s\" " - "from %s device %d:%lu %s\n", - filename, argv[1], dev, part, info.name); - } else { - printf("Loading file \"%s\" from %s device %d\n", - filename, argv[1], dev); - } - - part_length = zfs_set_blk_dev(zfs_dev_desc, part); - if (part_length == 0) { - printf("**Bad partition - %s %d:%lu **\n", argv[1], dev, part); - return 1; - } - - vdev.part_length = part_length; + zfs_set_blk_dev(dev_desc, &info); + vdev.part_length = info.size; memset(&zfile, 0, sizeof(zfile)); zfile.device = &vdev; @@ -149,7 +117,7 @@ static int do_zfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) zfile.size = (uint64_t)count; if (zfs_read(&zfile, (char *)addr, zfile.size) != zfile.size) { - printf("** Unable to read \"%s\" from %s %d:%lu **\n", + printf("** Unable to read \"%s\" from %s %d:%d **\n", filename, argv[1], dev, part); zfs_close(&zfile); return 1; @@ -181,41 +149,23 @@ int zfs_print(const char *entry, const struct zfs_dirhook_info *data) static int do_zfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { const char *filename = "/"; - int dev; - unsigned long part = 1; - char *ep; - int part_length; + int part; + block_dev_desc_t *dev_desc; + disk_partition_t info; struct device_s vdev; - if (argc < 3) + if (argc < 2) return cmd_usage(cmdtp); - dev = (int)simple_strtoul(argv[2], &ep, 16); - zfs_dev_desc = get_dev(argv[1], dev); - - if (zfs_dev_desc == NULL) { - printf("\n** Block device %s %d not supported\n", argv[1], dev); - return 1; - } - - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = simple_strtoul(++ep, NULL, 16); - } - if (argc == 4) filename = argv[3]; - part_length = zfs_set_blk_dev(zfs_dev_desc, part); - if (part_length == 0) { - printf("** Bad partition - %s %d:%lu **\n", argv[1], dev, part); + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); + if (part < 0) return 1; - } - vdev.part_length = part_length; + zfs_set_blk_dev(dev_desc, &info); + vdev.part_length = info.size; zfs_ls(&vdev, filename, zfs_print); diff --git a/common/cmd_zip.c b/common/cmd_zip.c new file mode 100644 index 0000000..a73c86d --- /dev/null +++ b/common/cmd_zip.c @@ -0,0 +1,60 @@ +/* + * (C) Copyright 2012 + * Lei Wen <leiwen@marvell.com>, Marvell Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> + +static int do_zip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned long src, dst; + unsigned long src_len, dst_len = ~0UL; + char buf[32]; + + switch (argc) { + case 5: + dst_len = simple_strtoul(argv[4], NULL, 16); + /* fall through */ + case 4: + src = simple_strtoul(argv[1], NULL, 16); + src_len = simple_strtoul(argv[2], NULL, 16); + dst = simple_strtoul(argv[3], NULL, 16); + break; + default: + return cmd_usage(cmdtp); + } + + if (gzip((void *) dst, &dst_len, (void *) src, src_len) != 0) + return 1; + + printf("Compressed size: %ld = 0x%lX\n", dst_len, dst_len); + sprintf(buf, "%lX", dst_len); + setenv("filesize", buf); + + return 0; +} + +U_BOOT_CMD( + zip, 5, 1, do_zip, + "zip a memory region", + "srcaddr srcsize dstaddr [dstsize]" +); diff --git a/common/dlmalloc.c b/common/dlmalloc.c index c645d73..1d7e527 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1487,11 +1487,11 @@ static mbinptr av_[NAV * 2 + 2] = { #ifdef CONFIG_NEEDS_MANUAL_RELOC void malloc_bin_reloc (void) { - unsigned long *p = (unsigned long *)(&av_[2]); - int i; - for (i=2; i<(sizeof(av_)/sizeof(mbinptr)); ++i) { - *p++ += gd->reloc_off; - } + mbinptr *p = &av_[2]; + size_t i; + + for (i = 2; i < ARRAY_SIZE(av_); ++i, ++p) + *p = (mbinptr)((ulong)*p + gd->reloc_off); } #endif diff --git a/common/env_common.c b/common/env_common.c index d9e990d..3e46c26 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -80,6 +80,9 @@ const uchar default_environment[] = { #ifdef CONFIG_ETH5ADDR "eth5addr=" MK_STR(CONFIG_ETH5ADDR) "\0" #endif +#ifdef CONFIG_ETHPRIME + "ethprime=" CONFIG_ETHPRIME "\0" +#endif #ifdef CONFIG_IPADDR "ipaddr=" MK_STR(CONFIG_IPADDR) "\0" #endif @@ -133,7 +136,9 @@ const uchar default_environment[] = { "\0" }; -struct hsearch_data env_htab; +struct hsearch_data env_htab = { + .apply = env_check_apply, +}; static uchar __env_get_char_spec(int index) { @@ -175,6 +180,11 @@ const uchar *env_get_addr(int index) void set_default_env(const char *s) { + /* + * By default, do not apply changes as they will eventually + * be applied by someone else + */ + int do_apply = 0; if (sizeof(default_environment) > ENV_SIZE) { puts("*** Error - default environment is too large\n\n"); return; @@ -186,6 +196,14 @@ void set_default_env(const char *s) "using default environment\n\n", s + 1); } else { + /* + * This set_to_default was explicitly asked for + * by the user, as opposed to being a recovery + * mechanism. Therefore we check every single + * variable and apply changes to the system + * right away (e.g. baudrate, console). + */ + do_apply = 1; puts(s); } } else { @@ -193,12 +211,26 @@ void set_default_env(const char *s) } if (himport_r(&env_htab, (char *)default_environment, - sizeof(default_environment), '\0', 0) == 0) + sizeof(default_environment), '\0', 0, + 0, NULL, do_apply) == 0) error("Environment import failed: errno = %d\n", errno); gd->flags |= GD_FLG_ENV_READY; } + +/* [re]set individual variables to their value in the default environment */ +int set_default_vars(int nvars, char * const vars[]) +{ + /* + * Special use-case: import from default environment + * (and use \0 as a separator) + */ + return himport_r(&env_htab, (const char *)default_environment, + sizeof(default_environment), '\0', H_NOCLEAR, + nvars, vars, 1 /* do_apply */); +} + /* * Check if CRC is valid and (if yes) import the environment. * Note that "buf" may or may not be aligned. @@ -218,7 +250,8 @@ int env_import(const char *buf, int check) } } - if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) { + if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, + 0, NULL, 0 /* do_apply */)) { gd->flags |= GD_FLG_ENV_READY; return 1; } diff --git a/common/env_fat.c b/common/env_fat.c index bad92aa..6ef5318 100644 --- a/common/env_fat.c +++ b/common/env_fat.c @@ -40,11 +40,6 @@ env_t *env_ptr; DECLARE_GLOBAL_DATA_PTR; -uchar env_get_char_spec(int index) -{ - return *((uchar *)(gd->env_addr + index)); -} - int env_init(void) { /* use default */ @@ -63,6 +58,7 @@ int saveenv(void) block_dev_desc_t *dev_desc = NULL; int dev = FAT_ENV_DEVICE; int part = FAT_ENV_PART; + int err; res = (char *)&env_new.data; len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL); @@ -72,7 +68,7 @@ int saveenv(void) } #ifdef CONFIG_MMC - if (strcmp (FAT_ENV_INTERFACE, "mmc") == 0) { + if (strcmp(FAT_ENV_INTERFACE, "mmc") == 0) { struct mmc *mmc = find_mmc_device(dev); if (!mmc) { @@ -91,14 +87,17 @@ int saveenv(void) FAT_ENV_INTERFACE, dev); return 1; } - if (fat_register_device(dev_desc, part) != 0) { + + err = fat_register_device(dev_desc, part); + if (err) { printf("Failed to register %s%d:%d\n", FAT_ENV_INTERFACE, dev, part); return 1; } env_new.crc = crc32(0, env_new.data, ENV_SIZE); - if (file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t)) == -1) { + err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t)); + if (err == -1) { printf("\n** Unable to write \"%s\" from %s%d:%d **\n", FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part); return 1; @@ -115,9 +114,10 @@ void env_relocate_spec(void) block_dev_desc_t *dev_desc = NULL; int dev = FAT_ENV_DEVICE; int part = FAT_ENV_PART; + int err; #ifdef CONFIG_MMC - if (strcmp (FAT_ENV_INTERFACE, "mmc") == 0) { + if (strcmp(FAT_ENV_INTERFACE, "mmc") == 0) { struct mmc *mmc = find_mmc_device(dev); if (!mmc) { @@ -138,14 +138,17 @@ void env_relocate_spec(void) set_default_env(NULL); return; } - if (fat_register_device(dev_desc, part) != 0) { + + err = fat_register_device(dev_desc, part); + if (err) { printf("Failed to register %s%d:%d\n", FAT_ENV_INTERFACE, dev, part); set_default_env(NULL); return; } - if (file_fat_read(FAT_ENV_FILE, (unsigned char *)&buf, CONFIG_ENV_SIZE) == -1) { + err = file_fat_read(FAT_ENV_FILE, (uchar *)&buf, CONFIG_ENV_SIZE); + if (err == -1) { printf("\n** Unable to read \"%s\" from %s%d:%d **\n", FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part); set_default_env(NULL); diff --git a/common/env_nand.c b/common/env_nand.c index e8daec9..79e8033 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -226,7 +226,7 @@ int saveenv(void) int saveenv(void) { int ret = 0; - env_t env_new; + ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); ssize_t len; char *res; nand_erase_options_t nand_erase_options; @@ -238,20 +238,20 @@ int saveenv(void) if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE) return 1; - res = (char *)&env_new.data; + res = (char *)&env_new->data; len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); return 1; } - env_new.crc = crc32(0, env_new.data, ENV_SIZE); + env_new->crc = crc32(0, env_new->data, ENV_SIZE); puts("Erasing Nand...\n"); if (nand_erase_opts(&nand_info[0], &nand_erase_options)) return 1; puts("Writing to Nand... "); - if (writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new)) { + if (writeenv(CONFIG_ENV_OFFSET, (u_char *)env_new)) { puts("FAILED!\n"); return 1; } @@ -398,7 +398,7 @@ void env_relocate_spec(void) { #if !defined(ENV_IS_EMBEDDED) int ret; - char buf[CONFIG_ENV_SIZE]; + ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); #if defined(CONFIG_ENV_OFFSET_OOB) ret = get_nand_env_oob(&nand_info[0], &nand_env_oob_offset); diff --git a/common/env_remote.c b/common/env_remote.c index 3bf0f95..6c10c90 100644 --- a/common/env_remote.c +++ b/common/env_remote.c @@ -41,11 +41,6 @@ DECLARE_GLOBAL_DATA_PTR; #define CONFIG_ENV_OFFSET 0 #endif -uchar env_get_char_spec(int index) -{ - return *((uchar *)(gd->env_addr + index)); -} - int env_init(void) { if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { @@ -62,8 +57,8 @@ int env_init(void) #ifdef CONFIG_CMD_SAVEENV int saveenv(void) { -#ifdef CONFIG_SRIOBOOT_SLAVE - printf("Can not support the 'saveenv' when boot from SRIO!\n"); +#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE + printf("Can not support the 'saveenv' when boot from SRIO or PCIE!\n"); return 1; #else return 0; diff --git a/common/flash.c b/common/flash.c index 781cb9c..8244ba2 100644 --- a/common/flash.c +++ b/common/flash.c @@ -221,6 +221,9 @@ void flash_perror (int err) case ERR_PROG_ERROR: puts ("General Flash Programming Error\n"); break; + case ERR_ABORTED: + puts("Flash Programming Aborted\n"); + break; default: printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err); break; diff --git a/common/hush.c b/common/hush.c index 1eff182..4c84c2f 100644 --- a/common/hush.c +++ b/common/hush.c @@ -127,6 +127,7 @@ #endif #endif #define SPECIAL_VAR_SYMBOL 03 +#define SUBSTED_VAR_SYMBOL 04 #ifndef __U_BOOT__ #define FLAG_EXIT_FROM_LOOP 1 #define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */ @@ -499,6 +500,7 @@ static void remove_bg_job(struct pipe *pi); /* local variable support */ static char **make_list_in(char **inp, char *name); static char *insert_var_value(char *inp); +static char *insert_var_value_sub(char *inp, int tag_subst); #ifndef __U_BOOT__ /* Table of built-in functions. They can be forked or not, depending on @@ -2743,13 +2745,50 @@ static int parse_group(o_string *dest, struct p_context *ctx, static char *lookup_param(char *src) { char *p; + char *sep; + char *default_val = NULL; + int assign = 0; + int expand_empty = 0; if (!src) return NULL; - p = getenv(src); - if (!p) - p = get_local_var(src); + sep = strchr(src, ':'); + + if (sep) { + *sep = '\0'; + if (*(sep + 1) == '-') + default_val = sep+2; + if (*(sep + 1) == '=') { + default_val = sep+2; + assign = 1; + } + if (*(sep + 1) == '+') { + default_val = sep+2; + expand_empty = 1; + } + } + + p = getenv(src); + if (!p) + p = get_local_var(src); + + if (!p || strlen(p) == 0) { + p = default_val; + if (assign) { + char *var = malloc(strlen(src)+strlen(default_val)+2); + if (var) { + sprintf(var, "%s=%s", src, default_val); + set_local_var(var, 0); + } + free(var); + } + } else if (expand_empty) { + p += strlen(p); + } + + if (sep) + *sep = ':'; return p; } @@ -3051,6 +3090,21 @@ int parse_stream(o_string *dest, struct p_context *ctx, return 1; break; #endif + case SUBSTED_VAR_SYMBOL: + dest->nonnull = 1; + while (ch = b_getch(input), ch != EOF && + ch != SUBSTED_VAR_SYMBOL) { + debug_printf("subst, pass=%d\n", ch); + if (input->__promptme == 0) + return 1; + b_addchr(dest, ch); + } + debug_printf("subst, term=%d\n", ch); + if (ch == EOF) { + syntax(); + return 1; + } + break; default: syntax(); /* this is really an internal logic error */ return 1; @@ -3092,6 +3146,10 @@ void update_ifs_map(void) mapset((uchar *)"\\$'\"`", 3); /* never flow through */ mapset((uchar *)"<>;&|(){}#", 1); /* flow through if quoted */ #else + { + uchar subst[2] = {SUBSTED_VAR_SYMBOL, 0}; + mapset(subst, 3); /* never flow through */ + } mapset((uchar *)"\\$'\"", 3); /* never flow through */ mapset((uchar *)";&|#", 1); /* flow through if quoted */ #endif @@ -3431,25 +3489,57 @@ final_return: static char *insert_var_value(char *inp) { + return insert_var_value_sub(inp, 0); +} + +static char *insert_var_value_sub(char *inp, int tag_subst) +{ int res_str_len = 0; int len; int done = 0; char *p, *p1, *res_str = NULL; while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) { + /* check the beginning of the string for normal charachters */ if (p != inp) { + /* copy any charachters to the result string */ len = p - inp; res_str = xrealloc(res_str, (res_str_len + len)); strncpy((res_str + res_str_len), inp, len); res_str_len += len; } inp = ++p; + /* find the ending marker */ p = strchr(inp, SPECIAL_VAR_SYMBOL); *p = '\0'; + /* look up the value to substitute */ if ((p1 = lookup_param(inp))) { - len = res_str_len + strlen(p1); + if (tag_subst) + len = res_str_len + strlen(p1) + 2; + else + len = res_str_len + strlen(p1); res_str = xrealloc(res_str, (1 + len)); - strcpy((res_str + res_str_len), p1); + if (tag_subst) { + /* + * copy the variable value to the result + * string + */ + strcpy((res_str + res_str_len + 1), p1); + + /* + * mark the replaced text to be accepted as + * is + */ + res_str[res_str_len] = SUBSTED_VAR_SYMBOL; + res_str[res_str_len + 1 + strlen(p1)] = + SUBSTED_VAR_SYMBOL; + } else + /* + * copy the variable value to the result + * string + */ + strcpy((res_str + res_str_len), p1); + res_str_len = len; } *p = SPECIAL_VAR_SYMBOL; @@ -3513,9 +3603,14 @@ static char * make_string(char ** inp) char *str = NULL; int n; int len = 2; + char *noeval_str; + int noeval = 0; + noeval_str = get_local_var("HUSH_NO_EVAL"); + if (noeval_str != NULL && *noeval_str != '0' && *noeval_str != '\0') + noeval = 1; for (n = 0; inp[n]; n++) { - p = insert_var_value(inp[n]); + p = insert_var_value_sub(inp[n], noeval); str = xrealloc(str, (len + strlen(p))); if (n) { strcat(str, " "); diff --git a/common/image.c b/common/image.c index 91954ac..f084d2b 100644 --- a/common/image.c +++ b/common/image.c @@ -143,6 +143,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_INVALID, NULL, "Invalid Image", }, { IH_TYPE_MULTI, "multi", "Multi-File Image", }, { IH_TYPE_OMAPIMAGE, "omapimage", "TI OMAP SPL With GP CH",}, + { IH_TYPE_PBLIMAGE, "pblimage", "Freescale PBL Boot Image",}, { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, { IH_TYPE_SCRIPT, "script", "Script", }, { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, @@ -2042,13 +2043,13 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); } - if (type == IH_TYPE_KERNEL) { + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) { fit_image_get_os(fit, image_noffset, &os); printf("%s OS: %s\n", p, genimg_get_os_name(os)); } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || - (type == IH_TYPE_FIRMWARE)) { + (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) { ret = fit_image_get_load(fit, image_noffset, &load); printf("%s Load Address: ", p); if (ret) @@ -2057,7 +2058,8 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("0x%08lx\n", load); } - if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) { + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || + (type == IH_TYPE_RAMDISK)) { fit_image_get_entry(fit, image_noffset, &entry); printf("%s Entry Point: ", p); if (ret) diff --git a/common/lcd.c b/common/lcd.c index 506a138..b6be800 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -498,23 +498,43 @@ static int lcd_getbgcolor(void) /************************************************************************/ /* ** Chipset depending Bitmap / Logo stuff... */ /************************************************************************/ +static inline ushort *configuration_get_cmap(void) +{ +#if defined CONFIG_CPU_PXA + struct pxafb_info *fbi = &panel_info.pxa; + return (ushort *)fbi->palette; +#elif defined(CONFIG_MPC823) + immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + cpm8xx_t *cp = &(immr->im_cpm); + return (ushort *)&(cp->lcd_cmap[255 * sizeof(ushort)]); +#elif defined(CONFIG_ATMEL_LCD) + return (ushort *)(panel_info.mmio + ATMEL_LCDC_LUT(0)); +#elif !defined(CONFIG_ATMEL_HLCD) && !defined(CONFIG_EXYNOS_FB) + return panel_info.cmap; +#else +#if defined(CONFIG_LCD_LOGO) + return bmp_logo_palette; +#else + return NULL; +#endif +#endif +} + #ifdef CONFIG_LCD_LOGO void bitmap_plot(int x, int y) { #ifdef CONFIG_ATMEL_LCD - uint *cmap; + uint *cmap = (uint *)bmp_logo_palette; #else - ushort *cmap; + ushort *cmap = (ushort *)bmp_logo_palette; #endif ushort i, j; uchar *bmap; uchar *fb; ushort *fb16; -#if defined(CONFIG_CPU_PXA) - struct pxafb_info *fbi = &panel_info.pxa; -#elif defined(CONFIG_MPC823) - volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; - volatile cpm8xx_t *cp = &(immr->im_cpm); +#if defined(CONFIG_MPC823) + immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + cpm8xx_t *cp = &(immr->im_cpm); #endif debug("Logo: width %d height %d colors %d cmap %d\n", @@ -525,20 +545,17 @@ void bitmap_plot(int x, int y) fb = (uchar *)(lcd_base + y * lcd_line_length + x); if (NBITS(panel_info.vl_bpix) < 12) { - /* Leave room for default color map */ -#if defined(CONFIG_CPU_PXA) - cmap = (ushort *) fbi->palette; -#elif defined(CONFIG_MPC823) + /* Leave room for default color map + * default case: generic system with no cmap (most likely 16bpp) + * cmap was set to the source palette, so no change is done. + * This avoids even more ifdefs in the next stanza + */ +#if defined(CONFIG_MPC823) cmap = (ushort *) &(cp->lcd_cmap[BMP_LOGO_OFFSET * sizeof(ushort)]); #elif defined(CONFIG_ATMEL_LCD) - cmap = (uint *) (panel_info.mmio + ATMEL_LCDC_LUT(0)); + cmap = (uint *)configuration_get_cmap(); #else - /* - * default case: generic system with no cmap (most likely 16bpp) - * We set cmap to the source palette, so no change is done. - * This avoids even more ifdef in the next stanza - */ - cmap = bmp_logo_palette; + cmap = configuration_get_cmap(); #endif WATCHDOG_RESET(); @@ -607,7 +624,46 @@ static inline void bitmap_plot(int x, int y) {} #ifdef CONFIG_SPLASH_SCREEN_ALIGN #define BMP_ALIGN_CENTER 0x7FFF + +static void splash_align_axis(int *axis, unsigned long panel_size, + unsigned long picture_size) +{ + unsigned long panel_picture_delta = panel_size - picture_size; + unsigned long axis_alignment; + + if (*axis == BMP_ALIGN_CENTER) + axis_alignment = panel_picture_delta / 2; + else if (*axis < 0) + axis_alignment = panel_picture_delta + *axis + 1; + else + return; + + *axis = max(0, axis_alignment); +} +#endif + +#if defined(CONFIG_MPC823) || defined(CONFIG_MCC200) +#define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++) +#else +#define FB_PUT_BYTE(fb, from) *(fb)++ = *(from)++ +#endif + +#if defined(CONFIG_BMP_16BPP) +#if defined(CONFIG_ATMEL_LCD_BGR555) +static inline void fb_put_word(uchar **fb, uchar **from) +{ + *(*fb)++ = (((*from)[0] & 0x1f) << 2) | ((*from)[1] & 0x03); + *(*fb)++ = ((*from)[0] & 0xe0) | (((*from)[1] & 0x7c) >> 2); + *from += 2; +} +#else +static inline void fb_put_word(uchar **fb, uchar **from) +{ + *(*fb)++ = *(*from)++; + *(*fb)++ = *(*from)++; +} #endif +#endif /* CONFIG_BMP_16BPP */ int lcd_display_bitmap(ulong bmp_image, int x, int y) { @@ -623,14 +679,8 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) unsigned long width, height, byte_width; unsigned long pwidth = panel_info.vl_col; unsigned colors, bpix, bmp_bpix; -#if defined(CONFIG_CPU_PXA) - struct pxafb_info *fbi = &panel_info.pxa; -#elif defined(CONFIG_MPC823) - volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; - volatile cpm8xx_t *cp = &(immr->im_cpm); -#endif - if (!((bmp->header.signature[0] == 'B') && + if (!bmp || !((bmp->header.signature[0] == 'B') && (bmp->header.signature[1] == 'M'))) { printf("Error: no valid bmp image at %lx\n", bmp_image); @@ -666,14 +716,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) #if !defined(CONFIG_MCC200) /* MCC200 LCD doesn't need CMAP, supports 1bpp b&w only */ if (bmp_bpix == 8) { -#if defined(CONFIG_CPU_PXA) - cmap = (ushort *)fbi->palette; -#elif defined(CONFIG_MPC823) - cmap = (ushort *)&(cp->lcd_cmap[255*sizeof(ushort)]); -#elif !defined(CONFIG_ATMEL_LCD) && !defined(CONFIG_EXYNOS_FB) - cmap = panel_info.cmap; -#endif - + cmap = configuration_get_cmap(); cmap_base = cmap; /* Set color map */ @@ -722,15 +765,8 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) padded_line = (width&0x3) ? ((width&~0x3)+4) : (width); #ifdef CONFIG_SPLASH_SCREEN_ALIGN - if (x == BMP_ALIGN_CENTER) - x = max(0, (pwidth - width) / 2); - else if (x < 0) - x = max(0, pwidth - width + x + 1); - - if (y == BMP_ALIGN_CENTER) - y = max(0, (panel_info.vl_row - height) / 2); - else if (y < 0) - y = max(0, panel_info.vl_row - height + y + 1); + splash_align_axis(&x, pwidth, width); + splash_align_axis(&y, panel_info.vl_row, height); #endif /* CONFIG_SPLASH_SCREEN_ALIGN */ if ((x + width) > pwidth) @@ -754,11 +790,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) WATCHDOG_RESET(); for (j = 0; j < width; j++) { if (bpix != 16) { -#if defined(CONFIG_CPU_PXA) || defined(CONFIG_ATMEL_LCD) - *(fb++) = *(bmap++); -#elif defined(CONFIG_MPC823) || defined(CONFIG_MCC200) - *(fb++) = 255 - *(bmap++); -#endif + FB_PUT_BYTE(fb, bmap); } else { *(uint16_t *)fb = cmap_base[*(bmap++)]; fb += sizeof(uint16_t) / sizeof(*fb); @@ -773,18 +805,9 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) case 16: for (i = 0; i < height; ++i) { WATCHDOG_RESET(); - for (j = 0; j < width; j++) { -#if defined(CONFIG_ATMEL_LCD_BGR555) - *(fb++) = ((bmap[0] & 0x1f) << 2) | - (bmap[1] & 0x03); - *(fb++) = (bmap[0] & 0xe0) | - ((bmap[1] & 0x7c) >> 2); - bmap += 2; -#else - *(fb++) = *(bmap++); - *(fb++) = *(bmap++); -#endif - } + for (j = 0; j < width; j++) + fb_put_word(&fb, &bmap); + bmap += (padded_line - width) * 2; fb -= (width * 2 + lcd_line_length); } @@ -842,17 +865,7 @@ static void *lcd_logo(void) } #endif /* CONFIG_SPLASH_SCREEN_ALIGN */ -#ifdef CONFIG_VIDEO_BMP_GZIP - bmp_image_t *bmp = (bmp_image_t *)addr; - unsigned long len; - - if (!((bmp->header.signature[0] == 'B') && - (bmp->header.signature[1] == 'M'))) { - addr = (ulong)gunzip_bmp(addr, &len); - } -#endif - - if (lcd_display_bitmap(addr, x, y) == 0) + if (bmp_display(addr, x, y) == 0) return (void *)lcd_base; } #endif /* CONFIG_SPLASH_SCREEN */ diff --git a/common/spl/Makefile b/common/spl/Makefile new file mode 100644 index 0000000..7cf01ad --- /dev/null +++ b/common/spl/Makefile @@ -0,0 +1,39 @@ +# +# (C) Copyright 2012 +# Texas Instruments Incorporated - http://www.ti.com/ +# Aneesh V <aneesh@ti.com> +# +# This file is released under the terms of GPL v2 and any later version. +# See the file COPYING in the root directory of the source tree for details. +# +# Based on common/Makefile. +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)libspl.o + +ifdef CONFIG_SPL_BUILD +COBJS-$(CONFIG_SPL_FRAMEWORK) += spl.o +COBJS-$(CONFIG_SPL_NOR_SUPPORT) += spl_nor.o +COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += spl_ymodem.o +COBJS-$(CONFIG_SPL_NAND_SUPPORT) += spl_nand.o +endif + +COBJS := $(sort $(COBJS-y)) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/common/spl/spl.c b/common/spl/spl.c new file mode 100644 index 0000000..c640f87 --- /dev/null +++ b/common/spl/spl.c @@ -0,0 +1,237 @@ +/* + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Aneesh V <aneesh@ti.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <spl.h> +#include <asm/u-boot.h> +#include <nand.h> +#include <fat.h> +#include <version.h> +#include <i2c.h> +#include <image.h> +#include <malloc.h> +#include <linux/compiler.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_UBOOT_START +#define CONFIG_SYS_UBOOT_START CONFIG_SYS_TEXT_BASE +#endif +#ifndef CONFIG_SYS_MONITOR_LEN +#define CONFIG_SYS_MONITOR_LEN (200 * 1024) +#endif + +u32 *boot_params_ptr = NULL; +struct spl_image_info spl_image; + +/* Define board data structure */ +static bd_t bdata __attribute__ ((section(".data"))); + +inline void hang(void) +{ + puts("### ERROR ### Please RESET the board ###\n"); + for (;;) + ; +} + +/* + * Default function to determine if u-boot or the OS should + * be started. This implementation always returns 1. + * + * Please implement your own board specific funcion to do this. + * + * RETURN + * 0 to not start u-boot + * positive if u-boot should start + */ +#ifdef CONFIG_SPL_OS_BOOT +__weak int spl_start_uboot(void) +{ + puts("SPL: Please implement spl_start_uboot() for your board\n"); + puts("SPL: Direct Linux boot not active!\n"); + return 1; +} +#endif + +void spl_parse_image_header(const struct image_header *header) +{ + u32 header_size = sizeof(struct image_header); + + if (image_get_magic(header) == IH_MAGIC) { + if (spl_image.flags & SPL_COPY_PAYLOAD_ONLY) { + /* + * On some system (e.g. powerpc), the load-address and + * entry-point is located at address 0. We can't load + * to 0-0x40. So skip header in this case. + */ + spl_image.load_addr = image_get_load(header); + spl_image.entry_point = image_get_ep(header); + spl_image.size = image_get_data_size(header); + } else { + spl_image.entry_point = image_get_load(header); + /* Load including the header */ + spl_image.load_addr = spl_image.entry_point - + header_size; + spl_image.size = image_get_data_size(header) + + header_size; + } + spl_image.os = image_get_os(header); + spl_image.name = image_get_name(header); + debug("spl: payload image: %s load addr: 0x%x size: %d\n", + spl_image.name, spl_image.load_addr, spl_image.size); + } else { + /* Signature not found - assume u-boot.bin */ + debug("mkimage signature not found - ih_magic = %x\n", + header->ih_magic); + /* Let's assume U-Boot will not be more than 200 KB */ + spl_image.size = CONFIG_SYS_MONITOR_LEN; + spl_image.entry_point = CONFIG_SYS_UBOOT_START; + spl_image.load_addr = CONFIG_SYS_TEXT_BASE; + spl_image.os = IH_OS_U_BOOT; + spl_image.name = "U-Boot"; + } +} + +static void __noreturn jump_to_image_no_args(void) +{ + typedef void __noreturn (*image_entry_noargs_t)(u32 *); + image_entry_noargs_t image_entry = + (image_entry_noargs_t) spl_image.entry_point; + + debug("image entry point: 0x%X\n", spl_image.entry_point); + /* Pass the saved boot_params from rom code */ +#if defined(CONFIG_VIRTIO) || defined(CONFIG_ZEBU) + image_entry = (image_entry_noargs_t)0x80100000; +#endif + u32 boot_params_ptr_addr = (u32)&boot_params_ptr; + image_entry((u32 *)boot_params_ptr_addr); +} + +#ifdef CONFIG_SPL_RAM_DEVICE +static void spl_ram_load_image(void) +{ + const struct image_header *header; + + /* + * Get the header. It will point to an address defined by handoff + * which will tell where the image located inside the flash. For + * now, it will temporary fixed to address pointed by U-Boot. + */ + header = (struct image_header *) + (CONFIG_SYS_TEXT_BASE - sizeof(struct image_header)); + + spl_parse_image_header(header); +} +#endif + +void board_init_r(gd_t *dummy1, ulong dummy2) +{ + u32 boot_device; + debug(">>spl:board_init_r()\n"); + +#ifdef CONFIG_SYS_SPL_MALLOC_START + mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START, + CONFIG_SYS_SPL_MALLOC_SIZE); +#endif + +#ifdef CONFIG_SPL_BOARD_INIT + spl_board_init(); +#endif + + boot_device = spl_boot_device(); + debug("boot device - %d\n", boot_device); + switch (boot_device) { +#ifdef CONFIG_SPL_RAM_DEVICE + case BOOT_DEVICE_RAM: + spl_ram_load_image(); + break; +#endif +#ifdef CONFIG_SPL_MMC_SUPPORT + case BOOT_DEVICE_MMC1: + case BOOT_DEVICE_MMC2: + case BOOT_DEVICE_MMC2_2: + spl_mmc_load_image(); + break; +#endif +#ifdef CONFIG_SPL_NAND_SUPPORT + case BOOT_DEVICE_NAND: + spl_nand_load_image(); + break; +#endif +#ifdef CONFIG_SPL_NOR_SUPPORT + case BOOT_DEVICE_NOR: + spl_nor_load_image(); + break; +#endif +#ifdef CONFIG_SPL_YMODEM_SUPPORT + case BOOT_DEVICE_UART: + spl_ymodem_load_image(); + break; +#endif +#ifdef CONFIG_SPL_SPI_SUPPORT + case BOOT_DEVICE_SPI: + spl_spi_load_image(); + break; +#endif + default: + debug("SPL: Un-supported Boot Device\n"); + hang(); + } + + switch (spl_image.os) { + case IH_OS_U_BOOT: + debug("Jumping to U-Boot\n"); + break; +#ifdef CONFIG_SPL_OS_BOOT + case IH_OS_LINUX: + debug("Jumping to Linux\n"); + spl_board_prepare_for_linux(); + jump_to_image_linux((void *)CONFIG_SYS_SPL_ARGS_ADDR); +#endif + default: + debug("Unsupported OS image.. Jumping nevertheless..\n"); + } + jump_to_image_no_args(); +} + +/* + * This requires UART clocks to be enabled. In order for this to work the + * caller must ensure that the gd pointer is valid. + */ +void preloader_console_init(void) +{ + gd->bd = &bdata; + gd->flags |= GD_FLG_RELOC; + gd->baudrate = CONFIG_BAUDRATE; + + serial_init(); /* serial communications setup */ + + gd->have_console = 1; + + puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \ + U_BOOT_TIME ")\n"); +#ifdef CONFIG_SPL_DISPLAY_PRINT + spl_display_print(); +#endif +} diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c new file mode 100644 index 0000000..61de5a4 --- /dev/null +++ b/common/spl/spl_nand.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <config.h> +#include <spl.h> +#include <asm/io.h> +#include <nand.h> + +void spl_nand_load_image(void) +{ + struct image_header *header; + int *src __attribute__((unused)); + int *dst __attribute__((unused)); + + debug("spl: nand - using hw ecc\n"); + nand_init(); + + /*use CONFIG_SYS_TEXT_BASE as temporary storage area */ + header = (struct image_header *)(CONFIG_SYS_TEXT_BASE); +#ifdef CONFIG_SPL_OS_BOOT + if (!spl_start_uboot()) { + /* + * load parameter image + * load to temp position since nand_spl_load_image reads + * a whole block which is typically larger than + * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite + * following sections like BSS + */ + nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS, + CONFIG_CMD_SPL_WRITE_SIZE, + (void *)CONFIG_SYS_TEXT_BASE); + /* copy to destintion */ + for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR, + src = (int *)CONFIG_SYS_TEXT_BASE; + src < (int *)(CONFIG_SYS_TEXT_BASE + + CONFIG_CMD_SPL_WRITE_SIZE); + src++, dst++) { + writel(readl(src), dst); + } + + /* load linux */ + nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS, + CONFIG_SYS_NAND_PAGE_SIZE, (void *)header); + spl_parse_image_header(header); + if (header->ih_os == IH_OS_LINUX) { + /* happy - was a linux */ + nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS, + spl_image.size, (void *)spl_image.load_addr); + nand_deselect(); + return; + } else { + puts("The Expected Linux image was not " + "found. Please check your NAND " + "configuration.\n"); + puts("Trying to start u-boot now...\n"); + } + } +#endif +#ifdef CONFIG_NAND_ENV_DST + nand_spl_load_image(CONFIG_ENV_OFFSET, + CONFIG_SYS_NAND_PAGE_SIZE, (void *)header); + spl_parse_image_header(header); + nand_spl_load_image(CONFIG_ENV_OFFSET, spl_image.size, + (void *)spl_image.load_addr); +#ifdef CONFIG_ENV_OFFSET_REDUND + nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, + CONFIG_SYS_NAND_PAGE_SIZE, (void *)header); + spl_parse_image_header(header); + nand_spl_load_image(CONFIG_ENV_OFFSET_REDUND, spl_image.size, + (void *)spl_image.load_addr); +#endif +#endif + /* Load u-boot */ + nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, + CONFIG_SYS_NAND_PAGE_SIZE, (void *)header); + spl_parse_image_header(header); + nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS, + spl_image.size, (void *)spl_image.load_addr); + nand_deselect(); +} diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c new file mode 100644 index 0000000..976e865 --- /dev/null +++ b/common/spl/spl_nor.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 Stefan Roese <sr@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <spl.h> + +void spl_nor_load_image(void) +{ + /* + * Loading of the payload to SDRAM is done with skipping of + * the mkimage header in this SPL NOR driver + */ + spl_image.flags |= SPL_COPY_PAYLOAD_ONLY; + + if (spl_start_uboot()) { + /* + * Load real U-Boot from its location in NOR flash to its + * defined location in SDRAM + */ + spl_parse_image_header( + (const struct image_header *)CONFIG_SYS_UBOOT_BASE); + + memcpy((void *)spl_image.load_addr, + (void *)(CONFIG_SYS_UBOOT_BASE + + sizeof(struct image_header)), + spl_image.size); + } else { + /* + * Load Linux from its location in NOR flash to its defined + * location in SDRAM + */ + spl_parse_image_header( + (const struct image_header *)CONFIG_SYS_OS_BASE); + + memcpy((void *)spl_image.load_addr, + (void *)(CONFIG_SYS_OS_BASE + + sizeof(struct image_header)), + spl_image.size); + + /* + * Copy DT blob (fdt) to SDRAM. Passing pointer to flash + * doesn't work (16 KiB should be enough for DT) + */ + memcpy((void *)CONFIG_SYS_SPL_ARGS_ADDR, + (void *)(CONFIG_SYS_FDT_BASE), + (16 << 10)); + } +} diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c new file mode 100644 index 0000000..40e5035 --- /dev/null +++ b/common/spl/spl_ymodem.c @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2011 + * Texas Instruments, <www.ti.com> + * + * Matt Porter <mporter@ti.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <spl.h> +#include <xyzModem.h> +#include <asm/u-boot.h> +#include <asm/utils.h> + +#define BUF_SIZE 1024 + +static int getcymodem(void) { + if (tstc()) + return (getc()); + return -1; +} + +void spl_ymodem_load_image(void) +{ + int size = 0; + int err; + int res; + int ret; + connection_info_t info; + char buf[BUF_SIZE]; + ulong store_addr = ~0; + ulong addr = 0; + + info.mode = xyzModem_ymodem; + ret = xyzModem_stream_open(&info, &err); + + if (!ret) { + while ((res = + xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) { + if (addr == 0) + spl_parse_image_header((struct image_header *)buf); + store_addr = addr + spl_image.load_addr; + size += res; + addr += res; + memcpy((char *)(store_addr), buf, res); + } + } else { + printf("spl: ymodem err - %s\n", xyzModem_error(err)); + hang(); + } + + xyzModem_stream_close(&err); + xyzModem_stream_terminate(false, &getcymodem); + + printf("Loaded %d bytes\n", size); +} diff --git a/common/usb_hub.c b/common/usb_hub.c index f35ad95..32750e8 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -43,6 +43,7 @@ #include <common.h> #include <command.h> #include <asm/processor.h> +#include <asm/unaligned.h> #include <linux/ctype.h> #include <asm/byteorder.h> #include <asm/unaligned.h> @@ -269,6 +270,7 @@ static int usb_hub_configure(struct usb_device *dev) int i; ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, USB_BUFSIZ); unsigned char *bitmap; + short hubCharacteristics; struct usb_hub_descriptor *descriptor; struct usb_hub_device *hub; #ifdef USB_HUB_DEBUG @@ -304,8 +306,9 @@ static int usb_hub_configure(struct usb_device *dev) } memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength); /* adjust 16bit values */ - hub->desc.wHubCharacteristics = - le16_to_cpu(descriptor->wHubCharacteristics); + put_unaligned(le16_to_cpu(get_unaligned( + &descriptor->wHubCharacteristics)), + &hub->desc.wHubCharacteristics); /* set the bitmap */ bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0]; /* devices not removable by default */ @@ -322,7 +325,8 @@ static int usb_hub_configure(struct usb_device *dev) dev->maxchild = descriptor->bNbrPorts; USB_HUB_PRINTF("%d ports detected\n", dev->maxchild); - switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) { + hubCharacteristics = get_unaligned(&hub->desc.wHubCharacteristics); + switch (hubCharacteristics & HUB_CHAR_LPSM) { case 0x00: USB_HUB_PRINTF("ganged power switching\n"); break; @@ -335,12 +339,12 @@ static int usb_hub_configure(struct usb_device *dev) break; } - if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND) + if (hubCharacteristics & HUB_CHAR_COMPOUND) USB_HUB_PRINTF("part of a compound device\n"); else USB_HUB_PRINTF("standalone hub\n"); - switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) { + switch (hubCharacteristics & HUB_CHAR_OCPM) { case 0x00: USB_HUB_PRINTF("global over-current protection\n"); break; diff --git a/common/usb_storage.c b/common/usb_storage.c index bdc306f..4aeed82 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -136,6 +136,7 @@ struct us_data { struct usb_device *pusb_dev; /* this usb_device */ unsigned int flags; /* from filter initially */ +# define USB_READY (1 << 0) unsigned char ifnum; /* interface number */ unsigned char ep_in; /* in endpoint */ unsigned char ep_out; /* out ....... */ @@ -155,11 +156,16 @@ struct us_data { trans_cmnd transport; /* transport routine */ }; +#ifdef CONFIG_USB_EHCI /* - * The U-Boot EHCI driver cannot handle more than 5 page aligned buffers - * of 4096 bytes in a transfer without running itself out of qt_buffers + * The U-Boot EHCI driver can handle any transfer length as long as there is + * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are + * limited to 65535 blocks. */ -#define USB_MAX_XFER_BLK(start, blksz) (((4096 * 5) - (start % 4096)) / blksz) +#define USB_MAX_XFER_BLK 65535 +#else +#define USB_MAX_XFER_BLK 20 +#endif static struct us_data usb_stor[USB_MAX_STOR_DEV]; @@ -693,7 +699,8 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us) usb_stor_BBB_reset(us); return USB_STOR_TRANSPORT_FAILED; } - mdelay(5); + if (!(us->flags & USB_READY)) + mdelay(5); pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out); /* DATA phase + error handling */ @@ -958,8 +965,10 @@ static int usb_test_unit_ready(ccb *srb, struct us_data *ss) srb->cmd[1] = srb->lun << 5; srb->datalen = 0; srb->cmdlen = 12; - if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) + if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) { + ss->flags |= USB_READY; return 0; + } usb_request_sense(srb, ss); mdelay(100); } while (retries--); @@ -1046,7 +1055,7 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor, unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer) { - unsigned long start, blks, buf_addr, max_xfer_blk; + unsigned long start, blks, buf_addr; unsigned short smallblks; struct usb_device *dev; struct us_data *ss; @@ -1074,12 +1083,6 @@ unsigned long usb_stor_read(int device, unsigned long blknr, buf_addr = (unsigned long)buffer; start = blknr; blks = blkcnt; - if (usb_test_unit_ready(srb, ss)) { - printf("Device NOT ready\n Request Sense returned %02X %02X" - " %02X\n", srb->sense_buf[2], srb->sense_buf[12], - srb->sense_buf[13]); - return 0; - } USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx" " buffer %lx\n", device, start, blks, buf_addr); @@ -1088,14 +1091,12 @@ unsigned long usb_stor_read(int device, unsigned long blknr, /* XXX need some comment here */ retry = 2; srb->pdata = (unsigned char *)buf_addr; - max_xfer_blk = USB_MAX_XFER_BLK(buf_addr, - usb_dev_desc[device].blksz); - if (blks > max_xfer_blk) - smallblks = (unsigned short) max_xfer_blk; + if (blks > USB_MAX_XFER_BLK) + smallblks = USB_MAX_XFER_BLK; else smallblks = (unsigned short) blks; retry_it: - if (smallblks == max_xfer_blk) + if (smallblks == USB_MAX_XFER_BLK) usb_show_progress(); srb->datalen = usb_dev_desc[device].blksz * smallblks; srb->pdata = (unsigned char *)buf_addr; @@ -1111,12 +1112,13 @@ retry_it: blks -= smallblks; buf_addr += srb->datalen; } while (blks != 0); + ss->flags &= ~USB_READY; USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n", start, smallblks, buf_addr); usb_disable_asynch(0); /* asynch transfer allowed */ - if (blkcnt >= max_xfer_blk) + if (blkcnt >= USB_MAX_XFER_BLK) debug("\n"); return blkcnt; } @@ -1124,7 +1126,7 @@ retry_it: unsigned long usb_stor_write(int device, unsigned long blknr, unsigned long blkcnt, const void *buffer) { - unsigned long start, blks, buf_addr, max_xfer_blk; + unsigned long start, blks, buf_addr; unsigned short smallblks; struct usb_device *dev; struct us_data *ss; @@ -1153,12 +1155,6 @@ unsigned long usb_stor_write(int device, unsigned long blknr, buf_addr = (unsigned long)buffer; start = blknr; blks = blkcnt; - if (usb_test_unit_ready(srb, ss)) { - printf("Device NOT ready\n Request Sense returned %02X %02X" - " %02X\n", srb->sense_buf[2], srb->sense_buf[12], - srb->sense_buf[13]); - return 0; - } USB_STOR_PRINTF("\nusb_write: dev %d startblk %lx, blccnt %lx" " buffer %lx\n", device, start, blks, buf_addr); @@ -1169,14 +1165,12 @@ unsigned long usb_stor_write(int device, unsigned long blknr, */ retry = 2; srb->pdata = (unsigned char *)buf_addr; - max_xfer_blk = USB_MAX_XFER_BLK(buf_addr, - usb_dev_desc[device].blksz); - if (blks > max_xfer_blk) - smallblks = (unsigned short) max_xfer_blk; + if (blks > USB_MAX_XFER_BLK) + smallblks = USB_MAX_XFER_BLK; else smallblks = (unsigned short) blks; retry_it: - if (smallblks == max_xfer_blk) + if (smallblks == USB_MAX_XFER_BLK) usb_show_progress(); srb->datalen = usb_dev_desc[device].blksz * smallblks; srb->pdata = (unsigned char *)buf_addr; @@ -1192,12 +1186,13 @@ retry_it: blks -= smallblks; buf_addr += srb->datalen; } while (blks != 0); + ss->flags &= ~USB_READY; USB_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n", start, smallblks, buf_addr); usb_disable_asynch(0); /* asynch transfer allowed */ - if (blkcnt >= max_xfer_blk) + if (blkcnt >= USB_MAX_XFER_BLK) debug("\n"); return blkcnt; @@ -1403,6 +1398,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, cap[0] = 2880; cap[1] = 0x200; } + ss->flags &= ~USB_READY; USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0], cap[1]); #if 0 |