Patchwork [RFC] Making flashrom standalone on Yeeloong

login
register
about
Submitter Vladimir 'φ-coder/phcoder' Serbinenko
Date 2010-05-28 23:50:17
Message ID <4C0056B9.8050204@gmail.com>
Download mbox | patch
Permalink /patch/1415/
State RFC
Headers show

Comments

Hello, all. As a side projetc I wanted to make flashrom loadable using
multiboot2 protocol on yeeloong. In this case multiboot2-compliant
loader will already put the necessary files in memory so no FS code is
required.
Major changes:
Remove OS includes, disable few secondary files, write standalone
analoga for standard functions, write initialisations, use passed
buffers instead of files and the most intrusive change is switch to
static allocation.
The patch still doesn't compile, I posting it here only for idea gathering

Patch

=== modified file '82802ab.c'
--- 82802ab.c	2003-07-21 12:05:56 +0000
+++ 82802ab.c	2010-05-28 20:40:58 +0000
@@ -26,8 +26,10 @@ 
  *  - Order number: 290658-004
  */
 
+#ifndef CONFIG_STANDALONE 
 #include <string.h>
 #include <stdlib.h>
+#endif
 #include "flash.h"
 #include "chipdrivers.h"
 

=== modified file 'Makefile'
--- Makefile	2003-07-23 20:29:49 +0000
+++ Makefile	2010-05-28 23:08:07 +0000
@@ -31,6 +31,14 @@ 
 
 WARNERROR ?= yes
 
+CONFIG_STANDALONE ?= no
+
+ifeq ($(CONFIG_STANDALONE), yes)
+ASM_OBJS = startup.o
+else
+ASM_OBJS = 
+endif
+
 ifeq ($(WARNERROR), yes)
 CFLAGS += -Werror
 endif
@@ -55,17 +63,36 @@ 
 CONFIG_SERPROG = no
 endif
 
+ifeq ($(CONFIG_STANDALONE), yes)
+# Bus Pirate and Serprog are not supported in standalone config.
+CONFIG_BUSPIRATESPI = no
+CONFIG_SERPROG = no
+endif
+
 CHIP_OBJS = jedec.o stm50flw0x0x.o w39v040c.o w39v080fa.o w29ee011.o \
 	sst28sf040.o m29f400bt.o 82802ab.o pm49fl00x.o \
 	sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o
 
 LIB_OBJS = layout.o
 
-CLI_OBJS = flashrom.o cli_classic.o cli_output.o print.o
-
-PROGRAMMER_OBJS = udelay.o programmer.o
-
+CLI_OBJS = flashrom.o print.o
+
+ifneq ($(CONFIG_STANDALONE), yes)
+CLI_OBJS += cli_classic.o cli_output.o
+else
+CLI_OBJS += cli_standalone.o
+endif
+
+
+PROGRAMMER_OBJS = programmer.o
+
+ifneq ($(CONFIG_STANDALONE), yes)
 all: pciutils features dep $(PROGRAM)
+PROGRAMMER_OBJS += udelay.o 
+else
+all: features dep $(PROGRAM)
+PROGRAMMER_OBJS += udelay_yeeloong.o 
+endif
 
 # Set the flashrom version string from the highest revision number
 # of the checked out flashrom files.
@@ -122,9 +149,18 @@ 
 # Disable wiki printing by default. It is only useful if you have wiki access.
 CONFIG_PRINT_WIKI ?= no
 
+ifeq ($(CONFIG_STANDALONE), yes)
+FEATURE_CFLAGS += -D'CONFIG_STANDALONE=1' -nostdinc -fno-builtin
+endif
+
 ifeq ($(CONFIG_INTERNAL), yes)
 FEATURE_CFLAGS += -D'INTERNAL_SUPPORT=1'
-PROGRAMMER_OBJS += chipset_enable.o board_enable.o cbtable.o dmi.o internal.o
+PROGRAMMER_OBJS += chipset_enable.o board_enable.o internal.o
+ifneq ($(CONFIG_STANDALONE), yes)
+PROGRAMMER_OBJS += dmi.o
+#### FIXME
+PROGRAMMER_OBJS += cbtable.o
+endif
 # FIXME: The PROGRAMMER_OBJS below should only be included on x86.
 PROGRAMMER_OBJS += it87spi.o ichspi.o sb600spi.o wbsio_spi.o
 NEED_PCI := yes
@@ -244,8 +280,13 @@ 
 
 OBJS = $(CHIP_OBJS) $(CLI_OBJS) $(PROGRAMMER_OBJS) $(LIB_OBJS)
 
-$(PROGRAM): $(OBJS)
+ifeq ($(CONFIG_STANDALONE), yes)
+$(PROGRAM): $(ASM_OBJS) $(OBJS)
+	$(CC) $(LDFLAGS) -o $(PROGRAM) $(OBJS)
+else
+$(PROGRAM): $(ASM_OBJS) $(OBJS)
 	$(CC) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(FEATURE_LIBS) $(LIBS)
+endif
 
 # TAROPTIONS reduces information leakage from the packager's system.
 # If other tar programs support command line arguments for setting uid/gid of
