diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
index 668aa71157e8f6bb98e131606938e69db65e55a5..e094ae2d053f331e40475d46852303c79fa3274a 100644
--- a/arch/sandbox/config.mk
+++ b/arch/sandbox/config.mk
@@ -5,6 +5,11 @@ PLATFORM_CPPFLAGS += -DCONFIG_SANDBOX -D__SANDBOX__ -U_FORTIFY_SOURCE
 PLATFORM_CPPFLAGS += -DCONFIG_ARCH_MAP_SYSMEM -DCONFIG_SYS_GENERIC_BOARD
 PLATFORM_LIBS += -lrt
 
+ifdef CONFIG_SANDBOX_SDL
+PLATFORM_LIBS += $(shell sdl-config --libs)
+PLATFORM_CPPFLAGS += $(shell sdl-config --cflags)
+endif
+
 # Support generic board on sandbox
 __HAVE_ARCH_GENERIC_BOARD := y
 
diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile
index 63dededf70f85125bbb67a9dce1c3cb31e6a23e6..7d4410c42a20a6760babfdf28308a3069cd36fec 100644
--- a/arch/sandbox/cpu/Makefile
+++ b/arch/sandbox/cpu/Makefile
@@ -8,6 +8,7 @@
 #
 
 obj-y	:= cpu.o os.o start.o state.o
+obj-$(CONFIG_SANDBOX_SDL)	+= sdl.o
 
 # os.c is build in the system environment, so needs standard includes
 # CFLAGS_REMOVE_os.o cannot be used to drop header include path
