diff -rubB --new-file cromwell-base/boot/LoadLinux.c cromwell/boot/LoadLinux.c
--- cromwell-base/boot/LoadLinux.c	Sun Apr  8 13:57:01 2007
+++ cromwell/boot/LoadLinux.c	Sun Apr  8 17:39:24 2007
@@ -21,6 +21,7 @@
 #include "BootParser.h"
 #include "config.h"
 #include "iso_fs.h"
+#include "bootinfo.h"
 
 //Grub bits
 unsigned long saved_drive;
@@ -31,6 +32,7 @@
 static int nRet;
 static u32 dwKernelSize= 0, dwInitrdSize = 0;
 
+struct bootinfo freebsd_bootinfo;
 
 void ExittoLinux(CONFIGENTRY *config);
 void startLinux(void* initrdStart, unsigned long initrdSize, const char* appendLine, unsigned int entry);
@@ -39,6 +41,7 @@
 
 void try_elf_boot (char* data, int len);
 
+CONFIGENTRY* bootingEntry = NULL;
 
 void BootPrintConfig(CONFIGENTRY *config) {
 	int CharsProcessed=0, CharsSinceNewline=0, Length=0;
@@ -155,6 +158,8 @@
 	char *szGrub;
 	u8* tempBuf;
 
+	bootingEntry = config;
+
 	szGrub = (char *) malloc(265+4);
         memset(szGrub,0,256+4);
         
@@ -260,6 +265,8 @@
 	static FATXFILEINFO infoinitrd;
 	u8* tempBuf;
 
+	bootingEntry = config;
+
 	memset((u8 *)KERNEL_SETUP,0,4096);
 	memset(&fileinfo,0x00,sizeof(fileinfo));
 	memset(&infokernel,0x00,sizeof(infokernel));
@@ -406,6 +413,8 @@
 int LoadKernelCdrom(CONFIGENTRY *config) {
 	u8* tempBuf;
 	
+	bootingEntry = config;
+	
 	// Use INITRD_START as temporary location for loading the Kernel 
 	tempBuf = (u8*)INITRD_START;
 	dwKernelSize=BootIso9660GetFile(config->drive,config->szKernel, tempBuf, MAX_KERNEL_SIZE);
@@ -545,6 +554,43 @@
 	startLinux((void*)INITRD_START, dwInitrdSize, config->szAppend, 0x100000);
 }
 	
+/*
+ * This code fills out a FreeBSD bootinfo structure. As expected, this is
+ * only needed if booting FreeBSD _AND_ you want to pass a kernel environment
+ * parameters to the OS.
+ *
+ * The structure must be above the kernel memory, since FreeBSD will try to
+ * access it relative to the kernel mapping. Therefore, we use a large offset
+ * (any hope no one will ever try to load a kernel there; but seeing the
+ *  Xbox only has 64MB memory this seems unlikely)
+ *
+ * 'cmdline' is taken from the 'append' parameter, and must be in the format
+ * 'foo=bar,hello=world' (each name=value pair, separated by ,)
+ */
+void
+freebsd_setup_bootinfo(struct bootinfo* bi, CONFIGENTRY* config)
+{
+#define KENV_OFFS (0x700000)
+	char* karg = (char*)KENV_OFFS;
+
+	memset(bi, 0, sizeof(struct bootinfo));
+	bi->bi_version = BOOTINFO_VERSION;
+	bi->bi_size = sizeof(struct bootinfo);
+
+	if (config != NULL && config->szAppend != NULL) {
+		const char *ptr = config->szAppend;
+		do {
+			while (*ptr != ',' && *ptr != '\0') {
+				*karg++ = *ptr++;
+			}
+			if (*ptr == ',') {
+				*karg++ = '\0'; *ptr++;
+			}
+		} while (*ptr != '\0');
+		*karg = '\0';
+		bi->bi_envp = (uint32_t)KENV_OFFS;
+	}
+}
 
 void startLinux(void* initrdStart, unsigned long initrdSize, const char* appendLine, unsigned int entry)
 {
@@ -579,6 +625,18 @@
 	// clear idt area
 	memset((void*)IDT_LOC,0x0,1024*8);
 	
+	/*
+	 * This is a bit of a kludge - If an ELF file is found, Etherboot
+	 * will happily rip whatever ELF text section is in there and pass it
+	 * as arguments (without doing things like concatination)
+	 *
+	 * We solve this by letting Etherboot do whatever it wants, and always
+	 * passing the booting entry to the bootinfo setup code. Linux won't
+	 * mind (as it never reads this information anyway), and we'll be
+	 * happy...
+	 */
+	freebsd_setup_bootinfo(&freebsd_bootinfo, bootingEntry);
+	
 	__asm__ ("movl %0,%%ebx" : : "a" (entry));	/* ebx = entry */
 	
 	__asm __volatile__ (
@@ -637,21 +695,25 @@
 
 	// This is for FreeBSD; i386/i386/locore.s expects certain stack
 	// values for bootload info - Linux doesn't care
-	"pushl	$0x0\n"
-	"pushl	$0x0\n"
-	"pushl	$0x0\n"
-	"pushl	$0x0\n"
-	"pushl	$0x0\n"
+	"pushl	$freebsd_bootinfo\n"	// bootinfo
+	"pushl	$0x0\n"			// 0
+	"pushl	$0x0\n"			// 0
+	"pushl	$0x0\n"			// 0
+	"pushl	$0x0\n"			// bootdev
+	"pushl	$0x80000000\n"		// howto (RB_BOOTINFO)
+
+	"pushl	$retaddr\n"		// return address (we fake a callf)
 
 	"pushl	$0x10\n"
 	"pushl	%ebx\n"			// 0x10:ebx is the entry point
 	"xor	%ebx,%ebx\n"		// clean leftover ebx (held entry point)
 	".byte	0xcb\n	"		// retf
-	);
 	
-	// We are not longer here, we are already in the Linux loader, we never come back here
+	// this is the value we use as our return address.
+"retaddr:\n"
+	);
 	
-	// See you again in Linux then	
+	printk("OS did a return... why?\n");
 	while(1);
 }
 