@@ -255,6 +296,9 @@ 
 %.o: %.c .features
 	$(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURE_CFLAGS) $(SVNDEF) -o $@ -c $<
 
+startup.o: startup.S	.features
+	$(CC) $(CFLAGS) $(CPPFLAGS) $(FEATURE_CFLAGS) $(SVNDEF) -DASM_FILE=1 -o $@ -c $<
+
 clean:
 	rm -f $(PROGRAM) *.o
 
@@ -262,7 +306,7 @@ 
 	rm -f .dependencies .features .libdeps
 
 dep:
-	@$(CC) $(CPPFLAGS) $(SVNDEF) -MM $(OBJS:.o=.c) > .dependencies
+	@$(CC) $(CPPFLAGS) $(SVNDEF) -MM $(ASM_OBJS:.o=.S) $(OBJS:.o=.c) > .dependencies
 
 strip: $(PROGRAM)
 	$(STRIP) $(STRIP_ARGS) $(PROGRAM)

=== modified file 'board_enable.c'
--- board_enable.c	2003-07-23 20:31:02 +0000
+++ board_enable.c	2010-05-28 21:35:32 +0000
@@ -23,9 +23,10 @@ 
 /*
  * Contains the board specific flash enables.
  */
-
+#ifndef CONFIG_STANDALONE
 #include <string.h>
 #include <fcntl.h>
+#endif
 #include "flash.h"
 
 #if defined(__i386__) || defined(__x86_64__)

=== modified file 'cbtable.c'
--- cbtable.c	2003-07-21 16:28:35 +0000
+++ cbtable.c	2010-05-28 21:39:58 +0000
@@ -22,9 +22,11 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <stdlib.h>
 #include <sys/types.h>
 #include <string.h>
+#endif
 #include "flash.h"
 #include "coreboot_tables.h"
 

=== modified file 'chipset_enable.c'
--- chipset_enable.c	2003-07-23 20:33:03 +0000
+++ chipset_enable.c	2010-05-28 21:35:08 +0000
@@ -27,11 +27,13 @@ 
 
 #define _LARGEFILE64_SOURCE
 
+#ifndef CONFIG_STANDALONE
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#endif
 #include "flash.h"
 
 #if defined(__i386__) || defined(__x86_64__)

=== added file 'cli_standalone.c'
--- cli_standalone.c	1970-01-01 00:00:00 +0000
+++ cli_standalone.c	2010-05-28 21:21:41 +0000
@@ -0,0 +1,37 @@ 
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2000 Silicon Integrated System Corporation
+ * Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
+ * Copyright (C) 2005-2008 coresystems GmbH
+ * Copyright (C) 2008,2009,2010 Carl-Daniel Hailfinger
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include "flash.h"
+#include "flashchips.h"
+
+int
+cli_standalone (char *args, char *file)
+{ 
+  print_version();
+  print_banner();
+
+  if (selfcheck())
+    return 1;
+
+  return 0;
+}

=== modified file 'drkaiser.c'
--- drkaiser.c	2003-06-24 21:51:16 +0000
+++ drkaiser.c	2010-05-28 22:21:29 +0000
@@ -18,9 +18,11 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#endif
 #include "flash.h"
 
 #define PCI_VENDOR_ID_DRKAISER		0x1803
@@ -62,7 +64,9 @@ 
 {
 	/* Write protect the flash again. */
 	pci_write_word(pcidev_dev, PCI_MAGIC_DRKAISER_ADDR, 0);
+#ifndef CONFIG_STANDALONE
 	free(programmer_param);
+#endif
 	pci_cleanup(pacc);
 	release_io_perms();
 	return 0;

=== modified file 'dummyflasher.c'
--- dummyflasher.c	2003-06-24 16:37:02 +0000
+++ dummyflasher.c	2010-05-28 22:23:00 +0000
@@ -18,10 +18,12 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <sys/types.h>
+#endif
 #include "flash.h"
 
 int dummy_init(void)
@@ -31,11 +33,17 @@ 
 
 	/* "all" is equivalent to specifying no type. */
 	if (programmer_param && (!strcmp(programmer_param, "all"))) {
+#ifndef CONFIG_STANDALONE
 		free(programmer_param);
+#endif
 		programmer_param = NULL;
 	}
 	if (!programmer_param)
+#ifndef CONFIG_STANDALONE
 		programmer_param = strdup("parallel,lpc,fwh,spi");
+#else
+		programmer_param = "parallel,lpc,fwh,spi";
+#endif
 	/* Convert the parameters to lowercase. */
 	for (i = 0; programmer_param[i] != '\0'; i++)
 		programmer_param[i] =
@@ -61,7 +69,9 @@ 
 	}
 	if (buses_supported == CHIP_BUSTYPE_NONE)
 		msg_pdbg("Support for all flash bus types disabled.\n");
+#ifndef CONFIG_STANDALONE
 	free(programmer_param);
+#endif
 	return 0;
 }
 

=== modified file 'flash.h'
--- flash.h	2003-07-23 20:33:03 +0000
+++ flash.h	2010-05-28 21:53:19 +0000
@@ -24,6 +24,10 @@ 
 #ifndef __FLASH_H__
 #define __FLASH_H__ 1
 
