diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile | 3 | ||||
-rw-r--r-- | common/bouncebuf.c | 75 | ||||
-rw-r--r-- | common/cmd_bmp.c | 5 | ||||
-rw-r--r-- | common/cmd_bootm.c | 11 | ||||
-rw-r--r-- | common/cmd_led.c | 6 | ||||
-rw-r--r-- | common/cmd_mmc.c | 11 | ||||
-rw-r--r-- | common/cmd_nand.c | 22 | ||||
-rw-r--r-- | common/cmd_usb.c | 2 | ||||
-rw-r--r-- | common/image.c | 127 | ||||
-rw-r--r-- | common/lcd.c | 178 | ||||
-rw-r--r-- | common/main.c | 104 | ||||
-rw-r--r-- | common/spl/spl.c | 16 | ||||
-rw-r--r-- | common/stdio.c | 4 | ||||
-rw-r--r-- | common/usb.c | 4 | ||||
-rw-r--r-- | common/usb_kbd.c | 18 |
15 files changed, 528 insertions, 58 deletions
diff --git a/common/Makefile b/common/Makefile index ded6318dc6..132b3bd79c 100644 --- a/common/Makefile +++ b/common/Makefile @@ -196,6 +196,9 @@ COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o endif ifdef CONFIG_SPL_BUILD +COBJS-y += cmd_nvedit.o +COBJS-y += env_common.o +COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o COBJS-$(CONFIG_SPL_NET_SUPPORT) += cmd_nvedit.o COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_common.o diff --git a/common/bouncebuf.c b/common/bouncebuf.c index 4f827f893d..1df12cdda0 100644 --- a/common/bouncebuf.c +++ b/common/bouncebuf.c @@ -27,21 +27,19 @@ #include <errno.h> #include <bouncebuf.h> -static int addr_aligned(void *data, size_t len) +static int addr_aligned(struct bounce_buffer *state) { const ulong align_mask = ARCH_DMA_MINALIGN - 1; /* Check if start is aligned */ - if ((ulong)data & align_mask) { - debug("Unaligned start address %p\n", data); + if ((ulong)state->user_buffer & align_mask) { + debug("Unaligned buffer address %p\n", state->user_buffer); return 0; } - data += len; - - /* Check if end is aligned */ - if ((ulong)data & align_mask) { - debug("Unaligned end address %p\n", data); + /* Check if length is aligned */ + if (state->len != state->len_aligned) { + debug("Unaligned buffer length %d\n", state->len); return 0; } @@ -49,44 +47,53 @@ static int addr_aligned(void *data, size_t len) return 1; } -int bounce_buffer_start(void **data, size_t len, void **backup, uint8_t flags) +int bounce_buffer_start(struct bounce_buffer *state, void *data, + size_t len, unsigned int flags) { - void *tmp; - size_t alen; - - if (addr_aligned(*data, len)) { - *backup = NULL; - return 0; + state->user_buffer = data; + state->bounce_buffer = data; + state->len = len; + state->len_aligned = roundup(len, ARCH_DMA_MINALIGN); + state->flags = flags; + + if (!addr_aligned(state)) { + state->bounce_buffer = memalign(ARCH_DMA_MINALIGN, + state->len_aligned); + if (!state->bounce_buffer) + return -ENOMEM; + + if (state->flags & GEN_BB_READ) + memcpy(state->bounce_buffer, state->user_buffer, + state->len); } - alen = roundup(len, ARCH_DMA_MINALIGN); - tmp = memalign(ARCH_DMA_MINALIGN, alen); - - if (!tmp) - return -ENOMEM; - - if (flags & GEN_BB_READ) - memcpy(tmp, *data, len); - - *backup = *data; - *data = tmp; + /* + * Flush data to RAM so DMA reads can pick it up, + * and any CPU writebacks don't race with DMA writes + */ + flush_dcache_range((unsigned long)state->bounce_buffer, + (unsigned long)(state->bounce_buffer) + + state->len_aligned); return 0; } -int bounce_buffer_stop(void **data, size_t len, void **backup, uint8_t flags) +int bounce_buffer_stop(struct bounce_buffer *state) { - void *tmp = *data; + if (state->flags & GEN_BB_WRITE) { + /* Invalidate cache so that CPU can see any newly DMA'd data */ + invalidate_dcache_range((unsigned long)state->bounce_buffer, + (unsigned long)(state->bounce_buffer) + + state->len_aligned); + } - /* The buffer was already aligned, since "backup" is NULL. */ - if (!*backup) + if (state->bounce_buffer == state->user_buffer) return 0; - if (flags & GEN_BB_WRITE) - memcpy(*backup, *data, len); + if (state->flags & GEN_BB_WRITE) + memcpy(state->user_buffer, state->bounce_buffer, state->len); - *data = *backup; - free(tmp); + free(state->bounce_buffer); return 0; } diff --git a/common/cmd_bmp.c b/common/cmd_bmp.c index b8809e3bf5..5a52edde31 100644 --- a/common/cmd_bmp.c +++ b/common/cmd_bmp.c @@ -31,6 +31,7 @@ #include <command.h> #include <asm/byteorder.h> #include <malloc.h> +#include <video.h> static int bmp_info (ulong addr); @@ -238,9 +239,7 @@ int bmp_display(ulong addr, int x, int y) #if defined(CONFIG_LCD) ret = lcd_display_bitmap((ulong)bmp, x, y); #elif defined(CONFIG_VIDEO) - extern int video_display_bitmap (ulong, int, int); - - ret = video_display_bitmap ((unsigned long)bmp, x, y); + ret = video_display_bitmap((unsigned long)bmp, x, y); #else # error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO #endif diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index d256ddfaa6..4dbe952bb0 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -949,8 +949,19 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, * node */ bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); +#ifdef CONFIG_FIT_BEST_MATCH + if (fit_uname_config) + cfg_noffset = + fit_conf_get_node(fit_hdr, + fit_uname_config); + else + cfg_noffset = + fit_conf_find_compat(fit_hdr, + gd->fdt_blob); +#else cfg_noffset = fit_conf_get_node(fit_hdr, fit_uname_config); +#endif if (cfg_noffset < 0) { bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME); return NULL; diff --git a/common/cmd_led.c b/common/cmd_led.c index d83b3ba69b..7f5ab43c7f 100644 --- a/common/cmd_led.c +++ b/common/cmd_led.c @@ -140,7 +140,7 @@ int do_led (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( led, 3, 1, do_led, - "led\t- [" + "[" #ifdef CONFIG_BOARD_SPECIFIC_LED #ifdef STATUS_LED_BIT "0|" @@ -167,6 +167,6 @@ U_BOOT_CMD( #ifdef STATUS_LED_BLUE "blue|" #endif - "all] [on|off|toggle]\n", - "led [led_name] [on|off|toggle] sets or clears led(s)\n" + "all] [on|off|toggle]", + "[led_name] [on|off|toggle] sets or clears led(s)" ); diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index 62a1c224d3..7dacd5114c 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -144,7 +144,7 @@ static 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", - "- dislay info of the current MMC device" + "- display info of the current MMC device" ); static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) @@ -250,14 +250,13 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } - if (strcmp(argv[1], "read") == 0) + state = MMC_INVALID; + if (argc == 5 && strcmp(argv[1], "read") == 0) state = MMC_READ; - else if (strcmp(argv[1], "write") == 0) + else if (argc == 5 && strcmp(argv[1], "write") == 0) state = MMC_WRITE; - else if (strcmp(argv[1], "erase") == 0) + else if (argc == 4 && strcmp(argv[1], "erase") == 0) state = MMC_ERASE; - else - state = MMC_INVALID; if (state != MMC_INVALID) { struct mmc *mmc = find_mmc_device(curr_device); diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 4b1606972b..1568594ca4 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -700,6 +700,25 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return ret == 0 ? 0 : 1; } +#ifdef CONFIG_CMD_NAND_TORTURE + if (strcmp(cmd, "torture") == 0) { + if (argc < 3) + goto usage; + + if (!str2off(argv[2], &off)) { + puts("Offset is not a valid number\n"); + return 1; + } + + printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n", + dev, off, nand->erasesize); + ret = nand_torture(nand, off); + printf(" %s\n", ret ? "Failed" : "Passed"); + + return ret == 0 ? 0 : 1; + } +#endif + if (strcmp(cmd, "markbad") == 0) { argc -= 2; argv += 2; @@ -810,6 +829,9 @@ static char nand_help_text[] = "nand erase.chip [clean] - erase entire chip'\n" "nand bad - show bad blocks\n" "nand dump[.oob] off - dump page\n" +#ifdef CONFIG_CMD_NAND_TORTURE + "nand torture off - torture block at offset\n" +#endif "nand scrub [-y] off size | scrub.part partition | scrub.chip\n" " really clean NAND erasing bad blocks (UNSAFE)\n" "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n" diff --git a/common/cmd_usb.c b/common/cmd_usb.c index 8ad0b23058..dacdc2d5b1 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -192,7 +192,7 @@ static void usb_display_desc(struct usb_device *dev) } -static void usb_display_conf_desc(struct usb_configuration_descriptor *config, +static void usb_display_conf_desc(struct usb_config_descriptor *config, struct usb_device *dev) { printf(" Configuration: %d\n", config->bConfigurationValue); diff --git a/common/image.c b/common/image.c index df642e656c..e93b6e89cf 100644 --- a/common/image.c +++ b/common/image.c @@ -3049,6 +3049,133 @@ int fit_check_format(const void *fit) return 1; } + +/** + * fit_conf_find_compat + * @fit: pointer to the FIT format image header + * @fdt: pointer to the device tree to compare against + * + * fit_conf_find_compat() attempts to find the configuration whose fdt is the + * most compatible with the passed in device tree. + * + * Example: + * + * / o image-tree + * |-o images + * | |-o fdt@1 + * | |-o fdt@2 + * | + * |-o configurations + * |-o config@1 + * | |-fdt = fdt@1 + * | + * |-o config@2 + * |-fdt = fdt@2 + * + * / o U-Boot fdt + * |-compatible = "foo,bar", "bim,bam" + * + * / o kernel fdt1 + * |-compatible = "foo,bar", + * + * / o kernel fdt2 + * |-compatible = "bim,bam", "baz,biz" + * + * Configuration 1 would be picked because the first string in U-Boot's + * compatible list, "foo,bar", matches a compatible string in the root of fdt1. + * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1. + * + * returns: + * offset to the configuration to use if one was found + * -1 otherwise + */ +int fit_conf_find_compat(const void *fit, const void *fdt) +{ + int ndepth = 0; + int noffset, confs_noffset, images_noffset; + const void *fdt_compat; + int fdt_compat_len; + int best_match_offset = 0; + int best_match_pos = 0; + + confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); + images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); + if (confs_noffset < 0 || images_noffset < 0) { + debug("Can't find configurations or images nodes.\n"); + return -1; + } + + fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len); + if (!fdt_compat) { + debug("Fdt for comparison has no \"compatible\" property.\n"); + return -1; + } + + /* + * Loop over the configurations in the FIT image. + */ + for (noffset = fdt_next_node(fit, confs_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node(fit, noffset, &ndepth)) { + const void *kfdt; + const char *kfdt_name; + int kfdt_noffset; + const char *cur_fdt_compat; + int len; + size_t size; + int i; + + if (ndepth > 1) + continue; + + kfdt_name = fdt_getprop(fit, noffset, "fdt", &len); + if (!kfdt_name) { + debug("No fdt property found.\n"); + continue; + } + kfdt_noffset = fdt_subnode_offset(fit, images_noffset, + kfdt_name); + if (kfdt_noffset < 0) { + debug("No image node named \"%s\" found.\n", + kfdt_name); + continue; + } + /* + * Get a pointer to this configuration's fdt. + */ + if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) { + debug("Failed to get fdt \"%s\".\n", kfdt_name); + continue; + } + + len = fdt_compat_len; + cur_fdt_compat = fdt_compat; + /* + * Look for a match for each U-Boot compatibility string in + * turn in this configuration's fdt. + */ + for (i = 0; len > 0 && + (!best_match_offset || best_match_pos > i); i++) { + int cur_len = strlen(cur_fdt_compat) + 1; + + if (!fdt_node_check_compatible(kfdt, 0, + cur_fdt_compat)) { + best_match_offset = noffset; + best_match_pos = i; + break; + } + len -= cur_len; + cur_fdt_compat += cur_len; + } + } + if (!best_match_offset) { + debug("No match found.\n"); + return -1; + } + + return best_match_offset; +} + /** * fit_conf_get_node - get node offset for configuration of a given unit name * @fit: pointer to the FIT format image header diff --git a/common/lcd.c b/common/lcd.c index 3017604734..4778655a26 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -696,6 +696,138 @@ static void splash_align_axis(int *axis, unsigned long panel_size, } #endif + +#ifdef CONFIG_LCD_BMP_RLE8 + +#define BMP_RLE8_ESCAPE 0 +#define BMP_RLE8_EOL 0 +#define BMP_RLE8_EOBMP 1 +#define BMP_RLE8_DELTA 2 + +static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap, + int cnt) +{ + while (cnt > 0) { + *(*fbp)++ = cmap[*bmap++]; + cnt--; + } +} + +static void draw_encoded_bitmap(ushort **fbp, ushort c, int cnt) +{ + ushort *fb = *fbp; + int cnt_8copy = cnt >> 3; + + cnt -= cnt_8copy << 3; + while (cnt_8copy > 0) { + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + *fb++ = c; + cnt_8copy--; + } + while (cnt > 0) { + *fb++ = c; + cnt--; + } + (*fbp) = fb; +} + +/* + * Do not call this function directly, must be called from + * lcd_display_bitmap. + */ +static void lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb, + int x_off, int y_off) +{ + uchar *bmap; + ulong width, height; + ulong cnt, runlen; + int x, y; + int decode = 1; + + width = le32_to_cpu(bmp->header.width); + height = le32_to_cpu(bmp->header.height); + bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset); + + x = 0; + y = height - 1; + + while (decode) { + if (bmap[0] == BMP_RLE8_ESCAPE) { + switch (bmap[1]) { + case BMP_RLE8_EOL: + /* end of line */ + bmap += 2; + x = 0; + y--; + /* 16bpix, 2-byte per pixel, width should *2 */ + fb -= (width * 2 + lcd_line_length); + break; + case BMP_RLE8_EOBMP: + /* end of bitmap */ + decode = 0; + break; + case BMP_RLE8_DELTA: + /* delta run */ + x += bmap[2]; + y -= bmap[3]; + /* 16bpix, 2-byte per pixel, x should *2 */ + fb = (uchar *) (lcd_base + (y + y_off - 1) + * lcd_line_length + (x + x_off) * 2); + bmap += 4; + break; + default: + /* unencoded run */ + runlen = bmap[1]; + bmap += 2; + if (y < height) { + if (x < width) { + if (x + runlen > width) + cnt = width - x; + else + cnt = runlen; + draw_unencoded_bitmap( + (ushort **)&fb, + bmap, cmap, cnt); + } + x += runlen; + } + bmap += runlen; + if (runlen & 1) + bmap++; + } + } else { + /* encoded run */ + if (y < height) { + runlen = bmap[0]; + if (x < width) { + /* aggregate the same code */ + while (bmap[0] == 0xff && + bmap[2] != BMP_RLE8_ESCAPE && + bmap[1] == bmap[3]) { + runlen += bmap[2]; + bmap += 2; + } + if (x + runlen > width) + cnt = width - x; + else + cnt = runlen; + draw_encoded_bitmap((ushort **)&fb, + cmap[bmap[1]], cnt); + } + x += runlen; + } + bmap += 2; + } + } +} +#endif + #if defined(CONFIG_MPC823) || defined(CONFIG_MCC200) #define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++) #else @@ -729,7 +861,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) uchar *fb; bmp_image_t *bmp=(bmp_image_t *)bmp_image; uchar *bmap; - ushort padded_line; + ushort padded_width; unsigned long width, height, byte_width; unsigned long pwidth = panel_info.vl_col; unsigned colors, bpix, bmp_bpix; @@ -816,7 +948,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) } #endif - padded_line = (width&0x3) ? ((width&~0x3)+4) : (width); + padded_width = (width&0x3) ? ((width&~0x3)+4) : (width); #ifdef CONFIG_SPLASH_SCREEN_ALIGN splash_align_axis(&x, pwidth, width); @@ -835,6 +967,18 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) switch (bmp_bpix) { case 1: /* pass through */ case 8: +#ifdef CONFIG_LCD_BMP_RLE8 + if (le32_to_cpu(bmp->header.compression) == BMP_BI_RLE8) { + if (bpix != 16) { + /* TODO implement render code for bpix != 16 */ + printf("Error: only support 16 bpix"); + return 1; + } + lcd_display_rle8_bitmap(bmp, cmap_base, fb, x, y); + break; + } +#endif + if (bpix != 16) byte_width = width; else @@ -850,7 +994,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) fb += sizeof(uint16_t) / sizeof(*fb); } } - bmap += (width - padded_line); + bmap += (padded_width - width); fb -= (byte_width + lcd_line_length); } break; @@ -862,7 +1006,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) for (j = 0; j < width; j++) fb_put_word(&fb, &bmap); - bmap += (padded_line - width) * 2; + bmap += (padded_width - width) * 2; fb -= (width * 2 + lcd_line_length); } break; @@ -940,5 +1084,31 @@ static void *lcd_logo(void) #endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */ } +void lcd_position_cursor(unsigned col, unsigned row) +{ + console_col = min(col, CONSOLE_COLS - 1); + console_row = min(row, CONSOLE_ROWS - 1); +} + +int lcd_get_pixel_width(void) +{ + return panel_info.vl_col; +} + +int lcd_get_pixel_height(void) +{ + return panel_info.vl_row; +} + +int lcd_get_screen_rows(void) +{ + return CONSOLE_ROWS; +} + +int lcd_get_screen_columns(void) +{ + return CONSOLE_COLS; +} + /************************************************************************/ /************************************************************************/ diff --git a/common/main.c b/common/main.c index 5fdfff2e28..44fa20dd6a 100644 --- a/common/main.c +++ b/common/main.c @@ -30,6 +30,7 @@ #include <common.h> #include <watchdog.h> #include <command.h> +#include <fdtdec.h> #include <malloc.h> #include <version.h> #ifdef CONFIG_MODEM_SUPPORT @@ -40,13 +41,19 @@ #include <hush.h> #endif +#ifdef CONFIG_OF_CONTROL +#include <fdtdec.h> +#endif + +#ifdef CONFIG_OF_LIBFDT +#include <fdt_support.h> +#endif /* CONFIG_OF_LIBFDT */ + #include <post.h> #include <linux/ctype.h> #include <menu.h> -#if defined(CONFIG_SILENT_CONSOLE) || defined(CONFIG_POST) || defined(CONFIG_CMDLINE_EDITING) DECLARE_GLOBAL_DATA_PTR; -#endif /* * Board-specific Platform code can reimplement show_boot_progress () if needed @@ -274,6 +281,73 @@ int abortboot(int bootdelay) # endif /* CONFIG_AUTOBOOT_KEYED */ #endif /* CONFIG_BOOTDELAY >= 0 */ +/* + * Runs the given boot command securely. Specifically: + * - Doesn't run the command with the shell (run_command or parse_string_outer), + * since that's a lot of code surface that an attacker might exploit. + * Because of this, we don't do any argument parsing--the secure boot command + * has to be a full-fledged u-boot command. + * - Doesn't check for keypresses before booting, since that could be a + * security hole; also disables Ctrl-C. + * - Doesn't allow the command to return. + * + * Upon any failures, this function will drop into an infinite loop after + * printing the error message to console. + */ + +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) && \ + defined(CONFIG_OF_CONTROL) +static void secure_boot_cmd(char *cmd) +{ + cmd_tbl_t *cmdtp; + int rc; + + if (!cmd) { + printf("## Error: Secure boot command not specified\n"); + goto err; + } + + /* Disable Ctrl-C just in case some command is used that checks it. */ + disable_ctrlc(1); + + /* Find the command directly. */ + cmdtp = find_cmd(cmd); + if (!cmdtp) { + printf("## Error: \"%s\" not defined\n", cmd); + goto err; + } + + /* Run the command, forcing no flags and faking argc and argv. */ + rc = (cmdtp->cmd)(cmdtp, 0, 1, &cmd); + + /* Shouldn't ever return from boot command. */ + printf("## Error: \"%s\" returned (code %d)\n", cmd, rc); + +err: + /* + * Not a whole lot to do here. Rebooting won't help much, since we'll + * just end up right back here. Just loop. + */ + hang(); +} + +static void process_fdt_options(const void *blob) +{ + ulong addr; + + /* Add an env variable to point to a kernel payload, if available */ + addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0); + if (addr) + setenv_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr)); + + /* Add an env variable to point to a root disk, if available */ + addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0); + if (addr) + setenv_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr)); +} +#endif /* CONFIG_OF_CONTROL */ + + /****************************************************************************/ void main_loop (void) @@ -284,7 +358,10 @@ void main_loop (void) int rc = 1; int flag; #endif - +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) && \ + defined(CONFIG_OF_CONTROL) + char *env; +#endif #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) char *s; int bootdelay; @@ -380,6 +457,23 @@ void main_loop (void) else #endif /* CONFIG_BOOTCOUNT_LIMIT */ s = getenv ("bootcmd"); +#ifdef CONFIG_OF_CONTROL + /* Allow the fdt to override the boot command */ + env = fdtdec_get_config_string(gd->fdt_blob, "bootcmd"); + if (env) + s = env; + + process_fdt_options(gd->fdt_blob); + + /* + * If the bootsecure option was chosen, use secure_boot_cmd(). + * Always use 'env' in this case, since bootsecure requres that the + * bootcmd was specified in the FDT too. + */ + if (fdtdec_get_config_int(gd->fdt_blob, "bootsecure", 0)) + secure_boot_cmd(env); + +#endif /* CONFIG_OF_CONTROL */ debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); @@ -404,6 +498,10 @@ void main_loop (void) #endif /* CONFIG_MENUKEY */ #endif /* CONFIG_BOOTDELAY */ +#if defined CONFIG_OF_CONTROL + set_working_fdt_addr((void *)gd->fdt_blob); +#endif /* CONFIG_OF_CONTROL */ + /* * Main Loop for Monitor Command Processing */ diff --git a/common/spl/spl.c b/common/spl/spl.c index f068abd8f8..ff9ba7b0a5 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -74,6 +74,16 @@ __weak int spl_start_uboot(void) } #endif +/* + * Weak default function for board specific cleanup/preparation before + * Linux boot. Some boards/platforms might not need it, so just provide + * an empty stub here. + */ +__weak void spl_board_prepare_for_linux(void) +{ + /* Nothing to do! */ +} + void spl_parse_image_header(const struct image_header *header) { u32 header_size = sizeof(struct image_header); @@ -155,7 +165,13 @@ void board_init_r(gd_t *dummy1, ulong dummy2) CONFIG_SYS_SPL_MALLOC_SIZE); #endif +#ifndef CONFIG_PPC + /* + * timer_init() does not exist on PPC systems. The timer is initialized + * and enabled (decrementer) in interrupt_init() here. + */ timer_init(); +#endif #ifdef CONFIG_SPL_BOARD_INIT spl_board_init(); diff --git a/common/stdio.c b/common/stdio.c index 605ff3fde3..9f48e5f503 100644 --- a/common/stdio.c +++ b/common/stdio.c @@ -237,6 +237,8 @@ int stdio_init (void) #ifdef CONFIG_JTAG_CONSOLE drv_jtag_console_init (); #endif - +#ifdef CONFIG_CBMEM_CONSOLE + cbmemc_init(); +#endif return (0); } diff --git a/common/usb.c b/common/usb.c index 50b81752eb..ac9b4ca8d5 100644 --- a/common/usb.c +++ b/common/usb.c @@ -492,9 +492,9 @@ int usb_get_configuration_no(struct usb_device *dev, { int result; unsigned int tmp; - struct usb_configuration_descriptor *config; + struct usb_config_descriptor *config; - config = (struct usb_configuration_descriptor *)&buffer[0]; + config = (struct usb_config_descriptor *)&buffer[0]; result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9); if (result < 9) { if (result < 0) diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 19f01db1ca..4efbcfe90d 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -94,6 +94,15 @@ static const unsigned char usb_kbd_num_keypad[] = { }; /* + * map arrow keys to ^F/^B ^N/^P, can't really use the proper + * ANSI sequence for arrow keys because the queuing code breaks + * when a single keypress expands to 3 queue elements + */ +static const unsigned char usb_kbd_arrow[] = { + 0x6, 0x2, 0xe, 0x10 +}; + +/* * NOTE: It's important for the NUM, CAPS, SCROLL-lock bits to be in this * order. See usb_kbd_setled() function! */ @@ -112,7 +121,7 @@ struct usb_kbd_pdata { uint32_t usb_out_pointer; uint8_t usb_kbd_buffer[USB_KBD_BUFFER_LEN]; - uint8_t new[8]; + uint8_t *new; uint8_t old[8]; uint8_t flags; @@ -224,6 +233,10 @@ static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, keycode = usb_kbd_numkey[scancode - 0x1e]; } + /* Arrow keys */ + if ((scancode >= 0x4f) && (scancode <= 0x52)) + keycode = usb_kbd_arrow[scancode - 0x4f]; + /* Numeric keypad */ if ((scancode >= 0x54) && (scancode <= 0x67)) keycode = usb_kbd_num_keypad[scancode - 0x54]; @@ -435,6 +448,9 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) /* Clear private data */ memset(data, 0, sizeof(struct usb_kbd_pdata)); + /* allocate input buffer aligned and sized to USB DMA alignment */ + data->new = memalign(USB_DMA_MINALIGN, roundup(8, USB_DMA_MINALIGN)); + /* Insert private data into USB device structure */ dev->privptr = data; |