diff -rubB --new-file cromwell-base/include/bootinfo.h cromwell/include/bootinfo.h
--- cromwell-base/include/bootinfo.h	Thu Jan  1 01:00:00 1970
+++ cromwell/include/bootinfo.h	Sun Apr  8 17:42:08 2007
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (C) 1994 by Rodney W. Grimes, Milwaukie, Oregon  97222
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer as
+ *    the first lines of this file unmodified.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Rodney W. Grimes.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RODNEY W. GRIMES ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL RODNEY W. GRIMES BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/include/bootinfo.h,v 1.15 2003/04/04 16:35:15 phk Exp $
+ */
+
+#ifndef	_MACHINE_BOOTINFO_H_
+#define	_MACHINE_BOOTINFO_H_
+
+/* Only change the version number if you break compatibility. */
+#define	BOOTINFO_VERSION	1
+
+#define	N_BIOS_GEOM		8
+
+/* XXX does not belong here*/
+#define RB_VERBOSE      0x800   /* print all potentially useful info */
+#define RB_BOOTINFO     0x80000000      /* have `struct bootinfo *' arg */
+
+/*
+ * A zero bootinfo field often means that there is no info available.
+ * Flags are used to indicate the validity of fields where zero is a
+ * normal value.
+ */
+struct bootinfo {
+	uint32_t	bi_version;
+	uint32_t	bi_kernelname;		/* represents a char * */
+	uint32_t	bi_nfs_diskless;	/* struct nfs_diskless * */
+				/* End of fields that are always present. */
+#define	bi_endcommon	bi_n_bios_used
+	uint32_t	bi_n_bios_used;
+	uint32_t	bi_bios_geom[N_BIOS_GEOM];
+	uint32_t	bi_size;
+	uint8_t		bi_memsizes_valid;
+	uint8_t		bi_bios_dev;		/* bootdev BIOS unit number */
+	uint8_t		bi_pad[2];
+	uint32_t	bi_basemem;
+	uint32_t	bi_extmem;
+	uint32_t	bi_symtab;		/* struct symtab * */
+	uint32_t	bi_esymtab;		/* struct symtab * */
+				/* Items below only from advanced bootloader */
+	uint32_t	bi_kernend;		/* end of kernel space */
+	uint32_t	bi_envp;		/* environment */
+	uint32_t	bi_modulep;		/* preloaded modules */
+};
+
+#endif	/* !_MACHINE_BOOTINFO_H_ */
diff -rubB --new-file cromwell-base/lib/misc/BootParser.h cromwell/lib/misc/BootParser.h
--- cromwell-base/lib/misc/BootParser.h	Tue Nov 30 02:23:48 2004
+++ cromwell/lib/misc/BootParser.h	Sun Apr  8 17:14:45 2007
@@ -28,5 +28,7 @@
 	struct CONFIGENTRY *nextConfigEntry;
 } CONFIGENTRY;
 
+extern CONFIGENTRY* bootingEntry;
+
 CONFIGENTRY* ParseConfig(char *szBuffer, unsigned int fileLen, char *szPath);
 #endif // _BootParser_H_