+#ifdef CONFIG_STANDALONE
+#include "standalone.h"
+#include "hwaccess.h"
+#else
 #include <unistd.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -33,6 +37,7 @@ 
 #undef min
 #undef max
 #endif
+#endif
 
 typedef unsigned long chipaddr;
 

=== modified file 'flashrom.c'
--- flashrom.c	2003-07-23 20:29:49 +0000
+++ flashrom.c	2010-05-28 22:52:27 +0000
@@ -21,6 +21,7 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -30,6 +31,7 @@ 
 #if HAVE_UTSNAME == 1
 #include <sys/utsname.h>
 #endif
+#endif
 #include "flash.h"
 #include "flashchips.h"
 
@@ -511,6 +513,7 @@ 
 	return i;
 }
 
+#ifndef CONFIG_STANDALONE
 char *strcat_realloc(char *dest, const char *src)
 {
 	dest = realloc(dest, strlen(dest) + strlen(src) + 1);
@@ -519,6 +522,7 @@ 
 	strcat(dest, src);
 	return dest;
 }
+#endif
 
 /* This is a somewhat hacked function similar in some ways to strtok().
  * It will look for needle in haystack, return a copy of needle and remove
@@ -1002,6 +1006,7 @@ 
 	return ret;
 }
 
+#ifndef CONFIG_STANDALONE
 int read_flash(struct flashchip *flash, char *filename)
 {
 	unsigned long numbytes;
@@ -1033,6 +1038,7 @@ 
 		return 1;
 	return 0;
 }
+#endif
 
 /* This function shares a lot of its structure with erase_flash().
  * Even if an error is found, the function will keep going and check the rest.
@@ -1192,7 +1198,7 @@ 
 
 void print_sysinfo(void)
 {
-#if HAVE_UTSNAME == 1
+#if HAVE_UTSNAME == 1 && !defined (CONFIG_STANDALONE)
 	struct utsname osinfo;
 	uname(&osinfo);
 
@@ -1330,13 +1336,11 @@ 
 int doit(struct flashchip *flash, int force, char *filename, int read_it, int write_it, int erase_it, int verify_it)
 {
 	uint8_t *buf;
-	unsigned long numbytes;
-	FILE *image;
 	int ret = 0;
 	unsigned long size;
 
 	size = flash->total_size * 1024;
-	buf = (uint8_t *) calloc(size, sizeof(char));
+	buf = NULL;
 
 	if (erase_it) {
 		if (flash->tested & TEST_BAD_ERASE) {
@@ -1366,8 +1370,6 @@ 
 			return 1;
 		}
 	} else {
-		struct stat image_stat;
-
 		if (flash->unlock)
 			flash->unlock(flash);
 
@@ -1392,34 +1394,51 @@ 
 				msg_cerr("Continuing anyway.\n");
 			}
 		}
-		if ((image = fopen(filename, "rb")) == NULL) {
-			perror(filename);
-			programmer_shutdown();
-			exit(1);
-		}
-		if (fstat(fileno(image), &image_stat) != 0) {
-			perror(filename);
-			programmer_shutdown();
-			exit(1);
-		}
-		if (image_stat.st_size != flash->total_size * 1024) {
-			msg_gerr("Error: Image size doesn't match\n");
-			programmer_shutdown();
-			exit(1);
-		}
-
-		numbytes = fread(buf, 1, size, image);
+#ifndef CONFIG_STANDALONE
+		{
+			FILE *image;
+			struct stat image_stat;
+			unsigned long numbytes;
+
+			buf = (uint8_t *) calloc(size, sizeof(char));
+
+			if ((image = fopen(filename, "rb")) == NULL) {
+				perror(filename);
+				programmer_shutdown();
+				exit(1);
+			}
+			if (fstat(fileno(image), &image_stat) != 0) {
+				perror(filename);
+				programmer_shutdown();
+				exit(1);
+			}
+			if (image_stat.st_size != flash->total_size * 1024) {
+				msg_gerr("Error: Image size doesn't match\n");
+				programmer_shutdown();
+				exit(1);
+			}
+
+			numbytes = fread(buf, 1, size, image);
+			fclose(image);
+			if (numbytes != size) {
+				msg_gerr("Error: Failed to read file. Got %ld bytes, wanted %ld!\n", numbytes, size);
+				programmer_shutdown();
+				return 1;
+			}
+		}
+#else
+		buf = module_image;
+		size = module_image_size;
+#endif
+
 #if INTERNAL_SUPPORT == 1
 		show_id(buf, size, force);
 #endif
-		fclose(image);
-		if (numbytes != size) {
-			msg_gerr("Error: Failed to read file. Got %ld bytes, wanted %ld!\n", numbytes, size);
-			programmer_shutdown();
-			return 1;
-		}
 	}
 
+	if (!buf)
+		return ret;
+
 	// This should be moved into each flash part's code to do it 
 	// cleanly. This does the job.
 	handle_romentries(buf, flash);

=== modified file 'hwaccess.c'
--- hwaccess.c	2003-07-23 20:29:49 +0000
+++ hwaccess.c	2010-05-28 20:40:59 +0000
@@ -18,12 +18,14 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <stdint.h>
 #include <string.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <errno.h>
+#endif
 #include "flash.h"
 
 #if defined(__i386__) || defined(__x86_64__)

=== modified file 'hwaccess.h'
--- hwaccess.h	2003-07-23 20:29:49 +0000
+++ hwaccess.h	2010-05-28 20:40:59 +0000
@@ -30,7 +30,7 @@ 
 #endif
 #endif
 
-#if NEED_PCI == 1
+#if NEED_PCI == 1 && !defined (CONFIG_STANDALONE)
 #include <pci/pci.h>
 #endif
 

=== modified file 'internal.c'
--- internal.c	2003-07-23 20:29:49 +0000
+++ internal.c	2010-05-28 21:52:32 +0000
@@ -18,6 +18,7 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <stdint.h>
 #include <string.h>
 #include <stdlib.h>
@@ -25,6 +26,7 @@ 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
+#endif
 #include "flash.h"
 
 #if NEED_PCI == 1

=== modified file 'layout.c'
--- layout.c	2003-07-21 15:51:40 +0000
+++ layout.c	2010-05-28 22:32:09 +0000
@@ -18,9 +18,11 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#endif
 #include "flash.h"
 
 #if INTERNAL_SUPPORT == 1
@@ -89,8 +91,8 @@ 
 	printf_debug("coreboot last image size "
 		     "(not ROM size) is %d bytes.\n", *walk);
 
-	mainboard_part = strdup(mb_part);
-	mainboard_vendor = strdup(mb_vendor);
+	mainboard_part = mb_part;
+	mainboard_vendor = mb_vendor;
 	printf_debug("Manufacturer: %s\n", mainboard_vendor);
 	printf_debug("Mainboard ID: %s\n", mainboard_part);
 

=== added file 'multiboot2.h'
--- multiboot2.h	1970-01-01 00:00:00 +0000
+++ multiboot2.h	2010-05-28 20:40:58 +0000
@@ -0,0 +1,314 @@ 
+/*  multiboot2.h - Multiboot 2 header file.  */
+/*  Copyright (C) 1999,2003,2007,2008,2009,2010  Free Software Foundation, Inc.
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to
+ *  deal in the Software without restriction, including without limitation the
+ *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ *  sell copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in
+ *  all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL ANY
+ *  DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ *  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header.  */
+#define MULTIBOOT_SEARCH			32768
+#define MULTIBOOT_HEADER_ALIGN			8
+
+/* The magic field should contain this.  */
+#define MULTIBOOT2_HEADER_MAGIC			0xe85250d6
+
+/* This should be in %eax.  */
+#define MULTIBOOT2_BOOTLOADER_MAGIC		0x36d76289
+
+/* Alignment of multiboot modules.  */
+#define MULTIBOOT_MOD_ALIGN			0x00001000
+
+/* Alignment of the multiboot info structure.  */
+#define MULTIBOOT_INFO_ALIGN			0x00000008
+
+/* Flags set in the 'flags' member of the multiboot header.  */
+
+#define MULTIBOOT_TAG_ALIGN                  8
+#define MULTIBOOT_TAG_TYPE_END               0
+#define MULTIBOOT_TAG_TYPE_CMDLINE           1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME  2
+#define MULTIBOOT_TAG_TYPE_MODULE            3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO     4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV           5
+#define MULTIBOOT_TAG_TYPE_MMAP              6
+#define MULTIBOOT_TAG_TYPE_VBE               7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER       8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS      9
+#define MULTIBOOT_TAG_TYPE_APM               10
+
+#define MULTIBOOT_HEADER_TAG_END  0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST  1
+#define MULTIBOOT_HEADER_TAG_ADDRESS  2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS  3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS  4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER  5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN  6
+
+#define MULTIBOOT_ARCHITECTURE_I386  0
+#define MULTIBOOT_ARCHITECTURE_MIPS32  4
+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+
+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
+
+#ifndef ASM_FILE
+
+typedef unsigned char		multiboot_uint8_t;
+typedef unsigned short		multiboot_uint16_t;
+typedef unsigned int		multiboot_uint32_t;
+typedef unsigned long long	multiboot_uint64_t;
+
+struct multiboot_header
+{
+  /* Must be MULTIBOOT_MAGIC - see above.  */
+  multiboot_uint32_t magic;
+
+  /* ISA */
+  multiboot_uint32_t architecture;
+
+  /* Total header length.  */
+  multiboot_uint32_t header_length;
+
+  /* The above fields plus this one must equal 0 mod 2^32. */
+  multiboot_uint32_t checksum;
+};
+
+struct multiboot_header_tag
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_information_request
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t requests[0];
+};
+
+struct multiboot_header_tag_address
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t header_addr;
+  multiboot_uint32_t load_addr;
+  multiboot_uint32_t load_end_addr;
+  multiboot_uint32_t bss_end_addr;
+};
+
+struct multiboot_header_tag_entry_address
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t entry_addr;
+};
+
+struct multiboot_header_tag_console_flags
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t console_flags;
+};
+
+struct multiboot_header_tag_framebuffer
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t width;
+  multiboot_uint32_t height;
+  multiboot_uint32_t depth;
+};
+
+struct multiboot_header_tag_module_align
+{
+  multiboot_uint16_t type;
+  multiboot_uint16_t flags;
+  multiboot_uint32_t size;
+  multiboot_uint32_t width;
+  multiboot_uint32_t height;
+  multiboot_uint32_t depth;
+};
+
+struct multiboot_color
+{
+  multiboot_uint8_t red;
+  multiboot_uint8_t green;
+  multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry
+{
+  multiboot_uint64_t addr;
+  multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE		1
+#define MULTIBOOT_MEMORY_RESERVED		2
+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE       3
+#define MULTIBOOT_MEMORY_NVS                    4
+  multiboot_uint32_t type;
+  multiboot_uint32_t zero;
+} __attribute__((packed));
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_tag
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+};
+
+struct multiboot_tag_string
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  char string[0];
+};
+
+struct multiboot_tag_module
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t mod_start;
+  multiboot_uint32_t mod_end;
+  char cmdline[0];
+};
+
+struct multiboot_tag_basic_meminfo
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t mem_lower;
+  multiboot_uint32_t mem_upper;
+};
+
+struct multiboot_tag_bootdev
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t biosdev;
+  multiboot_uint32_t slice;
+  multiboot_uint32_t part;
+};
+
+struct multiboot_tag_mmap
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t entry_size;
+  multiboot_uint32_t entry_version;
+  struct multiboot_mmap_entry entries[0];  
+};
+
+struct multiboot_vbe_info_block
+{
+  multiboot_uint8_t external_specification[512];
+};
+
+struct multiboot_vbe_mode_info_block
+{
+  multiboot_uint8_t external_specification[256];
+};
+
+struct multiboot_tag_vbe
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
+  multiboot_uint16_t vbe_mode;
+  multiboot_uint16_t vbe_interface_seg;
+  multiboot_uint16_t vbe_interface_off;
+  multiboot_uint16_t vbe_interface_len;
+
+  struct multiboot_vbe_info_block vbe_control_info;
+  struct multiboot_vbe_mode_info_block vbe_mode_info;
+};
+
+struct multiboot_tag_framebuffer_common
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+
+  multiboot_uint64_t framebuffer_addr;
+  multiboot_uint32_t framebuffer_pitch;
+  multiboot_uint32_t framebuffer_width;
+  multiboot_uint32_t framebuffer_height;
+  multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB     1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT	2
+  multiboot_uint8_t framebuffer_type;
+  multiboot_uint16_t reserved;
+};
+
+struct multiboot_tag_framebuffer
+{
+  struct multiboot_tag_framebuffer_common common;
+
+  union
+  {
+    struct
+    {
+      multiboot_uint16_t framebuffer_palette_num_colors;
+      struct multiboot_color framebuffer_palette[0];
+    };
+    struct
+    {
+      multiboot_uint8_t framebuffer_red_field_position;
+      multiboot_uint8_t framebuffer_red_mask_size;
+      multiboot_uint8_t framebuffer_green_field_position;
+      multiboot_uint8_t framebuffer_green_mask_size;
+      multiboot_uint8_t framebuffer_blue_field_position;
+      multiboot_uint8_t framebuffer_blue_mask_size;
+    };
+  };
+};
+
+struct multiboot_tag_elf_sections
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint32_t num;
+  multiboot_uint32_t entsize;
+  multiboot_uint32_t shndx;
+  char sections[0];
+};
+
+struct multiboot_tag_apm
+{
+  multiboot_uint32_t type;
+  multiboot_uint32_t size;
+  multiboot_uint16_t version;
+  multiboot_uint16_t cseg;
+  multiboot_uint32_t offset;
+  multiboot_uint16_t cseg_16;
+  multiboot_uint16_t dseg;
+  multiboot_uint16_t flags;
+  multiboot_uint16_t cseg_len;
+  multiboot_uint16_t cseg_16_len;
+  multiboot_uint16_t dseg_len;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT_HEADER */

=== modified file 'physmap.c'
--- physmap.c	2003-07-23 20:29:49 +0000
+++ physmap.c	2010-05-28 22:11:22 +0000
@@ -20,15 +20,40 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#endif
 #include "flash.h"
 
-#ifdef __DJGPP__
+#ifdef CONFIG_STANDALONE
+#if defined (__i386__) || defined (__x86_64__)
+void *sys_physmap(unsigned long phys_addr, size_t len)
+{
+  return (void *) phys_addr;
+}
+
+void physunmap(void *virt_addr, size_t len)
+{
+}
+
+#elif defined __mips
+
+void *sys_physmap(unsigned long phys_addr, size_t len)
+{
+  return (void *) (phys_addr | 0xa0000000);
+}
+
+void physunmap(void *virt_addr, size_t len)
+{
+}
+
+#endif
+#elif defined (__DJGPP__)
 #include <dpmi.h>
 #include <sys/nearptr.h>
 
@@ -179,6 +204,14 @@ 
 }
 #endif
 
