summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorStefano Babic <sbabic@denx.de>2012-12-08 12:02:45 +0100
committerStefano Babic <sbabic@denx.de>2012-12-08 12:02:45 +0100
commit05a860c228fe6c8f2e7aced8cc8ef88bc1038363 (patch)
tree764536da9202b9de387a0d957829f64dfba818b7 /common
parent393ff47ba3123208f7c4f08d63f114300a41d0c4 (diff)
parentfd4d564b3c80b111f18c93adb14233a6a7ddb0e9 (diff)
downloadu-boot-imx-05a860c228fe6c8f2e7aced8cc8ef88bc1038363.zip
u-boot-imx-05a860c228fe6c8f2e7aced8cc8ef88bc1038363.tar.gz
u-boot-imx-05a860c228fe6c8f2e7aced8cc8ef88bc1038363.tar.bz2
Merge branch 'master' of git://git.denx.de/u-boot into master
Conflicts: drivers/power/power_fsl.c include/configs/mx35pdk.h include/configs/mx53loco.h include/configs/woodburn_common.h board/woodburn/woodburn.c These boards still use the old old PMIC framework, so they do not merge properly after the power framework was merged into mainline. Fix all conflicts and update woodburn to use Power Framework. Signed-off-by: Stefano Babic <sbabic@denx.de>
Diffstat (limited to 'common')
-rw-r--r--common/Makefile3
-rw-r--r--common/bouncebuf.c75
-rw-r--r--common/cmd_bmp.c5
-rw-r--r--common/cmd_bootm.c11
-rw-r--r--common/cmd_led.c6
-rw-r--r--common/cmd_mmc.c11
-rw-r--r--common/cmd_nand.c22
-rw-r--r--common/cmd_usb.c2
-rw-r--r--common/image.c127
-rw-r--r--common/lcd.c178
-rw-r--r--common/main.c104
-rw-r--r--common/spl/spl.c16
-rw-r--r--common/stdio.c4
-rw-r--r--common/usb.c4
-rw-r--r--common/usb_kbd.c18
15 files changed, 528 insertions, 58 deletions
diff --git a/common/Makefile b/common/Makefile
index 9e43322..c29a7d8 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -195,6 +195,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 4f827f8..1df12cd 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 b8809e3..5a52edd 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 d256ddf..4dbe952 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 d83b3ba..7f5ab43 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 62a1c224..7dacd51 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 4b16069..1568594 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 8ad0b23..dacdc2d 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 df642e6..e93b6e8 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 b6be800..4c83a8b 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -642,6 +642,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
@@ -675,7 +807,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;
@@ -762,7 +894,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);
@@ -781,6 +913,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
@@ -796,7 +940,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;
@@ -808,7 +952,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;
@@ -885,5 +1029,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 592ce07..5362781 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 f068abd..ff9ba7b 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 605ff3f..9f48e5f 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 50b8175..ac9b4ca 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 19f01db..4efbcfe 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;