[PATCH 3/3] Gujin linux.kgz boot format

From: Etienne Lorrain
Date: Thu Oct 06 2005 - 04:49:36 EST


Attached third patch adds the autodetection of the root filesystem
based on the disk / partition / directory of the kernel file loaded.

Signed-off-by: Etienne Lorrain <etienne_lorrain@xxxxxxxxx>

Etienne.
diff -uprN -X linux-2.6.14-rc3/Documentation/dontdiff -x '*.orig' -x '*.cmd' -x '.tmp*' -x '*.o' -x '*.ko' -x '*.a' -x '*.so' -x '.config*' -x asm-offsets.s -x asm_offsets.h -x vmlinux.lds -x vsyscall.lds -x '*.mod.c' -x Module.symvers -x consolemap_deftbl.c -x defkeymap.c -x classlist.h -x devlist.h -x asm -x md -x scsi -x logo -x config -x .version -x zconf.tab.h -x elfconfig.h -x System.map -x zconf.tab.c -x lex.zconf.c -x compile.h -x config_data.h -x version.h -x crc32table.h -x autoconf.h -x gen-devlist -x initramfs_list linux-2.6.14-rc3-2/arch/i386/kernel/realmode.c linux-2.6.14-rc3-3/arch/i386/kernel/realmode.c
--- linux-2.6.14-rc3-2/arch/i386/kernel/realmode.c 2005-10-04 15:45:57.015054296 +0200
+++ linux-2.6.14-rc3-3/arch/i386/kernel/realmode.c 2005-10-04 15:46:33.915444584 +0200
@@ -1234,11 +1234,578 @@ vmlinuz_CMDLINE (char *command_line, con
*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 } 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. */
+ union {
+ unsigned first_ext_partition_start; /* NOT A LONG LONG */
+ ISO9660_Validation_entry *ElToritoValidation; /* first one only */
+ ISO9660_Default_entry *ElToritoCatalog; /* array index >= 1 */
+ } extrainfo;
+ 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) /* bigger than "floppy" */
+ unsigned char name[MAX_DISKNAMESIZE];
+ } __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)
+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;
@@ -1246,6 +1813,18 @@ vmlinuz_DISKS (union drive_info *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++;
@@ -1350,7 +1929,11 @@ linux_set_params (unsigned local_return_
vmlinuz_APM (&LnxParam->apm_bios_info);

_X86SpeedStepSmi (&LnxParam->X86SpeedStepSmi);
- vmlinuz_DISKS (&LnxParam->drive1, &LnxParam->drive2);
+ 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,
@@ -1401,6 +1984,8 @@ linux_set_params (unsigned local_return_
ptr++)
if (*ptr == '/')
nb_slash_in_kernelname++;
+ vmlinuz_ROOT (system_desc, togpl, LnxParam->command_line,
+ nb_slash_in_kernelname);

test_vgaprint();

diff -uprN -X linux-2.6.14-rc3/Documentation/dontdiff -x '*.orig' -x '*.cmd' -x '.tmp*' -x '*.o' -x '*.ko' -x '*.a' -x '*.so' -x '.config*' -x asm-offsets.s -x asm_offsets.h -x vmlinux.lds -x vsyscall.lds -x '*.mod.c' -x Module.symvers -x consolemap_deftbl.c -x defkeymap.c -x classlist.h -x devlist.h -x asm -x md -x scsi -x logo -x config -x .version -x zconf.tab.h -x elfconfig.h -x System.map -x zconf.tab.c -x lex.zconf.c -x compile.h -x config_data.h -x version.h -x crc32table.h -x autoconf.h -x gen-devlist -x initramfs_list linux-2.6.14-rc3-2/include/asm-i386/realmode.h linux-2.6.14-rc3-3/include/asm-i386/realmode.h
--- linux-2.6.14-rc3-2/include/asm-i386/realmode.h 2005-10-04 15:45:57.091042744 +0200
+++ linux-2.6.14-rc3-3/include/asm-i386/realmode.h 2005-10-04 15:46:33.917444280 +0200
@@ -9,6 +9,10 @@
* loosing the EDD and EDID infomation which moved in Linux-2.6.12
*/

+/* try really hard to figure out the root filesystem when not given
+ on command line, uses Gujin data structures (GPL kernel) */
+#define ROOT_EXTENSIVE_SEARCH
+
/* 16 bits segment in MSB, 16 bits offset in LSB: */
typedef unsigned farptr;

diff -uprN -X linux-2.6.14-rc3/Documentation/dontdiff -x '*.orig' -x '*.cmd' -x '.tmp*' -x '*.o' -x '*.ko' -x '*.a' -x '*.so' -x '.config*' -x asm-offsets.s -x asm_offsets.h -x vmlinux.lds -x vsyscall.lds -x '*.mod.c' -x Module.symvers -x consolemap_deftbl.c -x defkeymap.c -x classlist.h -x devlist.h -x asm -x md -x scsi -x logo -x config -x .version -x zconf.tab.h -x elfconfig.h -x System.map -x zconf.tab.c -x lex.zconf.c -x compile.h -x config_data.h -x version.h -x crc32table.h -x autoconf.h -x gen-devlist -x initramfs_list linux-2.6.14-rc3-2/Makefile linux-2.6.14-rc3-3/Makefile
--- linux-2.6.14-rc3-2/Makefile 2005-10-04 15:45:57.093042440 +0200
+++ linux-2.6.14-rc3-3/Makefile 2005-10-04 15:46:33.919443976 +0200
@@ -1135,7 +1135,8 @@ help:
@echo 'Other generic targets:'
@echo ' all - Build all targets marked with [*]'
@echo '* vmlinux - Build the bare kernel'
- @echo ' /boot/linux.kgz ROOT=/dev/hda1 - replace "hda1" with your root filesystem'
+ @echo " /boot/linux-$(KERNELRELEASE).kgz - create a boot kernel for the Gujin bootloader"
+ @echo ' /boot/linux.kgz ROOT=/dev/hda1 - do not autodetect root filesystem at boot time'
@echo ' /boot/linux.kgz ROOT=auto - root filesystem from current /proc/cmdline'
@echo '* modules - Build all modules'
@echo ' modules_install - Install all modules'