+#ifdef CONFIG_STANDALONE
+
+void *physmap_common(const char *descr, unsigned long phys_addr, size_t len, int mayfail, int readonly)
+{
+  return sys_physmap (phys_addr, len);
+}
+
+#else
 #define PHYSMAP_NOFAIL	0
 #define PHYSMAP_MAYFAIL	1
 #define PHYSMAP_RW	0
@@ -241,6 +274,8 @@ 
 	return physmap_common(descr, phys_addr, len, PHYSMAP_MAYFAIL, PHYSMAP_RO);
 }
 
+#endif
+
 #if defined(__i386__) || defined(__x86_64__)
 
 #ifdef __linux__

=== modified file 'print.c'
--- print.c	2003-07-23 20:29:49 +0000
+++ print.c	2010-05-28 21:05:00 +0000
@@ -19,41 +19,55 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <string.h>
 #include <stdlib.h>
+#endif
 #include "flash.h"
 #include "flashchips.h"
 
+static inline void
+cat_str (char **out, const char *in)
+{
+	memcpy (*out, "Unknown,", strlen (in));
+	*out += strlen (in);
+}
 /*
  * Return a string corresponding to the bustype parameter.
  * Memory is obtained with malloc() and can be freed with free().
  */
 char *flashbuses_to_text(enum chipbustype bustype)
 {
-	char *ret = calloc(1, 1);
+	static char ret[sizeof ("Unknown,") + sizeof ("Non-SPI,")
+			+ sizeof ("Parallel,") + sizeof ("LPC,")
+			+ sizeof ("FWH,") + sizeof ("SPI,")
+			+ sizeof ("None,") + 10];
+	char *ptr = ret;
 	if (bustype == CHIP_BUSTYPE_UNKNOWN) {
-		ret = strcat_realloc(ret, "Unknown,");
+		cat_str (&ptr, "Unknown,");
 	/*
 	 * FIXME: Once all chipsets and flash chips have been updated, NONSPI
 	 * will cease to exist and should be eliminated here as well.
 	 */
 	} else if (bustype == CHIP_BUSTYPE_NONSPI) {
-		ret = strcat_realloc(ret, "Non-SPI,");
+		cat_str (&ptr, "Non-SPI,");
 	} else {
 		if (bustype & CHIP_BUSTYPE_PARALLEL)
-			ret = strcat_realloc(ret, "Parallel,");
+			cat_str (&ptr, "Parallel,");
 		if (bustype & CHIP_BUSTYPE_LPC)
-			ret = strcat_realloc(ret, "LPC,");
+			cat_str (&ptr, "LPC,");
 		if (bustype & CHIP_BUSTYPE_FWH)
-			ret = strcat_realloc(ret, "FWH,");
+			cat_str (&ptr, "FWH,");
 		if (bustype & CHIP_BUSTYPE_SPI)
-			ret = strcat_realloc(ret, "SPI,");
+			cat_str (&ptr, "SPI,");
 		if (bustype == CHIP_BUSTYPE_NONE)
-			ret = strcat_realloc(ret, "None,");
+			cat_str (&ptr, "None,");
 	}
 	/* Kill last comma. */
-	ret[strlen(ret) - 1] = '\0';
-	ret = realloc(ret, strlen(ret) + 1);
+	if (ptr != ret)
+		*(ptr - 1) = '\0';
+	else
+		*ret = 0;
 	return ret;
 }
 