@@ -17,3 +18,5 @@ cmd_cc_os.o = $(CC) $(filter-out -nostdinc, \
 
 $(obj)/os.o: $(src)/os.c FORCE
 	$(call if_changed_dep,cc_os.o)
+$(obj)/sdl.o: $(src)/sdl.c FORCE
+	$(call if_changed_dep,cc_os.o)
diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c
new file mode 100644
index 0000000000000000000000000000000000000000..18dc7edf19c285d5600d98145c5b606a20992663
--- /dev/null
+++ b/arch/sandbox/cpu/sdl.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <errno.h>
+#include <linux/input.h>
+#include <SDL/SDL.h>
+#include <sound.h>
+#include <asm/state.h>
+
+static struct sdl_info {
+	SDL_Surface *screen;
+	int width;
+	int height;
+	int depth;
+	int pitch;
+	uint frequency;
+	uint audio_pos;
+	uint audio_size;
+	uint8_t *audio_data;
+	bool audio_active;
+	bool inited;
+} sdl;
+
+static void sandbox_sdl_poll_events(void)
+{
+	/*
+	 * We don't want to include common.h in this file since it uses
+	 * system headers. So add a declation here.
+	 */
+	extern void reset_cpu(unsigned long addr);
+	SDL_Event event;
+
+	while (SDL_PollEvent(&event)) {
+		switch (event.type) {
+		case SDL_QUIT:
+			puts("LCD window closed - quitting\n");
+			reset_cpu(1);
+			break;
+		}
+	}
+}
+
+static int sandbox_sdl_ensure_init(void)
+{
+	if (!sdl.inited) {
+		if (SDL_Init(0) < 0) {
+			printf("Unable to initialize SDL: %s\n",
+			       SDL_GetError());
+			return -EIO;
+		}
+
+		atexit(SDL_Quit);
+
+		sdl.inited = true;
+	}
+	return 0;
+}
+
+int sandbox_sdl_init_display(int width, int height, int log2_bpp)
+{
+	struct sandbox_state *state = state_get_current();
+	int err;
+
+	if (!width || !state->show_lcd)
+		return 0;
+	err = sandbox_sdl_ensure_init();
+	if (err)
+		return err;
+	if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
+		printf("Unable to initialize SDL LCD: %s\n", SDL_GetError());
+		return -EPERM;
+	}
+	SDL_WM_SetCaption("U-Boot", "U-Boot");
+
+	sdl.width = width;
+	sdl.height = height;
+	sdl.depth = 1 << log2_bpp;
+	sdl.pitch = sdl.width * sdl.depth / 8;
+	sdl.screen = SDL_SetVideoMode(width, height, 0, 0);
+	sandbox_sdl_poll_events();
+
+	return 0;
+}
+
+int sandbox_sdl_sync(void *lcd_base)
+{
+	SDL_Surface *frame;
+
+	frame = SDL_CreateRGBSurfaceFrom(lcd_base, sdl.width, sdl.height,
+			sdl.depth, sdl.pitch,
+			0x1f << 11, 0x3f << 5, 0x1f << 0, 0);
+	SDL_BlitSurface(frame, NULL, sdl.screen, NULL);
+	SDL_FreeSurface(frame);
+	SDL_UpdateRect(sdl.screen, 0, 0, 0, 0);
+	sandbox_sdl_poll_events();
+
+	return 0;
+}
+
+#define NONE (-1)
+#define NUM_SDL_CODES	(SDLK_UNDO + 1)
+
+static int16_t sdl_to_keycode[NUM_SDL_CODES] = {
+	/* 0 */
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, KEY_BACKSPACE, KEY_TAB,
+	NONE, NONE, NONE, KEY_ENTER, NONE,
+	NONE, NONE, NONE, NONE, KEY_POWER,	/* use PAUSE as POWER */
+
+	/* 20 */
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, KEY_ESC, NONE, NONE,
+	NONE, NONE, KEY_SPACE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+
+	/* 40 */
+	NONE, NONE, NONE, NONE, KEY_COMMA,
+	KEY_MINUS, KEY_DOT, KEY_SLASH, KEY_0, KEY_1,
+	KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
+	KEY_7, KEY_8, KEY_9, NONE, KEY_SEMICOLON,
+
+	/* 60 */
+	NONE, KEY_EQUAL, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+
+	/* 80 */
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, KEY_BACKSLASH, NONE, NONE,
+	NONE, KEY_GRAVE, KEY_A, KEY_B, KEY_C,
+
+	/* 100 */
+	KEY_D, KEY_E, KEY_F, KEY_G, KEY_H,
+	KEY_I, KEY_J, KEY_K, KEY_L, KEY_M,
+	KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R,
+	KEY_S, KEY_T, KEY_U, KEY_V, KEY_W,
+
+	/* 120 */
+	KEY_X, KEY_Y, KEY_Z, NONE, NONE,
+	NONE, NONE, KEY_DELETE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+
+	/* 140 */
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+
+	/* 160 */
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+
+	/* 180 */
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+
+	/* 200 */
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+
+	/* 220 */
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+
+	/* 240 */
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+	NONE, KEY_KP0, KEY_KP1, KEY_KP2, KEY_KP3,
+
+	/* 260 */
+	KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8,
+	KEY_KP9, KEY_KPDOT, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS,
+	KEY_KPPLUS, KEY_KPENTER, KEY_KPEQUAL, KEY_UP, KEY_DOWN,
+	KEY_RIGHT, KEY_LEFT, KEY_INSERT, KEY_HOME, KEY_END,
+
+	/* 280 */
+	KEY_PAGEUP, KEY_PAGEDOWN, KEY_F1, KEY_F2, KEY_F3,
+	KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8,
+	KEY_F9, KEY_F10, KEY_F11, KEY_F12, NONE,
+	NONE, NONE, NONE, NONE, NONE,
+
+	/* 300 */
+	KEY_NUMLOCK, KEY_CAPSLOCK, KEY_SCROLLLOCK, KEY_RIGHTSHIFT,
+		KEY_LEFTSHIFT,
+	KEY_RIGHTCTRL, KEY_LEFTCTRL, KEY_RIGHTALT, KEY_LEFTALT, KEY_RIGHTMETA,
+	KEY_LEFTMETA, NONE, KEY_FN, NONE, KEY_COMPOSE,
+	NONE, KEY_PRINT, KEY_SYSRQ, KEY_PAUSE, NONE,
+
+	/* 320 */
+	NONE, NONE, NONE,
+};
+
+int sandbox_sdl_scan_keys(int key[], int max_keys)
+{
+	Uint8 *keystate;
+	int i, count;
+
+	sandbox_sdl_poll_events();
+	keystate = SDL_GetKeyState(NULL);
+	for (i = count = 0; i < NUM_SDL_CODES; i++) {
+		if (count >= max_keys)
+			break;
+		else if (keystate[i])
+			key[count++] = sdl_to_keycode[i];
+	}
+
+	return count;
+}
+
+int sandbox_sdl_key_pressed(int keycode)
+{
+	int key[8];	/* allow up to 8 keys to be pressed at once */
+	int count;
+	int i;
+
+	count = sandbox_sdl_scan_keys(key, sizeof(key) / sizeof(key[0]));
+	for (i = 0; i < count; i++) {
+		if (key[i] == keycode)
+			return 0;
+	}
+
+	return -ENOENT;
+}
+
+void sandbox_sdl_fill_audio(void *udata, Uint8 *stream, int len)
+{
+	int avail;
+
+	avail = sdl.audio_size - sdl.audio_pos;
+	if (avail < len)
+		len = avail;
+
+	SDL_MixAudio(stream, sdl.audio_data + sdl.audio_pos, len,
+		     SDL_MIX_MAXVOLUME);
+	sdl.audio_pos += len;
+
+	/* Loop if we are at the end */
+	if (sdl.audio_pos == sdl.audio_size)
+		sdl.audio_pos = 0;
+}
+
+int sandbox_sdl_sound_init(void)
+{
+	SDL_AudioSpec wanted;
+
+	if (sandbox_sdl_ensure_init())
+		return -1;
+
+	if (sdl.audio_active)
+		return 0;
+
+	/*
+	 * At present all sandbox sounds crash. This is probably due to
+	 * symbol name conflicts with U-Boot. We can remove the malloc()
+	 * probles with:
+	 *
+	 * #define USE_DL_PREFIX
+	 *
+	 * and get this:
+	 *
+	 * Assertion 'e->pollfd->fd == e->fd' failed at pulse/mainloop.c:676,
+	 *		function dispatch_pollfds(). Aborting.
+	 *
+	 * The right solution is probably to make U-Boot's names private or
+	 * link os.c and sdl.c against their libraries before liking with
+	 * U-Boot. TBD. For now sound is disabled.
+	 */
+	printf("(Warning: sandbox sound disabled)\n");
+	return 0;
+
+	/* Set the audio format */
+	wanted.freq = 22050;
+	wanted.format = AUDIO_S16;
+	wanted.channels = 1;    /* 1 = mono, 2 = stereo */
+	wanted.samples = 1024;  /* Good low-latency value for callback */
+	wanted.callback = sandbox_sdl_fill_audio;
+	wanted.userdata = NULL;
+
+	sdl.audio_size = sizeof(uint16_t) * wanted.freq;
+	sdl.audio_data = malloc(sdl.audio_size);
+	if (!sdl.audio_data) {
+		printf("%s: Out of memory\n", __func__);
+		return -1;
+	}
+	sdl.audio_pos = 0;
+
+	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
+		printf("Unable to initialize SDL audio: %s\n", SDL_GetError());
+		goto err;
+	}
+
+	/* Open the audio device, forcing the desired format */
+	if (SDL_OpenAudio(&wanted, NULL) < 0) {
+		printf("Couldn't open audio: %s\n", SDL_GetError());
+		goto err;
+	}
+	sdl.audio_active = true;
+
+	return 0;
+
+err:
+	free(sdl.audio_data);
+	return -1;
+}
+
+int sandbox_sdl_sound_start(uint frequency)
+{
+	if (!sdl.audio_active)
+		return -1;
+	sdl.frequency = frequency;
+	sound_create_square_wave((unsigned short *)sdl.audio_data,
+				 sdl.audio_size, frequency);
+	sdl.audio_pos = 0;
+	SDL_PauseAudio(0);
+
+	return 0;
+}
+
+int sandbox_sdl_sound_stop(void)
+{
+	if (!sdl.audio_active)
+		return -1;
+	SDL_PauseAudio(1);
+
+	return 0;
+}
diff --git a/arch/sandbox/include/asm/sdl.h b/arch/sandbox/include/asm/sdl.h
new file mode 100644
index 0000000000000000000000000000000000000000..6edec1acfa39a2f26ddd6c3c52cdcf34522275b0
--- /dev/null
+++ b/arch/sandbox/include/asm/sdl.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __SANDBOX_SDL_H
+#define __SANDBOX_SDL_H
+
+#include <errno.h>
+
+#ifdef CONFIG_SANDBOX_SDL
+
+/**
+ * sandbox_sdl_init_display() - Set up SDL video ready for use
+ *
+ * @width:	Window width in pixels
+ * @height	Window height in pixels
+ * @log2_bpp:	Log to base 2 of the number of bits per pixel. So a 32bpp
+ *		display will pass 5, since 2*5 = 32
+ * @return 0 if OK, -ENODEV if no device, -EIO if SDL failed to initialize
+ *		and -EPERM if the video failed to come up.
+ */
+int sandbox_sdl_init_display(int width, int height, int log2_bpp);
+
+/**
+ * sandbox_sdl_sync() - Sync current U-Boot LCD frame buffer to SDL
+ *
+ * This must be called periodically to update the screen for SDL so that the
+ * user can see it.
+ *
+ * @lcd_base: Base of frame buffer
+ * @return 0 if screen was updated, -ENODEV is there is no screen.
+ */
+int sandbox_sdl_sync(void *lcd_base);
+
+/**
+ * sandbox_sdl_scan_keys() - scan for pressed keys
+ *
+ * Works out which keys are pressed and returns a list
+ *
+ * @key:	Array to receive keycodes
+ * @max_keys:	Size of array
+ * @return number of keycodes found, 0 if none, -ENODEV if no keyboard
+ */
+int sandbox_sdl_scan_keys(int key[], int max_keys);
+
+/**
+ * sandbox_sdl_key_pressed() - check if a particular key is pressed
+ *
+ * @keycode:	Keycode to check (KEY_... - see include/linux/input.h
+ * @return 0 if pressed, -ENOENT if not pressed. -ENODEV if keybord not
+ * available,
+ */
+int sandbox_sdl_key_pressed(int keycode);
+
+/**
+ * sandbox_sdl_sound_start() - start playing a sound
+ *
+ * @frequency:	Frequency of sounds in Hertz
+ * @return 0 if OK, -ENODEV if no sound is available
+ */
+int sandbox_sdl_sound_start(uint frequency);
+
+/**
+ * sandbox_sdl_sound_stop() - stop playing a sound
+ *
+ * @return 0 if OK, -ENODEV if no sound is available
+ */
+int sandbox_sdl_sound_stop(void);
+
+/**
+ * sandbox_sdl_sound_init() - set up the sound system
+ *
+ * @return 0 if OK, -ENODEV if no sound is available
+ */
+int sandbox_sdl_sound_init(void);
+
+#else
+static inline int sandbox_sdl_init_display(int width, int height,
+					    int log2_bpp)
+{
+	return -ENODEV;
+}
+
+static inline int sandbox_sdl_sync(void *lcd_base)
+{
+	return -ENODEV;
+}
+
+static inline int sandbox_sdl_scan_keys(int key[], int max_keys)
+{
+	return -ENODEV;
+}
+
+static inline int sandbox_sdl_key_pressed(int keycode)
+{
+	return -ENODEV;
+}
+
+static inline int sandbox_sdl_sound_start(uint frequency)
+{
+	return -ENODEV;
+}
+
+static inline int sandbox_sdl_sound_stop(void)
+{
+	return -ENODEV;
+}
+
+static inline int sandbox_sdl_sound_init(void)
+{
+	return -ENODEV;
+}
+
+#endif
+
+#endif