LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Etienne Lorrain <etienne_lorrain@yahoo.fr>
To: linux-kernel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] Compressed ia32 ELF file generation for loading by Gujin 2/3
Date: Mon, 5 Feb 2007 23:58:20 +0000 (GMT)	[thread overview]
Message-ID: <94642.67267.qm@web26914.mail.ukl.yahoo.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 373 bytes --]

That is the main file BIOS information gathering realmode.c




	

	
		
___________________________________________________________________________ 
Découvrez une nouvelle façon d'obtenir des réponses à toutes vos questions ! 
Profitez des connaissances, des opinions et des expériences des internautes sur Yahoo! Questions/Réponses 
http://fr.answers.yahoo.com

[-- Attachment #2: gujin-patch-2.6.20-2 --]
[-- Type: application/octet-stream, Size: 64516 bytes --]

diff -uprN -X linux-2.6.20/Documentation/dontdiff linux-2.6.20/arch/i386/kernel/realmode.c linux-2.6.20-gujin/arch/i386/kernel/realmode.c
--- linux-2.6.20/arch/i386/kernel/realmode.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.20-gujin/arch/i386/kernel/realmode.c	2007-02-05 21:27:01.000000000 +0000
@@ -0,0 +1,1997 @@
+/*
+ *  This file "realmode.c" is licensed with the same license as the Linux
+ * kernel; anyway the mapping of the data structure produced is owned by
+ * Linux kernel copyright owner(s) for a long time.
+ *
+ *  The main use of this file is to produce the real-mode part of the
+ * ELF file vmlinux (at the root of the linux tree), this file will
+ * be (usually) stripped of debug info and then compressed by GZIP
+ * to make a "Gujin native bootable file" with the "kgz" extension.
+ *  This real-mode part is removed (by objdump) from the binary later
+ * in the process if you generate a bzImage file.
+ *  This real-mode part is used at boot time to get informations from
+ * the BIOS: memory size, disk present, video mode... and is no more
+ * accessible once the processor has switch to protected-mode.
+ *
+ * Gujin homepage is at: http://gujin.org/ ; it is itself licensed
+ * under the terms of the GNU General Public License, version 2.
+ * Gujin is Copyright (C) 1999-2005 Etienne Lorrain, fingerprint (2D3AF3EA):
+ *   2471 DF64 9DEE 41D4 C8DB 9667 E448 FF8C 2D3A F3EA
+ * E-Mail: etienne dot lorrain at gujin dot org
+ *
+ *  First version has been written by Etienne Lorrain in December 2004.
+ */
+
+/*
+ * Do not touch - used to generate real mode ia32 code and manage
+ * the inter-segment call transparently, after maximum 4 Kbytes
+ * of real mode rodata/data has been copied into %ds segment.
+ *
+ * Having constant/initialised variable in here is a bit tricky,
+ * it uses the fact that since Gujin-1.0, the segment ".fourKsegment"
+ * containning the only variable "fourKbuffer" (of size 4 Kbytes)
+ * is located at %ds:0 i.e. before the ".rodata" of Gujin.
+ * Note that here the code segment is local but the data segment
+ * (and the stack segment) is the one of Gujin for obvious reasons.
+ * The first person modifying data at address over %ds:0x1000
+ * get all the blame for any bug happening in Gujin, in between
+ * the last and the next big bang, and it is a pretty long time.
+ * <smile>You don't like my memory protection system?</smile>
+ */
+asm("	.psize 0				\n"
+    "	.code16gcc				\n"
+    "	.section .init.text16,\"ax\",@progbits	\n"
+    "	push	%di				\n"
+    "	push	%si				\n"
+    "	mov	$_sdata16,%si			\n"
+    "	mov	%si,%di				\n"
+    "	mov	$_edata16,%cx			\n"
+    "	and	$0xFFF,%cx			\n"
+    "	sub	%si,%cx				\n"
+    "	shr	$2,%cx				\n"
+    "	rep movsl %cs:(%si),%es:(%di)		\n"
+    "	pop	%si				\n"
+    "	pop	%di				\n"
+    "	calll	linux_set_params		\n"
+    "	lretw					\n"
+    "	.previous				\n"
+);
+
+#include "asm/realmode.h"
+
+/*
+ * Those need to be used because there is no way to set the default
+ * segment name used for ".text", ".data", ".rodata*" and ".bss"
+ * It would be nice to be able to do: asm(".equ .data, .data16");
+ * or shall that be managed by the compiler - and by compilation
+ * switch or by the attribute of functions?
+ * This file is pre-linked (section with same name grouped together)
+ * in "arch/i386/kernel/built-in.o" so no hope to manage it in
+ * the final linker file if it uses the same section names.
+ * Maybe if "arch/i386/kernel/built-in.o" could be an archive?
+ * Maybe it is "the right way (TM)" to use different section names
+ * so that those functions can be located in different source files.
+ * Maybe the section name shall be automatically changed using
+ * objcopy in the realmode.o file, just after compilation.
+ * Maybe the segment names shall be changed by sed in the
+ * assembler file.
+ * The method used here works and is as fool proof as possible.
+ *
+ * Unfortunately, I do not know how to use inline strings here,
+ * i.e. puts("hello world"); will not work due to the segment
+ * used to store the constant "hello world".
+ * Same for the implicit table generated by a big switch().
+ * This would generate a prohibited cross reference at linker time.
+ *
+ * I also need to add that using GCC to generate real-mode i386
+ * executable has a major limitation: no use of library compiled
+ * for protected mode. If your source make GCC to call memcpy(),
+ * memset(), strcpy()... then you have to provide them yourself.
+ * The same thing apply if you multiply or divide 64 bit numbers
+ * by non power of two. Adding and substracting of long long is OK.
+ */
+#define CONST		__attribute__ ((section (".rodata16"))) const
+#define VARIABLE	__attribute__ ((section (".data16")))
+#define BSS		__attribute__ ((section (".bss16")))
+#define CODE		__attribute__ ((section (".text16")))
+
+#if 0
+/*
+ * When compiling this file, some combination of GCC and options
+ * will call memset() in the assembly generated. You can check it
+ * by typing "make arch/i386/kernel/realmode.s".
+ * They cannot be inline because they are _called_ by the compiler.
+ * It is not possible to access the standard one because its
+ * hexadecimal coding is for protected mode, and not possible to
+ * code it in assembler because of we do not know the calling
+ * convension (GCC optimisations like "-mtrd", "-mregparm=3").
+ * We also cannot have two memcpy() nor memset() in the same
+ * final link, so we rename them in assembler.
+ * This part is currently disabled due to a problem in the linker
+ * but right now no GCC switch combination produces such
+ * memset/memcpy calls with a Linux supported compiler.
+ */
+CODE void code16_memcpy (char *dest, const char *src, unsigned nb)
+{
+	while (nb--)
+		*dest++ = *src++;
+}
+CODE void code16_memset (char *dest, unsigned val, unsigned nb)
+{
+	while (nb--)
+		*dest++ = val;
+}
+asm (
+    "memcpy = code16_memcpy \n"
+    "memset = code16_memset \n"
+);
+#endif
+
+/**
+ ** Few debug functions and how to use them, including how to declare
+ ** variables and constants. For complex debug, you may want to
+ ** check dbgload.exe of Gujin. The following debug uses the VIDEO BIOS
+ ** to display messages so will not work in VESA modes when the VESA
+ ** BIOS do not support printing characters in current video mode
+ ** (bit BIOS_output_supported of VESA_modeinfo_t / struct screen_info)
+ **/
+//#define TEST_VGAPRINT
+
+#ifdef TEST_VGAPRINT
+CONST char test_before[] = "test: 0x";
+VARIABLE unsigned test_val = 0x089ABC0;
+CONST char test_middle[] = ", test_val2 = 0x";
+BSS unsigned test_val2;
+VARIABLE char test_after[] = ".\r\n";
+
+#define PUSHALL "pushw %%ds; pushw %%es; pushw %%fs; pushw %%gs; pushal\n"
+#define POPALL  "popal; popw %%gs; popw %%fs; popw %%es; popw %%ds\n"
+
+CODE static void vgaputs (const char *string)
+{
+	while (*string != '\0')
+		asm(PUSHALL
+		    "	movw	$0x0007,%%bx\n	int	$0x10	\n"
+		    POPALL
+		    : : "a" (0x0E00 | (unsigned char)*string++));
+}
+
+CODE static void vgaputx (unsigned val)
+{
+	unsigned digit_shift = 7 * 4;
+
+	while (digit_shift && (val & (0xF << digit_shift)) == 0)
+		digit_shift -= 4;
+	for (;;) {
+		asm(PUSHALL
+		    "	movw	$0x0007,%%bx	\n"
+		    "	sahf	# clear AF	\n"
+		    "	aaa			\n"
+		    "	aad	$0x11		\n"
+		    "	add	$0x0E30,%%ax	\n"
+		    "	int	$0x10		\n"
+		    POPALL
+		    : : "a" ((val >> digit_shift) & 0x0F));
+		if (digit_shift == 0)
+			break;
+		digit_shift -= 4;
+	}
+}
+
+CODE static inline void vga_wait_seconds (unsigned seconds)
+{
+	unsigned nb_microsec = seconds * 1000 * 1000;
+	unsigned short status;
+
+	asm volatile ("	int	$0x15	# _BIOS_wait "
+	     : "=a" (status)
+	     : "a" ((unsigned short)0x8600), "d" (nb_microsec & 0xFFFF),
+		 "c" (nb_microsec >> 16));
+}
+
+extern inline void test_vgaprint (void)
+{
+	unsigned stackptr;
+	static CONST char stkmsg[] = ", sp = 0x";
+
+	asm (" mov	%%esp,%0 " : "=r" (stackptr));
+	test_val2 = 0x1234fedc;
+
+	vgaputs(test_before);
+	vgaputx(test_val);
+	vgaputs(test_middle);
+	vgaputx(test_val2);
+	vgaputs(stkmsg);
+	vgaputx(stackptr);
+	vgaputs(test_after);
+	vga_wait_seconds(7);
+}
+
+#define DBG(startstr, variable, endstr) { \
+	static CONST char before[]=startstr, after[] = endstr;	\
+	vgaputs(before); vgaputx(variable); vgaputs(after);	\
+	}
+#define DBG_WAIT()	vga_wait_seconds(7)
+#else
+#define test_vgaprint()	/*nothing*/
+#define DBG(startstr, variable, endstr)	/*nothing*/
+#define DBG_WAIT()	/*nothing*/
+#endif
+
+/**
+ ** All the non BIOS related, low level functions we use:
+ **/
+extern inline unsigned peekb (farptr adr)
+{
+	unsigned returned;
+	unsigned short scratch;
+	extern char memory[];
+
+      asm("	pushl	%2		\n"
+	  "	popw	%w0		\n"
+	  "	popw	%%fs		\n"
+	  "	movzbl	%%fs:(%w0),%1	\n"
+	  : "=bSDB" (scratch), "=r" (returned)
+	  : "g" (adr), "m" (*memory) );
+	return returned;
+}
+
+extern inline unsigned peekw (farptr adr)
+{
+	unsigned returned;
+	unsigned short scratch;
+	extern char memory[];
+
+      asm("	pushl	%2		\n"
+	  "	popw	%w0		\n"
+	  "	popw	%%fs		\n"
+	  "	movzwl	%%fs:(%w0),%1	\n"
+	  : "=bSDB" (scratch), "=r" (returned)
+	  : "g" (adr), "m" (*memory) );
+	return returned;
+}
+
+extern inline void outb (unsigned short port, unsigned char data)
+{
+	asm volatile (" outb %0,%1 " : : "a" (data), "dN" (port));
+}
+
+extern inline unsigned char inb (unsigned short port)
+{
+	unsigned char result;
+	asm volatile (" inb %1,%0 " : "=a" (result) : "dN" (port));
+	return result;
+}
+
+extern inline void short_delay (unsigned count)
+{
+	asm volatile (" loopl . \n" : "+c" (count));
+}
+
+extern inline unsigned char getnvram (unsigned char addr)
+{
+	outb(0x70, addr & ~0x80);	/* bit 7 cleared: NMI enabled */
+	short_delay(1000);	/* wait 1000 assembly instructions */
+	return inb(0x71);
+}
+
+__attribute__ ((const)) extern inline farptr
+stack_farptr (const void *data)
+{
+	unsigned stackseg_mask;  /* stack is max 64 K */
+
+	asm (" mov %%ss,%0 \n" : "=r" (stackseg_mask));
+	return (farptr)((stackseg_mask << 16) | (unsigned) data);
+}
+
+/**
+ ** Generic BIOS calls:
+ **/
+
+extern inline struct shift_flags_str {
+	unsigned char right_shift_key_pressed	: 1;
+	unsigned char left_shift_key_pressed	: 1;
+	unsigned char control_key_pressed	: 1;
+	unsigned char alternate_key_pressed	: 1;
+	unsigned char scroll_lock_active	: 1;
+	unsigned char num_lock_active		: 1;
+	unsigned char caps_lock_active		: 1;
+	unsigned char insert_active		: 1;
+} _BIOS_get_shift_flags (void)
+{
+	struct shift_flags_str flags;
+
+	asm (" int $0x16 # _BIOS_get_shift_flags"
+	     : "=a" (flags)
+	     : "a" ((unsigned short)0x0200) );
+	return flags;
+}
+
+extern inline farptr _BIOS_getConfiguration (void)
+{
+	unsigned char error;
+	farptr conf;
+
+	asm ("	pushl	%%es						\n"
+	     "	stc							\n"
+	     "	int	$0x15		# _BIOS_getConfiguration	\n"
+	     "	setc	%%al						\n"
+	     "	pushw	%%es						\n"
+	     "	pushw	%%bx						\n"
+	     "	popl	%%ebx						\n"
+	     "	popl	%%es						\n"
+	     : "=a" (error), "=b" (conf)
+	     : "a" ((unsigned short)0xC000) );
+	if (error)
+		return (farptr)0;
+	return conf;
+}
+
+extern inline void
+get_bios_conf (farptr adr, struct sys_desc_table_info *sys_desc_table)
+{
+	unsigned nbbyte = sizeof(struct sys_desc_table_info);
+
+	asm ("	pushl	%%esi				\n"
+	     "	popw	%%si				\n"
+	     "	popw	%%fs				\n"
+	     "	cld					\n"
+	     "	rep movsb %%fs:(%%si),%%es:(%%di)	\n"
+	     : "+S" (adr), "+D" (sys_desc_table), "+c" (nbbyte), "=X" (*sys_desc_table)
+	     );
+}
+
+extern inline unsigned char
+_BIOS_getExtendedMemory (unsigned short *sizeinKb)
+{
+	unsigned char error;
+
+	asm ("	int	$0x15	# _BIOS_getExtendedMemory	\n"
+	     "	setc	%0					\n"
+	     : "=qm" (error), "=a" (*sizeinKb)
+	     : "a" ((unsigned short)0x8800)
+	     );
+	return error;	/* 0 if no error */
+}
+
+struct MemoryMap_str {
+	unsigned long long base, length;
+	enum { MemAvailable = 1, MemSpecial = 2,
+		Mem_ACPI_reclaim = 3, Mem_ACPI_NVS = 4
+	} type:32;
+} __attribute__ ((packed));
+
+extern inline unsigned
+_BIOS_QueryMemoryMap (unsigned *cont_val, unsigned bufsize,
+		      struct e820map_info *buffer)
+{
+	/* inline */ const unsigned smapsig = 0x534D4150;	/* 'SMAP' in big endian */
+	unsigned smap_res = 0xE820U, actual_len;
+
+	asm volatile ("	int     $0x15   # _BIOS_QueryMemoryMap		\n"
+		      "	jnc	1f					\n"
+		      "	xorl	%%eax,%%eax				\n"
+		      "	1:						\n"
+		      : "+a" (smap_res), "+b" (*cont_val),
+			"=c" (actual_len), "=X" (*buffer)
+		      : "c" (bufsize), "d" (smapsig), "D" (buffer)	/* in fact %%es:%%di */
+		      );
+	if (smap_res != smapsig)
+		return 0;
+	return actual_len;
+}
+
+extern inline unsigned char
+_APM_installation_check (unsigned short *BCD_version, unsigned short *flags)
+{
+	unsigned char error;
+	unsigned short sig;
+
+	asm ("	int     $0x15	# _APM_installation_check	\n"
+	     "	setc    %0					\n"
+	     : "=qm" (error), "=a" (*BCD_version), "=b" (sig), "=c" (*flags)
+	     : "a" ((unsigned short)0x5300), "b" (0)
+	     );
+	if (error) {
+		*BCD_version &= 0xFF00;	/* keep there error code */
+		*flags = 0;
+	}
+	return error || sig != 0x504D;	/* "PM" */
+}
+
+extern inline unsigned short _APM_disconnect (void)
+{
+	unsigned short error;
+
+	asm volatile ("	int     $0x15	# _APM_disconnect	\n"
+		      "	setc    %%al				\n"
+		      : "=a" (error)
+		      : "a" ((unsigned short)0x5304), "b" (0) );
+	if ((error & 0xFF) == 0)
+		return 0;
+	return error;
+}
+
+extern inline unsigned char
+_APM_connect_32bit (unsigned short *RM_segbase_32,
+		    unsigned *entry_point_offset_32,
+		    unsigned short *RM_segbase_code16,
+		    unsigned short *RM_segbase_data16,
+		    /* APM v1.1: */
+		    unsigned short *APM_BIOS_codeseg_len,
+		    unsigned short *APM_BIOS_dataseg_len)
+{
+	unsigned char error;
+
+	asm volatile ("	xorl	%%edi,%%edi			\n"
+		      "	xorl	%%esi,%%esi			\n"
+		      "	int     $0x15	# _APM_connect_32bit	\n"
+		      "	setc    %0				\n"
+		      : "=qm" (error),
+			"=a" (*RM_segbase_32), "=b" (*entry_point_offset_32),
+			"=c" (*RM_segbase_code16), "=d" (*RM_segbase_data16),
+			"=S" (*APM_BIOS_codeseg_len),
+			"=D" (*APM_BIOS_dataseg_len)
+		      : "a" ((unsigned short)0x5303), "b" (0)
+		      );
+	return error;
+}
+
+/**
+ ** Video BIOS: EGA, VGA, VESA and EDID.
+ **/
+union EGA_bx_union {
+	struct {
+		enum { EGA_64K, EGA_128K, EGA_192K, EGA_256K } memory:8;
+		enum { EGA_COLOR_3Dx, EGA_MONO_3Bx } IOaddr:8;
+	} enums;
+	unsigned short IOaddr_memory;
+} __attribute__ ((packed));
+
+struct EGA_cx_str {
+	unsigned short switch1off	: 1;
+	unsigned short switch2off	: 1;
+	unsigned short switch3off	: 1;
+	unsigned short switch4off	: 1;
+	unsigned short switch_unused	: 4;
+	unsigned short FEAT1line_state2	: 1;
+	unsigned short FEAT0line_state2	: 1;
+	unsigned short FEAT1line_state1	: 1;
+	unsigned short FEAT0line_state1	: 1;
+	unsigned short FEAT_unused	: 4;
+} __attribute__ ((packed));
+
+extern inline void
+_EGA_getdisplay (union EGA_bx_union *EGA_bx, struct EGA_cx_str *EGA_cx)
+{
+	unsigned short destroyed_tseng_ET4000_V8_00;
+	asm (" int $0x10	# _EGA_getdisplay "
+	     : "=b" (*EGA_bx), "=c" (*EGA_cx),
+		"=a" (destroyed_tseng_ET4000_V8_00)
+	     : "a" ((unsigned short)0x1200),
+		"b" ((unsigned short)0xFF10)	/* %bh = 0xFF to see if supported */
+	     );
+}
+
+extern inline void
+_VGA_getcursor (unsigned char page, unsigned char *row, unsigned char *col,
+	        unsigned char *cursorstart, unsigned char *cursorstop)
+{
+	unsigned short row_col, cstart_cstop;
+	unsigned short destroyed_Phoenix_BIOS;
+
+	asm (" int $0x10 # getcursor "
+	     : "=d" (row_col), "=c" (cstart_cstop),
+		"=a" (destroyed_Phoenix_BIOS)
+	     : "a" ((unsigned short)0x0300), "b" ((unsigned short)page << 8)
+	     );
+	*col = (unsigned char)row_col;
+	*row = row_col >> 8;
+	*cursorstart = cstart_cstop >> 8;	/* bug reported with mono displays */
+	*cursorstop = (unsigned char)cstart_cstop;
+}
+
+extern inline char
+_VGA_getmode (unsigned char *nbcol, unsigned char *page)
+{
+	unsigned short nbcol_mode;
+	unsigned short tmppage;
+
+	asm (" int $0x10 # getmode "
+	     : "=b" (tmppage), "=a" (nbcol_mode)
+	     : "a" ((unsigned short)0x0F00)
+	     );
+	*nbcol = nbcol_mode >> 8;
+	*page = tmppage >> 8;
+
+	return (char)nbcol_mode;	/* bit 7 set if last setmode had it */
+}
+
+extern inline unsigned
+_VGA_get_display_combination_code (unsigned char *active_dcc,
+				   unsigned char *alternate_dcc)
+{
+	unsigned char result;
+	unsigned short alternate_active;
+
+	asm (" int $0x10 # get_display_combination_code "
+	     : "=a" (result), "=b" (alternate_active)
+	     : "a" ((unsigned short)0x1A00)
+	     );
+	*active_dcc = (unsigned char)alternate_active;
+	*alternate_dcc = alternate_active >> 8;
+
+	return (result != 0x1A);
+}
+
+typedef struct {
+	char VbeSignature[4];	/* "VESA" but NOT zero terminated. */
+	unsigned short VbeVersion;
+	farptr OemStringPtr;
+	struct vesa_capabilities_str Capabilities;
+	farptr VideoModePtr;
+	unsigned short TotalMemory;	/* in 64K blocks */
+	/* if VBE 2.0+ (else structure is 256 bytes) : */
+	unsigned short OemSoftwareRev;
+	farptr OemVendorNamePtr;
+	farptr OemProductNamePtr;
+	farptr OemProductRevPtr;
+
+	unsigned char Reserved[222];	/* ONLY VESA version 1.2- info */
+	unsigned char OemData[256];	/* will not kill VESA1.2- */
+} __attribute__ ((packed)) VESA_VbeInfoBlock;
+
+typedef struct {
+	struct vesa_mode_attribute_str ModeAttributes;
+	struct {
+		unsigned char win_exist		: 1;
+		unsigned char win_readable	: 1;
+		unsigned char win_writable	: 1;
+		unsigned char padding		: 5;
+	} __attribute__ ((packed)) WinAAttributes, WinBAttributes;
+	unsigned short WinGranularity;	/* in Kb */
+	unsigned short WinSize;	/* in Kb */
+	unsigned short WinASegment;
+	unsigned short WinBSegment;
+	farptr WinFuncPtr;
+	unsigned short BytesPerScanLine;
+	/* optional part, see "attribute.optional_info_available": */
+	unsigned short XResolution;	/* char in text modes,
+					   pixel in graphic modes */
+	unsigned short YResolution;
+	unsigned char XCharSize;
+	unsigned char YCharSize;
+	unsigned char NumberOfPlanes;
+	unsigned char BitsPerPixel;
+	unsigned char NumberOfBanks;	/* unused here : no multipaged screen */
+	enum { mem_text = 0, mem_CGA, mem_HGC, mem_EGA, mem_packedpixel,
+		mem_seq256, mem_HiColor24, mem_YUV
+	} MemoryModel : 8;
+	/* mem_seq256 = non chain 4 */
+	unsigned char BankSize;	/* in Kb, unused here */
+	unsigned char NumberOfImagePages;
+	unsigned char Reserved;
+	/* VBE 1.2+: */
+	struct vesa_color_layout_str layout;
+	struct {
+		unsigned char color_ramp_programmable	: 1;
+		unsigned char reserved_space_usable	: 1;
+	} __attribute__ ((packed)) DirectColorModeInfo;
+	/* VBE 2.0: */
+	unsigned PhysBasePtr;
+	unsigned OffScreenMemOffset;
+	unsigned short OffScreenMemSize;	/* in Kb */
+	unsigned char Reserved2[206];
+} __attribute__ ((packed)) VESA_modeinfo_t;
+
+extern inline unsigned
+_VESA_getinfo (VESA_VbeInfoBlock *VESA_info)
+{
+	unsigned short cmd_status = 0x4F00;
+
+	if (sizeof(VESA_VbeInfoBlock) != 512)
+		__ERROR();
+
+	asm (" int $0x10 # _VESA_getinfo "
+	     : "+a"(cmd_status), "=X" (*VESA_info)
+	     : "D"(VESA_info)	/* in fact %es:%di */
+	     );
+	return (cmd_status != 0x004F);
+}
+
+extern inline unsigned
+_VESA_getmodeinfo (VESA_modeinfo_t *VESA_modeinfo, unsigned short mode)
+{
+	unsigned short cmd_status = 0x4F01;
+
+	if (sizeof(VESA_modeinfo_t) != 256)
+		__ERROR();
+
+	asm (" int $0x10 # _VESA_getmodeinfo "
+	     : "+a" (cmd_status), "=X" (*VESA_modeinfo)
+	     : "c" (mode), "D" (VESA_modeinfo) /* in fact %es:%di */
+	    );
+	return (cmd_status != 0x004F);
+}
+
+extern inline unsigned _VESA_getmode (unsigned short *mode)
+{
+	unsigned short cmd_status = 0x4F03;
+
+	asm (" int $0x10 # _VESA_getmode "
+	     : "+a" (cmd_status),
+		"=b" (*mode) /* *mode contains bits 13, 14 & 15 */
+	     );
+	return (cmd_status != 0x004F);
+}
+
+extern inline unsigned _VESA_setDACwidth (unsigned char depth)
+{
+	unsigned short cmd_status = 0x4F08;
+	unsigned short result = depth << 8; /* %bl = 0 */
+
+	asm volatile (" int $0x10 # _VESA_setDACwidth "       /* VESA 1.2+ */
+	    : "+a" (cmd_status), "+b" (result)
+	    );
+	return (cmd_status != 0x004F || (result >> 8) != depth);
+}
+
+/* VESA 2.0+ */
+extern inline unsigned
+_VESA_GetPMinterface (farptr *addr, unsigned short *len)
+{
+	unsigned short cmd_status = 0x4F0A;
+
+	asm ("	pushl	%%es						\n"
+	     "	xorw	%%di,%%di					\n"
+	     "	mov	%%di,%%es					\n"
+	     "	int	$0x10		# _VESA_GetPMinterface		\n"
+	     "	pushw	%%es						\n"
+	     "	pushw	%%di						\n"
+	     "	popl	%%edi						\n"
+	     "	popl	%%es						\n"
+	     : "+a" (cmd_status), "=D" (*addr), "=c" (*len)
+	     : "b" (0), "c" ((unsigned short)0)
+	     );
+
+	return (cmd_status != 0x004F);
+}
+
+extern inline unsigned _EDID_detect (void)
+{
+	unsigned short cmd_status = 0x4F15, unknown1, unknown2;
+	/* %cx modified by NVIDIA RIVA TNT2 Model 64/Model 64 Pro */
+
+	asm (
+"	pushw	%%es			\n"
+"	movw	%%di,%%es		\n"
+"	int	$0x10 # _EDID_detect	\n"
+"	popw	%%es			\n"
+        : "+a" (cmd_status), "=b" (unknown1), "=c" (unknown2)
+        : "b" (0), "c" (0), "D" (0)
+        );
+	return (cmd_status != 0x004F);
+}
+
+extern inline unsigned _EDID_read (VBE_EDID_t *info)
+{
+	unsigned short cmd_status = 0x4F15;
+	unsigned char tmp = 1;
+	unsigned short unknown1 = 0, unknown2 = 1;
+
+	if (sizeof (VBE_EDID_t) != 0x80)
+		__ERROR();
+
+	asm (" int $0x10 # _EDID_read"
+		: "+a" (cmd_status), "=X" (*info)
+		: "b" (tmp), "D" (info), /* in fact %es:%di */
+			"c" (unknown1), "d" (unknown2)
+	);
+	/* returns 0x014F if monitor non EDID */
+	return (cmd_status != 0x004F);
+}
+
+/**
+ ** Disk BIOS:
+ **/
+extern inline unsigned
+_BIOSDISK_getparam (unsigned char disk,
+	            unsigned short *tmpcx, unsigned short *tmpdx,
+	            farptr *DBTadr, unsigned char *CmosDriveType,
+	            unsigned char *status)
+{
+	unsigned char carry;
+
+	asm ("	pushl	%%es		\n"
+	     "	xorw	%%di,%%di	\n"
+	     "	mov	%%di,%%es	\n"
+	     "	int	$0x13		# _BIOSDISK_getparam	\n"
+	     "	pushw	%%es		\n"
+	     "	pushw	%%di		\n"
+	     "	popl	%%edi		\n"
+	     "	popl	%%es		\n"
+	     "	mov	%%ah,%1		\n"
+	     "	setc	%0		\n"
+	     : "=qm" (carry), "=qm" (*status), "=c" (*tmpcx), "=d" (*tmpdx),
+			"=b" (*CmosDriveType), "=D" (*DBTadr)
+	     : "a"((unsigned short)0x0800), "d" (disk), "b" (0)
+	     );
+
+	return carry;
+}
+
+extern inline unsigned char
+_BIOSDISK_gettype (unsigned char disk, unsigned *nbsect, unsigned char *status)
+{
+	unsigned char carry;
+	unsigned dummy;
+
+	asm ("	xor	%%dh,%%dh				\n"
+	     "	xor	%%cx,%%cx				\n"
+	     "	int	$0x13		# _BIOSDISK_gettype	\n"
+	     "	shll	$16,%%ecx				\n"
+	     "	movw	%%dx,%%cx				\n"
+	     "	movb	%%ah,%1					\n"
+	     "	setc	%0					\n"
+	     : "=qm" (carry), "=qm" (*status), "=c" (*nbsect), "=d" (dummy)
+	     : "a" ((unsigned short)0x1500),
+		"d" (disk)	/* disk = 0x80..0x8F else old Compaq bug */
+	     );
+
+	return carry;
+}
+
+extern inline void
+get_drive_info (farptr indirect_ptr, union drive_info *diskinfo)
+{
+	unsigned nbbyte = sizeof(*diskinfo);
+
+	asm ("	pushl	%%esi				\n"
+	     "	popw	%%si				\n"
+	     "	popw	%%fs				\n"
+	     "	pushl	%%fs:(%%si)			\n"
+	     "	popw	%%si				\n"
+	     "	popw	%%fs				\n"
+	     "	cld					\n"
+	     "	rep movsb %%fs:(%%si),%%es:(%%di)	\n"
+	     : "+S" (indirect_ptr), "+D" (diskinfo), "+c" (nbbyte), "=X" (*diskinfo)
+	     );
+}
+
+extern inline unsigned char
+_BIOSDISK_RWsector (unsigned char drive,
+		    unsigned short cylinder, unsigned char head,
+		    unsigned char sector, unsigned char nbsector,
+		    farptr buffer, const unsigned read)
+{
+	unsigned short result, buggy_bios;
+
+	asm volatile ("	pushl	%%es				\n"
+		      "	pushl	%%ebx				\n"
+		      "	popw	%%bx				\n"
+		      "	popw	%%es				\n"
+		      "	stc		# buggy BIOSes		\n"
+		      "	int	$0x13   # _BIOSDISK_RWsector	\n"
+		      "	sti		# buggy BIOSes		\n"
+		      "	popl	%%es				\n"
+		      "	setc	%%al				\n"
+		      : "=a" (result), "=d" (buggy_bios)
+		      : "a" ((read? 0x0200 : 0x0300) | nbsector),
+			"b" (buffer),
+			"c" ((cylinder << 8) | ((cylinder >> 2) & 0xC0)
+					| (sector & 0x3F)),
+			"d" ((((unsigned short)head) << 8) | drive)
+		      );
+	if (result & 0x00FF)
+		return result >> 8;
+	return 0;
+}
+
+typedef struct {
+	unsigned short buffersize;
+	unsigned short infobit;
+	unsigned nbcylinder;
+	unsigned nbhead;
+	unsigned nbsectorpertrack;
+	unsigned long long nbtotalsector;
+	unsigned short bytepersector;
+	/* V2.0+ : */
+	farptr configptr;	/* for instance ebiosPhoenix realmode address */
+	/* V3.0+ : */
+	unsigned short signature0xBEDD;
+	unsigned char lendevicepath;	/* 0x24 for v3.0 */
+	unsigned char reserved[3];
+	unsigned char bustype[4];	/* exactly "ISA" or "PCI" */
+	unsigned char Interface[8];	/* exactly "ATA", "ATAPI",
+						 "SCSI", "USB"... */
+	union interface_path_u {
+		struct {
+			unsigned short addr;
+			unsigned char pad[6];
+		} __attribute__ ((packed)) isa;
+		struct {
+			unsigned char busnr;
+			unsigned char devicenr;
+			unsigned char functionnr;
+			unsigned char pad[5];
+		} __attribute__ ((packed)) pci;
+	} bus;
+	union device_path_u {
+		struct {
+			unsigned char slave;	/* 0 if master, 1 if slave */
+			unsigned char pad[7];
+			unsigned long long reserved;	/* Not present in some docs... */
+		} __attribute__ ((packed)) ata;
+		struct {
+			unsigned char slave;	/* 0 if master, 1 if slave */
+			unsigned char logical_unit_nr;
+			unsigned char pad[6];
+		} __attribute__ ((packed)) atapi;
+		struct {
+			unsigned char logical_unit_nr;
+			unsigned char pad[7];
+		} __attribute__ ((packed)) scsi;
+		struct {
+			unsigned char tobedefined;
+			unsigned char pad[7];
+		} __attribute__ ((packed)) usb;
+		struct {
+			unsigned long long FireWireGeneralUniqueID;
+		} __attribute__ ((packed)) ieee1394;
+		struct {
+			unsigned long long WorldWideNumber;
+		} __attribute__ ((packed)) FibreChannel;
+	} device;
+	unsigned char zero;
+	unsigned char bytechecksum;	/* byte sum [0x1E..0x49] = 0 */
+} __attribute__ ((packed)) ebiosinfo_t;
+
+typedef struct {
+	unsigned short extended_fct	: 1;
+	unsigned short removable	: 1;
+	unsigned short enhanced		: 1;
+	unsigned short reserved		: 13;
+} __attribute__ ((packed)) ebios_bitmap_t;
+
+extern inline unsigned char
+_EBIOSDISK_probe (unsigned char disk, unsigned char *version,
+		  unsigned char *extension, ebios_bitmap_t *bitmap)
+{
+	unsigned char carry;
+	unsigned short signat0xAA55;
+
+	asm ("       int     $0x13           # _EBIOSDISK_probe      \n"
+	     "       mov     %%ah,%1                                 \n"
+	     "       mov     %%dh,%2                                 \n"
+	     "       setc    %0                                      \n"
+	     : "=qm" (carry), "=qm" (*version), "=qm" (*extension),
+		"=b" (signat0xAA55), "=c" (*bitmap)
+	     : "a" ((unsigned short)0x4100), "b" ((unsigned short)0x55AA),
+		"d"(disk)
+	     );
+
+	return carry || (signat0xAA55 != 0xAA55);
+}
+
+extern inline unsigned char
+_EBIOSDISK_getparam (unsigned char disk, ebiosinfo_t *ebiosinfo,
+		     unsigned char *status)
+{
+	unsigned char carry;
+
+	asm ("       int     $0x13           # _EBIOSDISK_getparam   \n"
+	     "       mov     %%ah,%1                                 \n"
+	     "       setc    %0                                      \n"
+	     : "=qm" (carry), "=qm" (*status)
+	     : "a" ((unsigned short)0x4800), "d" (disk), "S" (ebiosinfo)
+	    );
+
+	return carry;
+}
+
+/*
+ * Well, I do not know what that does, but because it is included in Linux
+ * kernel it has to be GPL - source code given in its most readable form...
+ */
+extern inline void
+_X86SpeedStepSmi (struct X86SpeedStepSmi_s *data)
+{
+	asm(" int  $0x15	# _X86SpeedStepSmi "
+	    : "=a" (data->data1), "=b" (data->data2),
+		"=c" (data->data3), "=d" (data->data4)
+	    : "a" (0x0000E980), "d" (0x47534943) );
+}
+
+/**
+ ** Fill in each of the sub-structures:
+ **/
+CODE static inline void
+vmlinuz_EGA (struct screen_info *screen_info)
+{
+	union EGA_bx_union EGA_bx;
+	struct EGA_cx_str EGA_cx;
+
+	_EGA_getdisplay(&EGA_bx, &EGA_cx);
+	screen_info->orig_video_ega_bx = EGA_bx.IOaddr_memory;
+	screen_info->orig_video_isVGA = 0;
+	if (EGA_bx.enums.IOaddr == EGA_COLOR_3Dx
+	    || EGA_bx.enums.IOaddr == EGA_MONO_3Bx) {
+		unsigned char active_dcc, alternate_dcc;
+
+		if (_VGA_get_display_combination_code(&active_dcc,
+						      &alternate_dcc) == 0)
+			screen_info->orig_video_isVGA = 1;
+
+		screen_info->orig_video_lines = peekb((farptr)0x00400084) + 1;
+		screen_info->orig_font_height = peekw((farptr)0x00400085);
+	} else {	/* EGA_bx.enums.IOaddr unchanged => CGA/MDA/HGA */
+		screen_info->orig_video_lines = 25;
+		screen_info->orig_font_height = 0;	/* i.e. invalid */
+	}
+}
+
+CODE static inline void
+vmlinuz_getcursor (struct screen_info *screen_info)
+{
+#if 1		/* what is the best ? IHMO using the BIOS functions */
+	unsigned char row, col;
+	unsigned char cursorstart, cursorstop;
+
+	_VGA_getcursor(screen_info->orig_video_page,
+		       &row, &col, &cursorstart, &cursorstop);
+	screen_info->orig_x = col;
+	screen_info->orig_y = row;
+#else
+	farptr ptr = 0x00400050 + 2 * screen_info->orig_video_page;
+
+	screen_info->orig_x = peekb(ptr);
+	screen_info->orig_y = peekb(ptr + 1);
+#endif
+}
+
+CODE static inline void
+vmlinuz_VGA (struct screen_info *screen_info, int proposed_line)
+{
+	unsigned char mode, nbcol, page;
+
+	mode = _VGA_getmode(&nbcol, &page);
+	screen_info->orig_video_mode = mode & 0x7F;
+	screen_info->orig_video_cols = nbcol;
+	screen_info->orig_video_page = page;	/* not tested if != 0 */
+	if (proposed_line >= 0) {
+		screen_info->orig_y = proposed_line;
+		screen_info->orig_x = 0;
+	} else {
+		vmlinuz_getcursor(screen_info);
+		/* We try not to erase the text written later by Gujin: */
+		screen_info->orig_x = 0;
+		if (screen_info->orig_y + 4 < screen_info->orig_video_lines)
+			screen_info->orig_y += 4;
+		else
+			screen_info->orig_y = screen_info->orig_video_lines - 1;
+	}
+}
+
+CODE static inline void
+vmlinuz_VESA (struct screen_info *screen_info, unsigned mode)
+{
+	VESA_modeinfo_t modeinfo;
+
+	if (_VESA_getmodeinfo(&modeinfo, mode & 0x01FF) == 0) {
+		if (modeinfo.MemoryModel == mem_text
+			&& modeinfo.NumberOfPlanes == 4) {
+			/* correct some buggy video BIOS: */
+			modeinfo.BytesPerScanLine = 2 * modeinfo.XResolution;
+			modeinfo.BitsPerPixel = 4;
+		}
+		if (modeinfo.MemoryModel == mem_text)
+			screen_info->lfb_base = 0xB8000;
+		else if (modeinfo.ModeAttributes.linear_framebuffer_supported) {
+			/* no text modes with linear framebuffer */
+			screen_info->orig_video_isVGA = 0x23;
+			screen_info->lfb_base = modeinfo.PhysBasePtr;
+		} else
+			screen_info->lfb_base = 0xA0000;
+		screen_info->lfb_linelength = modeinfo.BytesPerScanLine;
+		screen_info->lfb_width = modeinfo.XResolution;
+		screen_info->lfb_height = modeinfo.YResolution;
+		screen_info->lfb_depth = modeinfo.BitsPerPixel;
+		screen_info->lfb_pages = modeinfo.NumberOfImagePages;
+		screen_info->vesa_attrib = modeinfo.ModeAttributes;
+		screen_info->layout = modeinfo.layout;
+	} else
+		screen_info->lfb_base = 0;
+}
+
+CODE static void
+vmlinuz_VIDEO (struct screen_info *screen_info, unsigned short *acpi_vidmode,
+	       int proposed_line)
+{
+	VESA_VbeInfoBlock infoblock;
+
+	vmlinuz_EGA(screen_info);
+	vmlinuz_VGA(screen_info, proposed_line);
+	*acpi_vidmode = screen_info->orig_video_mode;
+
+	/* normaly only for graphic modes: */
+	if (_VESA_getinfo(&infoblock) == 0) {
+		unsigned short mode, len;
+		farptr addr;
+
+		screen_info->lfb_size = infoblock.TotalMemory;
+		screen_info->capabilities = infoblock.Capabilities;
+		if (_VESA_getmode(&mode) == 0) {
+			vmlinuz_VESA(screen_info, mode);
+			*acpi_vidmode = mode;
+#if 0	/* After doing that, we should program again the DAC with the right values... */
+			/* Linux do not manage text modes and DAC 8 bits: */
+			if (screen_info->lfb_base != 0xB8000
+				 && screen_info->lfb_depth <= 8
+				 && infoblock.Capabilities.DAC8bit_present) {
+				if (_VESA_setDACwidth (8) == 0) {
+					screen_info->layout = (const struct vesa_color_layout_str){
+						{8, 0}, {8, 0}, {8, 0}, {8, 0}};
+				}
+				else {
+					screen_info->layout = (const struct vesa_color_layout_str){
+						{6, 0}, {6, 0}, {6, 0}, {6, 0}};
+				}
+			}
+#endif
+		}
+
+		/* Note: We can have a PM interface even if getmodeinfo
+		   failed, for instance if we are in text mode 3 */
+		if (_VESA_GetPMinterface(&addr, &len) == 0) {
+			screen_info->vesapm_seg = addr >> 16;
+			screen_info->vesapm_off = addr & 0xFFFF;
+		}
+	}
+}
+
+CODE static inline unsigned short vmlinuz_EXT_MEM_K (void)
+{
+	unsigned short EXT_MEM_K;
+
+	if (_BIOS_getExtendedMemory(&EXT_MEM_K) != 0 || EXT_MEM_K == 0)
+		EXT_MEM_K = (((unsigned short)getnvram(0x18)) << 8)
+				+ getnvram(0x17);
+	return EXT_MEM_K;
+}
+
+CODE static inline void
+vmlinuz_APM (struct apm_bios_info *apm_bios_info)
+{
+	if (_APM_installation_check(&apm_bios_info->version,
+				   &apm_bios_info->flags) == 0) {
+		_APM_disconnect();	/* ignore possible error */
+		if ((apm_bios_info->flags & 2) == 0) {
+			/* no 32 bits support, ignore APM */
+		} else if (_APM_connect_32bit(&apm_bios_info->cseg,
+					     &apm_bios_info->offset,
+					     &apm_bios_info->cseg_16,
+					     &apm_bios_info->dseg,
+					     &apm_bios_info->cseg_len,
+					     &apm_bios_info->dseg_len) != 0) {
+			apm_bios_info->flags &= ~2; /* remove 32bits support */
+		} else {
+			/* Redo the installation check as the 32 bit connect
+				modifies the flags returned on some BIOSs : */
+			if (_APM_installation_check(&apm_bios_info->version,
+						&apm_bios_info->flags) != 0) {
+				apm_bios_info->flags &= ~2;
+				_APM_disconnect();
+			}
+		}
+	}
+}
+
+CODE static inline void
+vmlinuz_CONFIG (struct sys_desc_table_info *sys_desc_table)
+{
+	farptr adr = _BIOS_getConfiguration();
+
+	if (adr != 0)
+		get_bios_conf(adr, sys_desc_table);
+}
+
+CODE static inline void
+vmlinuz_EDID (VBE_EDID_t *edid_data)
+{
+	if (_EDID_detect() != 0 || _EDID_read(edid_data) != 0) {
+		unsigned char *ptr = (unsigned char *)edid_data;
+		unsigned cpt = sizeof(VBE_EDID_t);
+		/* failed, reset complete area: */
+		while (--cpt)
+			*ptr++ = 0x13;
+	}
+}
+
+CODE static inline unsigned
+vmlinuz_E820 (struct e820map_info *e820map, unsigned e820map_bufsize)
+{
+	unsigned bufsize = e820map_bufsize, cont_val = 0, actual_len;
+	/* Use that to avoid data in .rodata with GCC-2.95.3: */
+	unsigned element_size = sizeof(struct e820map_info);
+
+	while (   bufsize >= element_size
+	       && (actual_len = _BIOS_QueryMemoryMap(&cont_val,
+					bufsize, e820map)) != 0
+	       && cont_val != 0) {
+		bufsize -= actual_len;
+		e820map = (void *)e820map + actual_len;
+	}
+	return (e820map_bufsize - bufsize) / element_size;
+}
+
+CODE static inline unsigned
+vmlinuz_MBRSIG (unsigned *MBRSIG, unsigned total_MBRSIG_entries)
+{
+	unsigned buffer[512 / sizeof(unsigned)], cpt;
+#define EDD_MBR_SIG_OFFSET 0x1B8  /* offset of signature in the MBR */
+
+	for (cpt = 0; cpt < total_MBRSIG_entries; cpt++) {
+		if (_BIOSDISK_RWsector(0x80 + cpt, 0, 0, 1, 1,
+					 stack_farptr(buffer), 1) != 0)
+			return cpt;
+		*MBRSIG++ = buffer[EDD_MBR_SIG_OFFSET / sizeof(unsigned)];
+	}
+	return cpt;
+}
+
+CODE static inline unsigned
+vmlinuz_EDD (struct edd_info *edd, unsigned total_EDD_entries)
+{
+	unsigned cpt, eddcpt;
+
+	for (cpt = eddcpt = 0; cpt < 16 && eddcpt < total_EDD_entries; cpt++) {
+		unsigned char extension, status;
+		unsigned short tmpcx, tmpdx;
+		farptr DBTadr;
+		unsigned char CmosDriveType, stat;
+		struct edd_info *eddptr = &edd[eddcpt];
+
+		if (_EBIOSDISK_probe(0x80 + cpt, &eddptr->version, &extension,
+			     (ebios_bitmap_t *) &eddptr->interface_support))
+			continue;
+		eddptr->device = 0x80 + cpt;
+		eddptr->params.length = sizeof(eddptr->params);
+		eddptr->params.info_flags = 0;	/* buggy BIOS ? */
+		/* Don't check for fail return, it doesn't matter: */
+		_EBIOSDISK_getparam(0x80 + cpt,
+				(ebiosinfo_t *) &eddptr->params, &status);
+		if (_BIOSDISK_getparam(0x80 + cpt, &tmpcx, &tmpdx,
+				&DBTadr, &CmosDriveType, &stat) != 0) {
+			eddptr->max_cyl = 0;
+			eddptr->max_sect = eddptr->max_head = 0;
+		} else {
+			eddptr->max_head = tmpdx >> 8;
+			eddptr->max_sect = tmpcx & 0x3F;
+			eddptr->max_cyl = ((tmpcx & 0xC0) << 2) | (tmpcx >> 8);
+		}
+		eddcpt++;
+	}
+	return eddcpt;
+}
+
+
+/**
+ ** Command line stuff:
+ **/
+CODE static inline void
+vmlinuz_CMDLINE (char *command_line, const unsigned char *proposed_cmdline,
+		 farptr extra_cmdline_farptr,
+		 const char *cmdline_name, const char *cmdline_extraparam)
+{
+	char *cmdptr = command_line;
+
+	/* insert at beginning the name of the uncompressed GZIP file: */
+	if (cmdline_name && *cmdline_name) {
+		do
+			*cmdptr++ = *cmdline_name++;
+		while (*cmdline_name);
+		*cmdptr++ = ' ';
+	}
+
+	/* insert then: console=ttyS?,9600,n,7 or video=vesa,
+		keyboard=??, NumLock=on/off, mouse=/dev/psaux,
+		COLS=, LINES= proposed by Gujin */
+	if (proposed_cmdline && *proposed_cmdline) {
+		do
+			*cmdptr++ = *proposed_cmdline++;
+		while (*proposed_cmdline);
+		*cmdptr++ = ' ';
+	}
+
+	/* Add nearby end the Gujin gujin_param.extra_cmdline field: */
+	/* We assume there gujin_param.extra_cmdline is correctly zero terminated */
+	/* Note: we will have "root=" parameter from Gujin setup screen first,
+	   so that if the one in the GZIP comment if erroneous, we can just
+	   overwrite it with the Gujin setup (TOCHECK: when two "root=" are
+	   given on the command line, only the first one is taken) */
+	if (extra_cmdline_farptr != 0 && peekb(extra_cmdline_farptr) != 0) {
+		*cmdptr++ = ' '; /* two spaces as separator */
+		for (;;) {
+			*cmdptr = peekb(extra_cmdline_farptr++);
+			if (*cmdptr < ' ') { /* stop at \0, \n, \r or \t */
+				*cmdptr = '\0';
+				break;
+			}
+			cmdptr++;
+		}
+	}
+
+	/* add at end the params in the comment part of the GZIP file: */
+	/* This may or may not stop at the first newline */
+	if (cmdline_extraparam && *cmdline_extraparam) {
+		*cmdptr++ = ' ';
+		do
+			*cmdptr++ = *cmdline_extraparam++;
+		while (*cmdline_extraparam != 0 && *cmdline_extraparam != '\n');
+	}
+	*cmdptr = '\0';
+}
+
+/**
+ ** OPTIONAL: If we want to use the data structures of Gujin to try to
+ ** find and match the root filesystem of the kernel loaded (that part
+ ** can be completely disabled):
+ **/
+#ifdef ROOT_EXTENSIVE_SEARCH
+
+struct desc_str {
+	unsigned inode;
+	unsigned filesize;
+	unsigned char disk;
+	unsigned char partition;	/* 0xFF for MBR */
+	unsigned char name_offset;	/* to after the pattern */
+	enum curdir_e { inRoot = 0, inSlashBoot, inSlashImage } curdir  : 3;
+	enum boottype_e { is_MBR, is_PBR, is_kernel_with_header,
+		is_kernel_without_header, is_initrd,
+		is_bdi_file, is_el_torito, is_initramfs } boottype : 3;
+	unsigned char unused     : 2;
+#define NAME_LENGTH	52
+	char filename[NAME_LENGTH];
+} __attribute__ ((packed));
+
+struct gpl_compliant_str {
+	unsigned signature;
+	unsigned version;
+	unsigned feature;
+	unsigned size;
+	struct setjmp_buf {
+		unsigned esi, edi, ebp, ebx;
+		unsigned short gs, fs, es, ds;
+		unsigned short flags, ip, cs, sp, ss;
+	} __attribute__ ((packed)) jmpbuf;
+	/* unsigned short padding */
+	unsigned filename_array, gdt, regs, fourKbuffer;
+	unsigned LOADER, STATE, UI, MOUSE, DI, UTIL, BOOTWAY;
+};
+
+typedef struct {
+	unsigned char  header_id_0x01;
+	enum { platform_80x86 = 0, platform_PowerPC = 1,
+		platform_Mac = 2 } platform_id : 8;
+	unsigned short reserved;
+	unsigned char  manufacturer[0x1B - 0x04 +1];
+	unsigned short checksum;
+	unsigned char  signature1_0x55;
+	unsigned char  signature2_0xAA;
+} __attribute__ ((packed)) ISO9660_Validation_entry;
+
+typedef struct {
+	unsigned char  boot_indicator; /* 0x88: bootable, 0x00: non bootable */
+	enum { boot_media_noemul = 0, boot_media_120 = 1, boot_media_144 = 2,
+		boot_media_288 = 3, boot_media_hd = 4 } boot_media_type : 8;
+	unsigned short load_segment; /* 0x7c0 if null */
+	unsigned char  system_type;
+	unsigned char  unused;
+	unsigned short sector_count;
+	unsigned       sector_lba;
+	unsigned char  reserved[0x1F - 0x0C +1];
+} __attribute__ ((packed)) ISO9660_Default_entry;
+
+struct diskparam_str {
+	enum {	bios_chs, ebios_lba,
+		hardide_chs, hardide_lba, hardide_lba48, hardide_atapi,
+		dos_part
+	} access : 8;
+	unsigned char	disknb;	/* BIOS number or DOS letter
+				   or 0=master, non zero=slave */
+	unsigned char	biostype;	/* 1:floppy w/o change detect,
+						 2: with, 3: HD */
+	unsigned char	drivetype;	/* 1: 360K, 2: 1.2M, 3: 720K,
+					 4: 1.44M, 6: 2.88M, 0x10: ATAPI */
+	unsigned char	diskname[32];
+
+	struct ide_attribute_str {
+		unsigned smart			: 1;
+		unsigned host_protected_area	: 1;
+		unsigned security		: 1;
+		unsigned lba48			: 1;
+		unsigned removable		: 1;
+		unsigned SAORAB			: 1;
+		unsigned config_overlay		: 1;
+		unsigned reserved		: 25;
+	} ide_attribute;
+	struct error_log_str {
+		unsigned read_media			: 1;
+		unsigned write_media			: 1;
+		unsigned access_over_disk_tryed		: 1;
+		unsigned access_over_partition_tryed	: 1;
+		unsigned no_ebios_fct			: 1;
+		unsigned ebios_size_zero		: 1;
+		unsigned chs_bios_part_mismatch		: 1;
+		unsigned chs_ajusted_bootsect		: 1;
+		unsigned diskheader_ignored		: 1;
+		unsigned disk_locked			: 1;
+		unsigned disk_was_pw_locked		: 1;
+		unsigned SMART_disabled			: 1;
+		unsigned SMART_failure			: 1;
+		unsigned analyse_partition_failed	: 1;
+		unsigned NB_PARTITION_exceded		: 1;
+		unsigned partition_overlap		: 1;
+		unsigned partition_over_limit		: 1;
+		unsigned beer_checksum_error		: 1;
+		unsigned beer_in_extended_partition	: 1;
+		unsigned reserved			: 13;
+	} error_log;
+	unsigned short	bytepersector;
+	unsigned short	nbhead;		  /* DOS: MediaDescriptorByte */
+	unsigned	nbcylinder;       /* DOS: ClustersOnDisk */
+	unsigned	BEER_size;
+	unsigned long long	BEER_sector;
+	unsigned long long	BEER_HostProtectedArea_start;
+	unsigned long long	BEER_ReservedAreaBootCodeAddress;
+	unsigned long long	BEER_disksize;
+	  signed long long	fulldisk_offset; /* Nb sectors before MBR */
+	unsigned long long	fulldisk_size;	 /* only if MBR is offseted */
+	unsigned long long	nbtotalsector;
+	unsigned long long	config_max_lba;
+	unsigned short	nbsectorpertrack; /* DOS: SectorPerCluster */
+
+	unsigned short	infobit;	/* Int13/48 extensions */
+	unsigned char	ebios_version;	/* if present, used if access = ebios */
+	unsigned char	ebios_extension;
+	ebios_bitmap_t	ebios_bitmap;
+	unsigned short	reserved3;	/* ebios_bitmap is 16 bits */
+
+	unsigned char  ebios_bustype[4];	/* exactly "ISA" or "PCI" */
+	unsigned char  ebios_Interface[8];	/* exactly "ATA", "ATAPI",
+							"SCSI", "USB"...*/
+	union interface_path_u	ebios_bus;
+	union device_path_u	ebios_device;
+
+	unsigned short	reserved4;
+
+	unsigned short	ide_master_password_revision; /* if command_supported1.security */
+	unsigned short	ideIOadr;	/* if known, else 0 */
+	unsigned short	ideIOctrladr;	/* if known, else 0 */
+	unsigned char	lba_slave_mask;	/* see Phenix Bios (head | mask) */
+	unsigned char	irq;		/* if known, else 0 */
+	unsigned char	multiplemode;	/* int 0x13/0x21,0x22,0x24 or hardide,
+						set but not used. */
+	unsigned char	BEER_device_index;
+	struct config_multiword_dma_s {
+		unsigned short	mode0    : 1;
+		unsigned short	mode1    : 1; /* and below */
+		unsigned short	mode2    : 1; /* and below */
+		unsigned short	reserved : 13;
+	} __attribute__ ((packed)) initial_multiDMA, maximum_multiDMA;
+	struct config_ultra_dma_s {
+		unsigned short	mode0    : 1;
+		unsigned short	mode1    : 1; /* and below */
+		unsigned short	mode2    : 1; /* and below */
+		unsigned short	mode3    : 1; /* and below */
+		unsigned short	mode4    : 1; /* and below */
+		unsigned short	mode5    : 1; /* and below */
+		unsigned short	reserved : 10;
+	} __attribute__ ((packed)) initial_ultraDMA, maximum_ultraDMA;
+	struct config_feature_s {
+		unsigned short	smart_feature	: 1;
+		unsigned short	smart_selftest	: 1;
+		unsigned short	smart_errorlog	: 1;
+		unsigned short	security	: 1;
+		unsigned short	standby_powerup	: 1;
+		unsigned short	RW_DMA_queued	: 1;
+		unsigned short	acoustic	: 1;
+		unsigned short	host_prot_area	: 1;
+		unsigned short	lba48		: 1;
+		unsigned short	reserved	: 7;
+	} __attribute__ ((packed)) initial_feature, maximum_feature;
+	unsigned	CalibrationIdeloop; /* nanoseconds (10^-9) per loop */
+
+	/* Following three only for C/H/S partition, from standard BIOS: */
+	unsigned short	bios_nbcylinder;	/* max 1024 */
+	unsigned char	bios_nbhead;		/* max 256 */
+	unsigned char	bios_nbsectorpertrack;	/* max 63 */
+
+	unsigned char	bootable;	/* nonzero: bootable,
+				 > 1 when special bootsector recognised */
+	unsigned char	OSdisknumber;	/* as written in the boot block */
+
+	unsigned short	nbpartition;
+	unsigned short	nbOSnumber;
+	unsigned short	reserved5;
+	/* Following value is current extended primary partition,
+	   if there is more than one extended primary partition. */
+	unsigned		first_ext_partition_start; /* NOT A LONG LONG */
+	struct partition_str {
+		unsigned long long	start, length;
+		/* OSnumber should be equal to the # in /dev/hda#: */
+		unsigned char	type, OSnumber;
+		struct partition_misc_str {
+			/* order as found on disk: */
+			unsigned char order		: 6;
+			unsigned char fsanalyse_toobig	: 1;
+			unsigned char fsanalyse_error	: 1;
+			unsigned char maybe_root	: 1;
+			unsigned char fat_bootable	: 1;
+			unsigned char beer_partition	: 1;
+			unsigned char swap_partition	: 1;
+			unsigned char reserved		: 2;
+			enum part_state {
+				part_invalid = 0, part_active,
+				part_inactive, part_extended
+			} active		: 2;
+		} __attribute__ ((packed)) misc;
+#define MAX_DISKNAMESIZE	(64 - 20 - 4) /* bigger than "floppy" */
+		unsigned char	name[MAX_DISKNAMESIZE];
+		union {
+			ISO9660_Validation_entry *validation; /* first one only */
+			ISO9660_Default_entry *catalog; /* array index >= 1 */
+		} ElTorito;
+	} __attribute__ ((packed)) *partition;
+
+	unsigned	nbfreelist;
+	struct freelist_str {
+		unsigned long long start, length;
+	} *freelist;
+	char set_max_password[32];
+	} *param;
+
+struct disk_interface_str {
+	unsigned	nbdisk;
+	unsigned char	max_disk, max_partition, max_freelist, max_IDE_found;
+	unsigned short	sizeof_diskparam_str, sizeof_partition_str;
+	unsigned short	sizeof_freelist_str, sizeof_IDE_found_str;
+	unsigned char	nb_bios_fd, nb_bios_hd, cannot_reset_floppy,
+			nb_bios_blacklist;
+	unsigned char	bios_blacklist[4];
+	unsigned	reserved1[2];
+	unsigned char	(*readsector) (struct diskparam_str *dp, int partition,
+				unsigned long long lba, unsigned number,
+				farptr buffer);
+	unsigned char	(*writesector) (struct diskparam_str *dp, int partition,
+				unsigned long long lba, unsigned number,
+				farptr buffer);
+	int		(*ideSecurity) (struct diskparam_str *, char *,
+					 unsigned);
+	unsigned long long last_lba_read_or_write;
+	struct diskparam_str *param;
+	unsigned	nb_IDE_found;
+	struct IDE_found_str {
+		unsigned short	ideIOadr;
+		unsigned short	ideIOctrladr;
+		unsigned char	irq;
+		unsigned char	bios_order;
+		unsigned short	reserved;
+	} *IDE_found;
+};
+
+CODE static inline int
+add_hexletter (unsigned short *val, unsigned char hexletter)
+{
+	if (hexletter >= '0' && hexletter <= '9')
+		*val = (*val << 4) + hexletter - '0';
+	else if (hexletter >= 'a' && hexletter <= 'f')
+		*val = (*val << 4) + hexletter - 'a' + 10;
+	else if (hexletter >= 'A' && hexletter <= 'F')
+		*val = (*val << 4) + hexletter - 'A' + 10;
+	else
+		return 1;
+	return 0;
+}
+
+/* If the "ide[0-9]=" are already given on the command line, that may
+   indicate the user wants a special order - and we probe that order
+   to guess the root partition: */
+CODE static inline void
+init_IDE_found_from_cmdline (struct IDE_found_str *IDE_found,
+		const unsigned nb_IDE_found, const char *cmdptr)
+{
+	while (*cmdptr) {
+		if (cmdptr[0] == 'i' && cmdptr[1] == 'd' && cmdptr[2] == 'e'
+			&& cmdptr[3] >= '0' && cmdptr[3] <= '9'
+			&& cmdptr[4] == '='
+			&& cmdptr[5] == '0' && cmdptr[6] == 'x') {
+			unsigned short IOaddr = 0, IOctrladr = 0;
+			unsigned short index = cmdptr[3] - '0';
+			unsigned char irq = 0;
+
+			cmdptr += 7;
+			while (add_hexletter (&IOaddr, *cmdptr) == 0)
+				cmdptr++;
+			/* Why did you read up to here? Don't you trust me? */
+			if (cmdptr[0] == ',' && cmdptr[1] == '0'
+					     && cmdptr[2] == 'x') {
+				cmdptr += 3;
+				while (add_hexletter (&IOctrladr, *cmdptr) == 0)
+					cmdptr++;
+				if (*cmdptr == ',') {
+					cmdptr++;
+					while (*cmdptr >= '0' && *cmdptr <= '9')
+						irq = (irq * 10) + *cmdptr++ - '0';
+				}
+			}
+
+			/* first unknown char shall be spacing or end of string */
+			if (   (*cmdptr == ' ' || *cmdptr == '\0')
+			    && index < nb_IDE_found)
+				IDE_found[index] = (struct IDE_found_str) {
+					.ideIOadr	= IOaddr,
+					.ideIOctrladr	= IOctrladr,
+					.irq		= irq,
+					.bios_order	= 0xFF,
+					.reserved	= 0
+					};
+		}
+		else
+			cmdptr++;
+	}
+}
+
+/* If no "ide[0-9]=" given, we use the BIOS order found by Gujin;
+  if Gujin knows more IDEs (just one ide added like: ide2=0x...
+  but not ide0= and ide1=) add the obvious missing ones,
+  without erasing nor offseting the user given information: */
+CODE static inline void
+init_IDE_found_from_DI (struct IDE_found_str *IDE_found,
+		const unsigned nb_IDE_found,
+		const struct disk_interface_str *DI)
+{
+	unsigned cpt;
+
+	for (cpt = 0; cpt < DI->nb_IDE_found; cpt++) {
+		unsigned i, j;
+		for (i = 0; i < nb_IDE_found; i++)
+			if (IDE_found[i].ideIOadr == DI->IDE_found[cpt].ideIOadr)
+				break;
+		if (i < nb_IDE_found)
+			continue; /* already given */
+		for (j = 0; j < nb_IDE_found; j++)
+			if (IDE_found[j].ideIOadr == 0)
+				break; /* first unused */
+		if (j < nb_IDE_found)
+			IDE_found[j] = DI->IDE_found[cpt];
+	}
+}
+
+CODE static inline void
+finalise_cmdline (struct IDE_found_str *IDE_found, unsigned nb_IDE_found,
+		  char *command_line)
+{
+	static CONST char itoa_array[] = "0123456789abcdef";
+	unsigned cpt;
+	char *cmdptr = command_line;
+
+	while (*cmdptr != '\0')
+		cmdptr++;
+	for (cpt = 0; cpt < nb_IDE_found; cpt++) {
+		unsigned short val;
+		if (   IDE_found[cpt].ideIOadr == 0
+		    || IDE_found[cpt].bios_order == 0xFF)
+			continue;
+		if (cmdptr - command_line > 1024)
+			break;
+		*cmdptr++ = ' ';
+		*cmdptr++ = 'i'; *cmdptr++ = 'd'; *cmdptr++ = 'e';
+		*cmdptr++ = '0' + cpt;
+		*cmdptr++ = '='; *cmdptr++ = '0'; *cmdptr++ = 'x';
+		val = IDE_found[cpt].ideIOadr;
+		if (val & 0xF000)
+			*cmdptr++ = itoa_array[val >> 12];
+		*cmdptr++ = itoa_array[(val >> 8) & 0x0F];
+		*cmdptr++ = itoa_array[(val >> 4) & 0x0F];
+		*cmdptr++ = itoa_array[(val >> 0) & 0x0F];
+		val = IDE_found[cpt].ideIOctrladr;
+		if (val) {
+			*cmdptr++ = ',';
+			*cmdptr++ = '0';
+			*cmdptr++ = 'x';
+			if (val & 0xF000)
+				*cmdptr++ = itoa_array[val >> 12];
+			*cmdptr++ = itoa_array[(val >> 8) & 0x0F];
+			*cmdptr++ = itoa_array[(val >> 4) & 0x0F];
+			*cmdptr++ = itoa_array[(val >> 0) & 0x0F];
+			val = IDE_found[cpt].irq; /* < 100 */
+			if (val) {
+				*cmdptr++ = ',';
+				*cmdptr++ = itoa_array[val / 10];
+				*cmdptr++ = itoa_array[val % 10];
+			}
+		}
+		*cmdptr = '\0';
+	}
+}
+
+/* root= parameter not present, set it depending on system_desc->disk,
+   system_desc->partition and the number of slash in the kernel name as
+   found in the GZIP name field.
+   Note that we assume that IF the kernel file loaded was in the top
+   directory AND the partition size is too small, it is a "/boot"
+   partition and the real root is the NEXT partition of type 0x83 if it exists.
+   Gujin prefers a lot having only one root partition containning everything
+   including "/boot", but try to stay compatible. */
+CODE static inline void
+add_root_parameter (const struct desc_str *system_desc, char *cmdptr,
+			const struct IDE_found_str IDE_found[10],
+			const unsigned nb_IDE_found,
+			const struct disk_interface_str *DI,
+			const unsigned nb_slash_in_kernelname)
+ {
+	const struct diskparam_str *const dp = &DI->param[system_desc->disk];
+	const unsigned min_part_size = 640 * 1024 * 1024 / dp->bytepersector;
+	unsigned OSnumber = dp->partition[system_desc->partition].OSnumber;
+	static CONST char root_pattern[] = " root=/dev/";
+
+	if (   system_desc->curdir == inRoot
+	    && nb_slash_in_kernelname != 1 /* not really created in root dir */
+	    && dp->partition[system_desc->partition].length < min_part_size) {
+		/* find the next bigger 0x83 partition on same disk: */
+		unsigned partition;
+		for (partition = system_desc->partition;
+		    partition < dp->nbpartition;
+		    partition++)
+			if (   dp->partition[partition].length > min_part_size
+			    && dp->partition[partition].type == 0x83) {
+				OSnumber = dp->partition[partition].OSnumber;
+				break;
+			}
+	}
+
+	if (dp->ideIOadr != 0) {
+		/* seriously looks like an IDE disk, isn't it? */
+		unsigned cptide;
+		for (cptide = 0; cptide < nb_IDE_found; cptide++)
+			if (dp->ideIOadr == IDE_found[cptide].ideIOadr)
+				break;
+		if (cptide < nb_IDE_found) {
+			const char *ptr = root_pattern;
+			while (*ptr)
+				*cmdptr++ = *ptr++;
+			*cmdptr++ = 'h';
+			*cmdptr++ = 'd';
+			*cmdptr++ = 'a' + 2 * cptide + !!(dp->lba_slave_mask & 0x10);
+			*cmdptr++ = '0' + OSnumber;
+			*cmdptr = '\0';
+		}
+	} else {
+		/* count number of [E]BIOS hard disks and compare to the
+		number of IDE hard disk to know if there are SCSI disks: */
+		unsigned cpt_bios_disk = 0, cpt_ide_disk = 0, cptdisk;
+		unsigned char maybe_scsi = 0;
+		const char *ptr = root_pattern;
+
+		for (cptdisk = 0; cptdisk < DI->nbdisk; cptdisk++) {
+			if (  DI->param[cptdisk].access == bios_chs
+			   || DI->param[cptdisk].access == ebios_lba) {
+				if (DI->param[cptdisk].disknb >= 0x80) {
+					cpt_bios_disk++;
+					if (DI->param[cptdisk].ideIOadr == 0)
+						maybe_scsi = 1;
+				} /* else floppy disk */
+			}
+			else if (DI->param[cptdisk].access == hardide_chs
+			    || DI->param[cptdisk].access == hardide_lba
+			    || DI->param[cptdisk].access == hardide_lba48)
+				cpt_ide_disk++; /* not CDROM, not empty IDE */
+		}
+		while (*ptr)
+			*cmdptr++ = *ptr++;
+		/* If we have the same amount or less BIOS disks than IDE
+		disks, we assume we have a normal (or a very old w/o EBIOS) PC
+		without SCSI or USB drives, then assume BIOS mapping like
+		IDE mapping: 0x80 master on IDE0; else we assume all SCSI
+		drives are after the BIOS/IDE drives: */
+		if (maybe_scsi != 0 && cpt_bios_disk > cpt_ide_disk
+			&& dp->disknb >= 0x80 + cpt_bios_disk)
+			*cmdptr++ = 's';
+		else {
+			cpt_bios_disk = 0; /* no sda to hda correction */
+			*cmdptr++ = 'h';
+		}
+		*cmdptr++ = 'd';
+		/* If bootsector OSdisknumber initialised to something
+			else than 0 or 0x80, we assume the user forced
+			it and use that value ('a' for number 0x80): */
+		if ((dp->OSdisknumber & 0x7F) != 0)
+			*cmdptr++ = 'a' + (dp->OSdisknumber & 0x7F);
+		else
+			*cmdptr++ = 'a' + dp->disknb - 0x80 - cpt_bios_disk;
+		*cmdptr++ = '0' + OSnumber;
+		*cmdptr = '\0';
+	}
+}
+
+CODE static void
+vmlinuz_ROOT (const struct desc_str *system_desc,
+	      const struct gpl_compliant_str *togpl,
+	      char *command_line, unsigned nb_slash_in_kernelname)
+{
+	const struct disk_interface_str *DI =
+		 (const struct disk_interface_str *)togpl->DI;
+	char *cmdptr;
+#if 0	/* problem with linker, so do not call memset */
+	struct IDE_found_str IDE_found[10] = {};
+#else
+	struct IDE_found_str IDE_found[10];
+	unsigned i = sizeof (IDE_found) / sizeof(IDE_found[0]);
+	while (i--)
+		IDE_found[i].ideIOadr = IDE_found[i].ideIOctrladr
+			= IDE_found[i].irq = IDE_found[i].bios_order
+			= IDE_found[i].reserved = 0;
+#endif
+
+#if 0
+	DBG("togpl = 0x", (unsigned)togpl, ": ");
+	DBG("signature = 0x", togpl->signature, ", ");
+	DBG("version = 0x", togpl->version, ", ");
+	DBG("feature = 0x", togpl->feature, ", ");
+	DBG("size = 0x", togpl->size, ", ");
+	DBG("offsetof(struct gpl_compliant_str, DI) + 4 = 0x",
+		 offsetof(struct gpl_compliant_str, DI) + 4, "\r\n");
+	DBG_WAIT();
+#endif
+
+	if (togpl == 0 || togpl->signature != 16980327
+	    || (togpl->version >> 8) != 1 || (togpl->feature & 1) == 0
+	    || togpl->size <= offsetof(struct gpl_compliant_str, DI) + 4)
+		return;
+
+	init_IDE_found_from_cmdline (IDE_found,
+		sizeof(IDE_found)/sizeof(IDE_found[0]), command_line);
+	init_IDE_found_from_DI (IDE_found,
+		sizeof(IDE_found)/sizeof(IDE_found[0]), DI);
+
+#if 0
+	{
+	unsigned cpt;
+
+	for (cpt = 0; cpt < sizeof(IDE_found)/sizeof(IDE_found[0]); cpt++) {
+		DBG("IDE_found[cpt = 0x", cpt, "] : ");
+		DBG("ideIOadr = 0x", IDE_found[cpt].ideIOadr, ", ");
+		DBG("ideIOctrladr = 0x", IDE_found[cpt].ideIOctrladr, ", ");
+		DBG("irq = 0x", IDE_found[cpt].irq, ", ");
+		DBG("bios_order = 0x", IDE_found[cpt].bios_order, "\r\n");
+		}
+	DBG_WAIT();
+	}
+#endif
+
+	/* If "root=" is given, do not try to guess it: */
+	for (cmdptr = command_line; *cmdptr != '\0'; cmdptr++)
+		if (cmdptr[0] == 'r' && cmdptr[1] == 'o' && cmdptr[2] == 'o'
+			&& cmdptr[3] == 't' && cmdptr[4] == '=')
+			break;
+
+	/* sizeof struct diskparam_str 256, sizeof struct partition_str 64 */
+	if (*cmdptr == '\0'
+	    && sizeof (struct diskparam_str) == DI->sizeof_diskparam_str
+	    && sizeof (struct partition_str) == DI->sizeof_partition_str
+	    && DI->param[system_desc->disk].bytepersector != 0)
+		add_root_parameter (system_desc, cmdptr, IDE_found,
+				sizeof(IDE_found)/sizeof(IDE_found[0]),
+				DI, nb_slash_in_kernelname);
+
+	/* Add this after "root=", limited command line length */
+	finalise_cmdline (IDE_found,
+		sizeof(IDE_found)/sizeof(IDE_found[0]), command_line);
+}
+
+#else	/* ROOT_EXTENSIVE_SEARCH */
+
+struct desc_str;
+struct gpl_compliant_str;
+#define vmlinuz_ROOT(a, b, c, d)	/* nothing */
+
+#endif	/* ROOT_EXTENSIVE_SEARCH */
+
+CODE static inline void
+vmlinuz_DISKS (union drive_info *drive1, union drive_info *drive2
+#ifdef ROOT_EXTENSIVE_SEARCH
+		, const struct disk_interface_str *DI
+#endif
+		)
+{
+	unsigned nbsect;
+	unsigned char status, disk = 0x80;
+	union drive_info *drive = drive1;
+	farptr vectoradr = (farptr)(0x41 * 4);
+
+	while (disk <= 0x81) {
+#ifdef ROOT_EXTENSIVE_SEARCH
+		/* Some old and common SCSI card will do an invalid
+		instruction exception in _BIOSDISK_gettype, if the
+		BIOS has not been updated */
+		int cpt;
+		for (cpt = 0; cpt < DI->nb_bios_blacklist; cpt++)
+			if (DI->bios_blacklist[cpt] == disk)
+				break;
+		if (cpt < DI->nb_bios_blacklist)
+			continue;
+#endif
+
+		if (_BIOSDISK_gettype (disk, &nbsect, &status) == 0)
+			get_drive_info (vectoradr, drive);
+		disk++;
+		vectoradr = (farptr)(0x46 * 4);
+		drive = drive2;
+	}
+}
+
+/**
+ ** THE function:
+ **/
+struct LOADER_str {
+	unsigned short sizeof_loader_str, sizeof_fileload_str;
+	struct fileload_str {
+		/* input: */
+		unsigned load_address, max_size_or_crc32;
+		/* only for XMS use: */
+		unsigned KBalloced;
+		unsigned short handle;
+		/* For reference: */
+		unsigned short BOOTWAY_desc_index;
+		/* output: */
+		unsigned compressed_size, uncompressed_size;
+	} fileload[3], *curfileload;	/* kernel and initrd */
+	int initrd_index;
+	unsigned short minor_major_root;
+	unsigned short license_compliant;
+	unsigned vmlinuz_byte_treated; /* header + kernel GZIP */
+	unsigned uncompressed_signature;
+	unsigned ramdisk_max;
+	unsigned accept_uncompressed_initrd_filesize;
+	unsigned char post_comment_row, post_comment_col;
+	unsigned short reserved1;
+	unsigned reserved[5];
+	/* Initialised from the "comment" line of the GZIP file */
+	union {
+		unsigned array[32];
+		struct {
+			unsigned NONGPL_productID;
+			unsigned NONGPL_productNB;
+			unsigned min_gujin_version;	/* 0x100 for 1.0 */
+			unsigned late_relocation_address;
+			unsigned runadr;
+			unsigned paramadr;	/* usually 0x00080000 */
+			unsigned realfct_size;	/* in bytes */
+			unsigned minram;	/* in kilobytes */
+			unsigned option;
+			unsigned maskcpu;
+			unsigned maskDflags; /* request those bits set,
+					cpuid 0x00000001 in edx (usual) */
+			unsigned maskCflags; /* request those bits set,
+					cpuid 0x00000001 in ecx (new) */
+			unsigned maskBflags; /* unused on PCs */
+			unsigned maskAflags; /* request those bits set,
+					cpuid 0x80000001 */
+			unsigned maskvesa; /* if bit (8-1) set,
+						VESA 8BPP supported */
+			unsigned maskresolution; /* bit set => exclude
+						those modes */
+		} elem;
+	} comment;
+	/* related to Linux version: */
+	char cmdline_extraparam[512];
+	char cmdline_name[128];
+};
+
+CODE __attribute__ ((cdecl, regparm(0))) unsigned
+linux_set_params (unsigned local_return_address,
+		  unsigned totalmem,
+		  struct loader_t bootloader_type,
+		  struct linux_param *LnxParam,
+		  const struct LOADER_str *loader,
+		  const struct gpl_compliant_str *togpl,
+		  const struct desc_str *system_desc,
+		  int proposed_row,
+		  char **stringptr,
+		  unsigned char *proposed_cmdline)
+{
+	unsigned char *ptr;
+	unsigned nb_slash_in_kernelname = 0;
+	test_linux_param_struct();
+
+	vmlinuz_VIDEO (&LnxParam->screen_info, &LnxParam->in_out.vid_mode,
+		      proposed_row);
+
+	/* Just needed for old kernels, before 2.2.x: */
+	LnxParam->screen_info.EXT_MEM_K = vmlinuz_EXT_MEM_K();
+
+	/* old Command Line magic for 2.2- kernels: */
+	LnxParam->screen_info.CL_MAGIC = 0xA33F;
+	LnxParam->screen_info.CL_OFFSET = offsetof(struct linux_param,
+						   command_line);
+	/* New Command Line magic for 2.4+ kernels: */
+	LnxParam->in_out.cmd_line_ptr = loader->comment.elem.paramadr
+	    + offsetof (struct linux_param, command_line);
+
+/*  LnxParam->in_out.header_signature.longword = { { 'H', 'd', 'r', 'S' } }; */
+	LnxParam->in_out.header_version_number = 0x0202;
+	LnxParam->in_out.ramdisk_image = loader->fileload[1].load_address;
+	LnxParam->in_out.ramdisk_size = loader->fileload[1].uncompressed_size;
+	LnxParam->in_out.type_of_loader = bootloader_type;
+
+	LnxParam->ALT_MEM_K = totalmem;
+
+	vmlinuz_APM (&LnxParam->apm_bios_info);
+
+	_X86SpeedStepSmi (&LnxParam->X86SpeedStepSmi);
+	vmlinuz_DISKS (&LnxParam->drive1, &LnxParam->drive2
+#ifdef ROOT_EXTENSIVE_SEARCH
+			, (const struct disk_interface_str *)togpl->DI
+#endif
+			);
+	vmlinuz_CONFIG (&LnxParam->sys_desc_table);
+	/* do vmlinuz_EDID() before vmlinuz_E820() so that if the later
+	 function describes more than 18 (and less than 32) blocks of memory,
+	 the more important information erases the less important one.
+	 Since 2.6.12 there isn't any overwrite problem.*/
+	vmlinuz_EDID (&LnxParam->edid_data);
+	LnxParam->nb_E820_entries = vmlinuz_E820 (LnxParam->e820map,
+		sizeof(LnxParam->e820map));
+
+	/* Now the command line stuff: */
+	vmlinuz_CMDLINE (LnxParam->command_line, proposed_cmdline,
+			*(farptr *)stringptr,
+			loader->cmdline_name, loader->cmdline_extraparam);
+
+	for (ptr = LnxParam->command_line; *ptr != '\0'; ptr++) {
+		/* Do not try to be intelligent and do a 32 bits compare,
+		   it will generate constant in .rodata.str1.1 or .rodata
+		   with a version of GCC or another. */
+		if (ptr[0] == 'e' && ptr[1] == 'd' && ptr[2] == 'd'
+				  && ptr[3] == '=')
+			break;
+	}
+	/* I do not know about edd=skipmbr, if there is a read error
+		Gujin will not even boot up to there... */
+	if (*ptr == '\0' || ptr[4] != 'o' || ptr[5] != 'f' || ptr[6] != 'f') {
+		LnxParam->nb_MBRSIG_entries = vmlinuz_MBRSIG (LnxParam->MBRSIG,
+			sizeof(LnxParam->MBRSIG)/sizeof(LnxParam->MBRSIG[0]));
+		LnxParam->nb_EDD_entries = vmlinuz_EDD (LnxParam->edd,
+			sizeof(LnxParam->edd)/sizeof(LnxParam->edd[0]));
+	}
+
+	for (ptr = LnxParam->command_line; *ptr != '\0'; ptr++) {
+#define endparam(c) ((c) == ' ' || (c) == '\n' || (c) == '\t' || (c) == '\0')
+		if (ptr[0] == 'r' && (ptr[1] == 'w' || ptr[1] == 'o')
+				  && endparam(ptr[2])) {
+			LnxParam->in_out.root_flags.read_only
+					= (ptr[1] == 'w')? 0 : 1;
+			break;
+		} else {
+			while (!endparam(*ptr))
+				ptr++;
+		}
+	}
+
+	if (loader->cmdline_name)
+		for (ptr = (unsigned char *)loader->cmdline_name;
+		     *ptr != '\0';
+		     ptr++)
+			if (*ptr == '/')
+				nb_slash_in_kernelname++;
+	vmlinuz_ROOT (system_desc, togpl, LnxParam->command_line,
+			nb_slash_in_kernelname);
+
+	test_vgaprint();
+
+	*stringptr = 0; /* Gujin will not print anything by default */
+//	*stringptr = LnxParam->command_line;
+
+	return 0;
+}

                 reply	other threads:[~2007-02-06  0:05 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=94642.67267.qm@web26914.mail.ukl.yahoo.com \
    --to=etienne_lorrain@yahoo.fr \
    --cc=linux-kernel@vger.kernel.org \
    --subject='Re: [PATCH] Compressed ia32 ELF file generation for loading by Gujin 2/3' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).