=== modified file 'programmer.c'
--- programmer.c	2003-05-13 20:02:26 +0000
+++ programmer.c	2010-05-28 21:32:53 +0000
@@ -18,7 +18,9 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <stdlib.h>
+#endif
 #include "flash.h"
 
 /* No-op shutdown() for programmers which don't need special handling */

=== modified file 'satasii.c'
--- satasii.c	2003-06-24 21:51:16 +0000
+++ satasii.c	2010-05-28 22:17:05 +0000
@@ -20,8 +20,10 @@ 
 
 /* Datasheets can be found on http://www.siliconimage.com. Great thanks! */
 
+#ifndef CONFIG_STANDALONE
 #include <stdlib.h>
 #include <string.h>
+#endif
 #include "flash.h"
 
 #define PCI_VENDOR_ID_SII	0x1095
@@ -72,7 +74,9 @@ 
 
 int satasii_shutdown(void)
 {
+#ifndef CONFIG_STANDALONE
 	free(programmer_param);
+#endif
 	pci_cleanup(pacc);
 	release_io_perms();
 	return 0;

=== modified file 'spi.c'
--- spi.c	2003-07-23 20:33:03 +0000
+++ spi.c	2010-05-28 20:41:00 +0000
@@ -22,7 +22,9 @@ 
  * Contains the generic SPI framework
  */
 
+#ifndef CONFIG_STANDALONE
 #include <string.h>
+#endif
 #include "flash.h"
 #include "flashchips.h"
 #include "chipdrivers.h"

=== modified file 'spi25.c'
--- spi25.c	2003-07-23 20:34:46 +0000
+++ spi25.c	2010-05-28 20:41:00 +0000
@@ -22,7 +22,9 @@ 
  * Contains the common SPI chip driver functions
  */
 
+#ifndef CONFIG_STANDALONE
 #include <string.h>
+#endif
 #include "flash.h"
 #include "flashchips.h"
 #include "chipdrivers.h"

=== modified file 'sst49lfxxxc.c'
--- sst49lfxxxc.c	2003-07-18 06:39:07 +0000
+++ sst49lfxxxc.c	2010-05-28 20:41:00 +0000
@@ -20,7 +20,9 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <stdlib.h>
+#endif
 #include "flash.h"
 #include "chipdrivers.h"
 

=== modified file 'sst_fwhub.c'
--- sst_fwhub.c	2003-07-18 06:39:07 +0000
+++ sst_fwhub.c	2010-05-28 20:41:00 +0000
@@ -22,8 +22,10 @@ 
 
 /* Adapted from the Intel FW hub stuff for 82802ax parts. */
 
+#ifndef CONFIG_STANDALONE
 #include <stdlib.h>
 #include <string.h>
+#endif
 #include "flash.h"
 #include "chipdrivers.h"
 

=== added file 'standalone.h'
--- standalone.h	1970-01-01 00:00:00 +0000
+++ standalone.h	2010-05-28 22:49:18 +0000
@@ -0,0 +1,186 @@ 
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Vladimir Serbinenko <phcoder@gmail.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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+typedef unsigned long size_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+#define NULL ((void *) 0)
+
+struct pci_dev
+{
+  int bus, dev, func;
+  uint32_t device_id;
+};
+
+struct pci_filter;
+
+static inline char
+tolower (char in)
+{
+  if (in >= 'A' && in <= 'Z')
+    return in - 'A' + 'a';
+  return in;
+}
+
+static inline int
+strcmp (const char *str1, const char *str2)
+{
+  while (*str1 == *str2)
+    {
+      if (!*str1)
+	return 0;
+      str1++;
+      str2++;
+    }
+  if (*str1 < *str2)
+    return -1;
+  else
+    return +1;
+}
+
+static inline int
+strcasecmp (const char *str1, const char *str2)
+{
+  while (tolower (*str1) == tolower (*str2))
+    {
+      if (!*str1)
+	return 0;
+      str1++;
+      str2++;
+    }
+  if (tolower (*str1) < tolower (*str2))
+    return -1;
+  else
+    return +1;
+}
+
+static inline int
+strncmp (const char *str1, const char *str2, size_t n)
+{
+  while (n-- && *str1 == *str2)
+    {
+      if (!*str1)
+	return 0;
+      str1++;
+      str2++;
+    }
+  if (n == 0)
+    return 0;
+  if (*str1 < *str2)
+    return -1;
+  else
+    return +1;
+}
+
+static inline size_t
+strlen (const char *str)
+{
+  const char *ptr;
+  for (ptr = str; *ptr; ptr++);
+  return ptr - str;
+}
+
+static inline int
+memcmp (const void *ptr1, const void *ptr2, size_t n)
+{
+  while (n--)
+    {
+      if (*(const uint8_t *) ptr1 < *(const uint8_t *) ptr2)
+	return -1;
+      if (*(const uint8_t *) ptr1 > *(const uint8_t *) ptr2)
+	return +1;
+
+      ptr1 = (const uint8_t *) ptr1 + 1;
+      ptr2 = (const uint8_t *) ptr2 + 1;
+    }
+  return 0;
+}
+
+/* Not efficient but does the job.  */
+static inline char *
+strstr (char *haystack, const char *needle)
+{
+  char *ptr = haystack;
+  int ndlen = strlen (needle);
+  for (ptr = haystack; *ptr; ptr++)
+    if (strncmp (ptr, needle, ndlen) == 0)
+      return ptr;
+  return NULL;
+}
+
+static inline char *
+strchr (char *haystack, char needle)
+{
+  char *ptr;
+  for (ptr = haystack; *ptr; ptr++)
+    if (*ptr == needle)
+      return ptr;
+  return NULL;
+}
+
+static inline void
+memcpy (void *ptr1, const void *ptr2, size_t n)
+{
+  while (n--)
+    {
+      *(uint8_t *) ptr1 = *(const uint8_t *) ptr2;
+    
+      ptr1 = (uint8_t *) ptr1 + 1;
+      ptr2 = (const uint8_t *) ptr2 + 1;
+    }
+}
+
+void printf (char *str, ...);
+
+uint32_t
+pci_read_long (struct pci_dev *dev, unsigned addr);
+
+void
+pci_write_word (struct pci_dev *dev, unsigned addr, uint16_t val);
+
+struct pci_access;
+
+static inline void
+pci_cleanup (struct pci_access *pacc)
+{
+}
+
+static inline void
+memset (void *ptr, int val, size_t n)
+{
+  uint8_t *ptr2 = ptr;
+  while (n--)
+    *ptr2++ = val;
+}
+
+#define PCI_BASE_ADDRESS_0 0x10
+#define PCI_BASE_ADDRESS_2 0x18
+#define PCI_BASE_ADDRESS_5 0x24
+
+static inline int
+isprint (char c)
+{
+  return (c >= ' ') && (c < 0x7f);
+}
+
+extern uint8_t *module_image, *module_layout;
+extern size_t module_image_size, module_layout_size;

=== added file 'startup.S'
--- startup.S	1970-01-01 00:00:00 +0000
+++ startup.S	2010-05-28 23:03:45 +0000
@@ -0,0 +1,41 @@ 
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Vladimir Serbinenko  <phcoder@gmail.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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include "multiboot2.h"
+
+	.align MULTIBOOT_HEADER_ALIGN
+mbhead:	
+	.long MULTIBOOT2_HEADER_MAGIC
+	.long MULTIBOOT_ARCHITECTURE_MIPS32
+	.long mbhead_end - mbhead
+	.long -(MULTIBOOT2_HEADER_MAGIC+MULTIBOOT_ARCHITECTURE_MIPS32+(mbhead_end - mbhead))
+mbhead_end:
+
+_start:
+	lui $sp, %hi(stack_end)
+
+	j yeeloong_standalone_entry
+	 addiu $sp, $sp, %lo(stack_end)
+
+	.bss
+	.align 8
+stack_start:
+	. = stack_start + 65536
+stack_end:	
\ No newline at end of file

=== modified file 'stm50flw0x0x.c'
--- stm50flw0x0x.c	2003-07-19 03:07:07 +0000
+++ stm50flw0x0x.c	2010-05-28 20:41:00 +0000
@@ -27,8 +27,10 @@ 
  * ST M50FLW080B (not yet tested)
  */
 
+#ifndef CONFIG_STANDALONE
 #include <string.h>
 #include <stdlib.h>
+#endif
 #include "flash.h"
 #include "flashchips.h"
 #include "chipdrivers.h"

=== added file 'udelay_yeeloong.c'
--- udelay_yeeloong.c	1970-01-01 00:00:00 +0000
+++ udelay_yeeloong.c	2010-05-28 21:33:07 +0000
@@ -0,0 +1,42 @@ 
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Vladimir Serinenko <phcode@gmail.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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include "flash.h"
+
+__attribute__ ((noinline)) void myusec_delay(int usecs)
+{
+  uint32_t high = 0;
+  uint32_t last = 0, start = 0;
+  uint32_t low;
+
+  asm volatile ("mfc0 %0, $9": "=r" (start));
+  last = start;
+
+  while (1)
+    {
+      asm volatile ("mfc0 %0, $9": "=r" (low));
+      if (low < last)
+	high++;
+      /* FIXME: retrieve from mbi*/
+      if (((((uint64_t) high) << 32) | low) - ((uint64_t) start) > 400 * usecs)
+	return;
+      last = low;
+    }
+}

=== modified file 'w29ee011.c'
--- w29ee011.c	2003-07-18 06:39:07 +0000
+++ w29ee011.c	2010-05-28 20:41:01 +0000
@@ -18,7 +18,9 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifndef CONFIG_STANDALONE
 #include <string.h>
+#endif
 #include "flash.h"
 #include "chipdrivers.h"
 

=== added file 'yeeloong.c'
--- yeeloong.c	1970-01-01 00:00:00 +0000
+++ yeeloong.c	2010-05-28 22:49:28 +0000
@@ -0,0 +1,79 @@ 
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Vladimir Serbinenko  <phcoder@gmail.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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <multiboot2.h>
+
+#define ARGC_MAX 64
+
+uint8_t *module_image, *module_layout;
+size_t module_image_size, module_layout_size;
+
+void
+yeeloong_standalone_entry (int magic, void *mbi)
+{
+  int argc = 0;
+  char *args = NULL;
+  void *mbiptr;
+  int mbilen;
+  if (magic != MULTIBOOT2_BOOTLOADER_MAGIC)
+    {
+      printf ("No bootloader signature found.\n");
+      while (1);
+    }
+
+  argc = 1;
+  argv[0] = "standalone";
+
+  mbiptr = mbi;
+  mbilen = *(int *) mbiptr;
+  mbiptr = (char *) mbiptr + 8;
+  while (mbiptr < mbi + mbilen)
+    {
+      struct multiboot_header_tag *tag = mbiptr;
+      mbiptr = (char *) mbiptr + (tag->size + MULTIBOOT_TAG_ALIGN - 1)
+	& ~(MULTIBOOT_TAG_ALIGN - 1);
+      if (tag->type == MULTIBOOT_TAG_TYPE_END)
+	break;
+      switch (tag->type)
+	{
+	case MULTIBOOT_TAG_TYPE_CMDLINE:
+	  args = ((multiboot_tag_string *) tag)->string;
+	  break;
+	case MULTIBOOT_TAG_TYPE_MODULE:
+	  {
+	    struct multiboot_tag_module *tag_ = tag;
+	    if (memcmp (tag_->cmdline, "flash", sizeof ("flash")) == 0)
+	      {
+		module_image = tag_->mod_start;
+		module_image_size = tag_->mod_end - tag_->mod_start;
+	      }
+	    if (memcmp (tag_->cmdline, "layout", sizeof ("layout")) == 0)
+	      {
+		module_layout = tag_->mod_start;
+		module_layout_size = tag_->mod_end - tag_->mod_start;
+	      }
+	  }
+	  break;
+	}
+    }
+  cli_standalone (args, module);
+  /* FIXME: wait a timeout and reboot.  */
+  while (1);
+}