On 28/06/07, Alex Roman <[EMAIL PROTECTED]> wrote:
That being said, I will clean up the code I have so far and send it as
a patch for review ASAP (tonight or tomorrow latest)...

I've cleaned up the code and created a patch which will enable allow
booting from the first CD-ROM on a system. This is my first patch so I
checked my code many times... hopefully it won't cause unwanted side
effects, and hopefully my patch is in the correct format.

This patch adds support for CD-ROM devices in biosdisk.c (cd0, cd1,
etc). It also adds 2 new files, eltorito.c and .h which implement a
command which will boot from the first CD-ROM device, cd0.

There are a few TODO's in the code.. This is just the first version,
more will come :)


Thanks,
... regards!


--
Alex Roman <[EMAIL PROTECTED]>
2007-07-03  Alex Roman  <[EMAIL PROTECTED]>
	* conf/i386-pc.rmk: Add eltorito.mod
	* include/grub/i386/pc/biosdisk.h: Add DPTE structure
	* include/grub/i386/pc/loader.h: Add grub_eltorito_boot function declaration
	* kern/i386/pc/startup.S: Add grub_eltorito_boot function
	* disk/i386/pc/biosdisk.c: Initial support for CD-ROM drives as "cd?"
	* loader/i386/pc/eltorito.c: New file
	* include/grub/eltorito.h: New file

Index: conf/i386-pc.rmk
===================================================================
RCS file: /sources/grub/grub2/conf/i386-pc.rmk,v
retrieving revision 1.81
diff -u -r1.81 i386-pc.rmk
--- conf/i386-pc.rmk	23 Jun 2007 14:44:37 -0000	1.81
+++ conf/i386-pc.rmk	4 Jul 2007 03:06:38 -0000
@@ -131,7 +131,8 @@
 pkgdata_MODULES = _chain.mod _linux.mod linux.mod normal.mod \
 	_multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod	\
 	vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \
-	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod
+	videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod \
+	eltorito.mod
 
 # For _chain.mod.
 _chain_mod_SOURCES = loader/i386/pc/chainloader.c
@@ -153,6 +154,11 @@
 linux_mod_CFLAGS = $(COMMON_CFLAGS)
 linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For eltorito.mod.
+eltorito_mod_SOURCES = loader/i386/pc/eltorito.c
+eltorito_mod_CFLAGS = $(COMMON_CFLAGS)
+eltorito_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For normal.mod.
 normal_mod_DEPENDENCIES = grub_script.tab.c grub_script.tab.h
 normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c	\
Index: include/grub/i386/pc/biosdisk.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/i386/pc/biosdisk.h,v
retrieving revision 1.5
diff -u -r1.5 biosdisk.h
--- include/grub/i386/pc/biosdisk.h	29 Jul 2006 10:11:01 -0000	1.5
+++ include/grub/i386/pc/biosdisk.h	4 Jul 2007 03:06:38 -0000
@@ -81,6 +81,24 @@
   grub_uint64_t block;
 } __attribute__ ((packed));
 
+/* Device Parameter Table Extension */
+struct grub_biosdisk_dpte
+{
+  grub_uint16_t io_port_base;
+  grub_uint16_t ctrl_port_base;
+  grub_uint8_t head_register;   /* upper nibble only */
+  grub_uint8_t bios_vendor_specific;
+  grub_uint8_t irq_info;
+  grub_uint8_t block_count;
+  grub_uint8_t dma_info;
+  grub_uint8_t pio_info;
+  grub_uint16_t bios_hw_flags;
+  grub_uint16_t reserved;
+  grub_uint8_t revision;
+  grub_uint8_t checksum;
+} __attribute__ ((packed));
+
+
 int EXPORT_FUNC(grub_biosdisk_rw_int13_extensions) (int ah, int drive, void *dap);
 int EXPORT_FUNC(grub_biosdisk_rw_standard) (int ah, int drive, int coff, int hoff,
 			       int soff, int nsec, int segment);
Index: include/grub/i386/pc/loader.h
===================================================================
RCS file: /sources/grub/grub2/include/grub/i386/pc/loader.h,v
retrieving revision 1.7
diff -u -r1.7 loader.h
--- include/grub/i386/pc/loader.h	12 Sep 2004 12:20:52 -0000	1.7
+++ include/grub/i386/pc/loader.h	4 Jul 2007 03:06:38 -0000
@@ -39,6 +39,8 @@
 					    struct grub_multiboot_info *mbi) 
      __attribute__ ((noreturn));
 
+ void EXPORT_FUNC(grub_eltorito_boot) (int drive, void *addr, int size) __attribute__ ((noreturn)); 
+
 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
 void grub_rescue_cmd_linux (int argc, char *argv[]);
Index: kern/i386/pc/startup.S
===================================================================
RCS file: /sources/grub/grub2/kern/i386/pc/startup.S,v
retrieving revision 1.24
diff -u -r1.24 startup.S
--- kern/i386/pc/startup.S	21 Jun 2007 21:01:11 -0000	1.24
+++ kern/i386/pc/startup.S	4 Jul 2007 03:06:38 -0000
@@ -2200,3 +2200,69 @@
 	popl	%ebx
 	popl	%ebp
 	ret
+
+/*
+ * grub_eltorito_boot (
+ *                     int drive,	// %eax
+ *                     void *addr.	// %edx
+ *                     int size		// %ecx
+ *                    ); 
+ *
+ * This function will load *size* bytes from *addr* at 7C00h, save drive in
+ * %dl, clear the segment registers and perform a long jump to 0:7C00h.
+ *
+ * The address is a linear address and will be converted to seg:off format.
+ */
+FUNCTION(grub_eltorito_boot)
+	
+	/* Re-organize the contents of registers using the stack */
+	pushl	%ecx	/* size  */
+	pushl	%eax	/* drive */
+	pushl	%edx	/* addr  */
+	
+	popl	%ebx	/* addr  */
+	popl	%edx	/* drive */
+	popl	%ecx	/* size  */
+	
+	xorl	%eax, %eax
+	movl	%eax, %edi
+	movl	%eax, %esi
+
+	/* Turn off Gate A20 */
+	pusha
+	xorl	%eax, %eax
+	call	EXT_C(grub_gate_a20)
+	popa
+	call	EXT_C(prot_to_real)
+	
+	.code16
+
+	/* rep movsb will copy %ecx bytes from %ds:%si to %es:%di */
+	
+	/* compute "copy from" address in %ds:%si */
+	movw	%bx, %si
+	xorw	%bx, %bx
+	shrl	$4, %ebx
+	movw	%bx, %ds
+	
+	/* load "copy to" address in %es:%di */
+	xorw	%ax, %ax
+	movw	%ax, %di
+	movw	$0x07C0, %ax
+	movw	%ax, %es
+	
+	/* %ecx contains number of bytes, so go ahead and copy! */
+	rep
+	movsb
+	
+	xorw	%ax, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %fs
+	movw	%ax, %gs
+	movw	%ax, %ss
+	
+	/* jump to 0:7C00h */
+	ljmp	$0,$0x7C00
+
+	.code32
\ No newline at end of file
Index: disk/i386/pc/biosdisk.c
===================================================================
RCS file: /sources/grub/grub2/disk/i386/pc/biosdisk.c,v
retrieving revision 1.9
diff -u -r1.9 biosdisk.c
--- disk/i386/pc/biosdisk.c	29 Jul 2006 10:11:01 -0000	1.9
+++ disk/i386/pc/biosdisk.c	4 Jul 2007 03:06:38 -0000
@@ -31,7 +31,7 @@
 {
   unsigned long drive;
 
-  if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
+  if ((name[0] != 'f' && name[0] != 'h' && name[0] != 'c') || name[1] != 'd')
     goto fail;
     
   drive = grub_strtoul (name + 2, 0, 10);
@@ -40,6 +40,8 @@
 
   if (name[0] == 'h')
     drive += 0x80;
+  else if (name[0] == 'c')
+    drive += 0xe0; 
   
   return (int) drive ;
 
@@ -52,8 +54,14 @@
 grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
 {
   char name[10];
-
-  grub_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
+  
+  if (drive & 0xe0)
+    grub_sprintf (name, "cd%d", drive & (~0xe0));
+  else if (drive & 0x80)
+    grub_sprintf (name, "hd%d", drive & (~0x80));
+  else
+    grub_sprintf (name, "fd%d", drive);
+  
   return hook (name);
 }
 
@@ -80,6 +88,8 @@
 	return 1;
     }
   
+  /* TODO: What to do for CD drives? */
+  
   return 0;
 }
 
@@ -94,7 +104,7 @@
   if (drive < 0)
     return grub_errno;
 
-  disk->has_partitions = (drive & 0x80);
+  disk->has_partitions = ((drive & 0x80) && !(drive & 0xe0));
   disk->id = drive;
   
   data = (struct grub_biosdisk_data *) grub_malloc (sizeof (*data));
@@ -133,17 +143,21 @@
 	}
     }
 
-  if (grub_biosdisk_get_diskinfo_standard (drive,
-					   &data->cylinders,
-					   &data->heads,
-					   &data->sectors) != 0)
-    {
-      grub_free (data);
-      return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get C/H/S values");
-    }
-
-  if (! total_sectors)
-    total_sectors = data->cylinders * data->heads * data->sectors;
+  /* We can't do this for CD drives */
+  if ( ! (drive & 0xe0) )
+  {
+    if (grub_biosdisk_get_diskinfo_standard (drive,
+  					   &data->cylinders,
+  					   &data->heads,
+  					   &data->sectors) != 0)
+      {
+        grub_free (data);
+        return grub_error (GRUB_ERR_BAD_DEVICE, "cannot get C/H/S values");
+      }
+  
+    if (! total_sectors)
+      total_sectors = data->cylinders * data->heads * data->sectors;
+  }
 
   disk->total_sectors = total_sectors;
   disk->data = data;
@@ -167,20 +181,23 @@
 		  unsigned segment)
 {
   struct grub_biosdisk_data *data = disk->data;
-  
+
   if (data->flags & GRUB_BIOSDISK_FLAG_LBA)
     {
       struct grub_biosdisk_dap *dap;
       
+      /* Place the DAP as the last thing in the scratch buffer */
       dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
-					  + (data->sectors
-					     << GRUB_DISK_SECTOR_BITS));
+                                        + GRUB_MEMORY_MACHINE_SCRATCH_SIZE
+                                        - sizeof (struct grub_biosdisk_dap));
+
+      grub_memset( dap, 0, sizeof (*dap) );
       dap->length = sizeof (*dap);
       dap->reserved = 0;
       dap->blocks = size;
       dap->buffer = segment << 16;	/* The format SEGMENT:ADDRESS.  */
-      dap->block = sector;
-
+      dap->block =  sector;
+      
       if (grub_biosdisk_rw_int13_extensions (cmd + 0x42, data->drive, dap))
 	{
 	  /* Fall back to the CHS mode.  */
Index: loader/i386/pc/eltorito.c
===================================================================
RCS file: loader/i386/pc/eltorito.c
diff -N loader/i386/pc/eltorito.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ loader/i386/pc/eltorito.c	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,301 @@
+/* eltorito.c - ElTorito CD-ROM Boot Standard, Loader */
+/*
+*  GRUB  --  GRand Unified Bootloader
+*  Copyright (C) 2003  Free Software Foundation, Inc.
+*  Copyright (C) 2003  NIIBE Yutaka <[EMAIL PROTECTED]>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <grub/machine/biosdisk.h>
+#include <grub/machine/memory.h>
+#include <grub/machine/loader.h>
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/device.h>
+#include <grub/disk.h>
+
+#include <grub/eltorito.h>
+
+/*
+ * Decode and print a Boot Record Volume Descriptor structure
+ */
+static void
+eltorito_dump_brvd( void * _brvd )
+{
+  grub_eltorito_boot_record_vol_descr brvd = _brvd;
+  char scrap[6];
+  
+  grub_memcpy (scrap, brvd->iso9660_identifier, 5);
+  scrap[5] = 0;
+
+  grub_printf ("BOOT RECORD VOLUME DESCRIPTOR @ 0x%08x\n", (grub_uint32_t)brvd);
+  grub_printf ("boot_record_indicator      : %d\n", brvd->boot_record_indicator);
+  grub_printf ("iso9660_identifier         : %s\n", scrap);
+  grub_printf ("version                    : %d\n", brvd->version);
+  grub_printf ("boot_system_identifier     : %s\n", brvd->boot_system_identifier);
+  grub_printf ("boot_catalog_pointer       : 0x%08x\n", brvd->boot_catalog_pointer);
+}
+
+/*
+ * Decode and print a Validation Entry structure
+ */
+static void
+eltorito_dump_ve (void *_ve)
+{
+  grub_eltorito_validation_entry ve = _ve;
+  grub_printf ("VALIDATION ENTRY @ 0x%08x:\n", (grub_uint32_t)ve);
+  grub_printf ("header_id                  : %d\n", ve->header_id);
+  grub_printf ("platform_id                : %d\n", ve->platform_id);
+  grub_printf ("id_string                  : %s\n", ve->id_string);
+  grub_printf ("checksum                   : 0x%04x\n", ve->checksum);
+  grub_printf ("key                        : 0x%04x\n", ve->key);
+}
+
+/*
+ * Decode and print an Initial/Default Entry structure
+ */
+static void
+eltorito_dump_de (void *_de)
+{
+  grub_eltorito_default_entry de = _de;
+  grub_printf ("INITIAL/DEFAULT ENTRY @ 0x%08x:\n", (grub_uint32_t)de);
+  grub_printf ("boot_indicator             : 0x%x\n", de->boot_indicator);
+  grub_printf ("boot_media_type            : %d\n", de->boot_media_type);
+  grub_printf ("load_segment               : 0x%04x\n", de->load_segment);
+  grub_printf ("system_type:               : %d\n", de->system_type);
+  grub_printf ("sector_count               : %d\n", de->sector_count);
+  grub_printf ("load_rba                   : 0x%08x\n", de->load_rba);
+}
+
+/*
+ * Dump a region in memory as hex bytes
+ */
+static void
+eltorito_dump_memory (void *edmp_buf, int count)
+{
+  int i;
+  grub_uint8_t *b = (grub_uint8_t *)edmp_buf;
+
+  for (i=0; i<count; i++)
+    {
+      if ((i % 16) == 0)
+        grub_printf ("\n%04d: ", i);
+      grub_printf ("%02x ", b[i]);
+    }
+  grub_printf ("\n");
+}
+
+/*
+ * The main command function
+ */
+static grub_err_t
+grub_cmd_eltorito (struct grub_arg_list *state __attribute__ ((unused)),
+                   int argc __attribute__ ((unused)),
+                   char **args __attribute__ ((unused)))
+{
+  /* A few structure pointers that we'll need. */
+  grub_eltorito_boot_record_vol_descr brvd;
+  grub_eltorito_validation_entry ve;
+  grub_eltorito_default_entry de;
+
+  /* Some other variables we'll need. */
+  grub_device_t cd_dev;
+  grub_disk_t disk;
+  grub_err_t err;
+
+  /* 
+   * Open the first CD device.
+   * TODO: make use of multiple CD-ROM devices, perhaps through parameters.
+   */
+  cd_dev = grub_device_open ("cd0");
+  if (!cd_dev)
+    {
+      return GRUB_ERR_BAD_DEVICE;
+    }
+  
+  /* Make sure there's a disk associated with the device. */
+  disk = cd_dev->disk;
+  if (!disk)
+    {
+      return GRUB_ERR_BAD_DEVICE;
+    }
+
+  /* 
+   * Attempt to read the Boot Record Volume Descriptor which is located at
+   * block 0x11, according to spec.
+   */
+  err = disk->dev->read (disk, 0x11, 1,
+                         (char *)GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+  if (err != GRUB_ERR_NONE)
+    {
+      grub_printf ("Error reading the BRVD (err=0x%x)\n", err);
+      return GRUB_ERR_READ_ERROR;
+    }
+  
+  brvd = (grub_eltorito_boot_record_vol_descr)GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  
+  /* For debugging, dump the BRVD */
+  eltorito_dump_brvd (brvd);
+            
+  /*
+   * Make sure the BRVD's contents make sense:
+   *    + boot_record_indicator needs to be 0
+   *    + version needs to be 1
+   *    + iso9660_identifier needs to be "CD001", not NULL terminated
+   *    + boot_system_identifier needs to be "EL_TORITO_SPECIFICATION"
+   */
+  if ( !(brvd->boot_record_indicator == 0 &&
+         brvd->version == 1 &&
+         grub_memcmp (brvd->iso9660_identifier, "CD001", 5) == 0 &&
+         grub_memcmp (brvd->boot_system_identifier, "EL TORITO SPECIFICATION", 24) == 0) )
+    {
+      grub_printf ("Read bad BRVD. Is the CD bootable?\n");
+      grub_printf ("bri = %d\n", brvd->boot_record_indicator);
+      grub_printf ("version = %d\n", brvd->version);
+      grub_printf ("%d\n", grub_memcmp (brvd->iso9660_identifier, "CD001", 5));
+      grub_printf ("%d\n", grub_memcmp (brvd->boot_system_identifier, "EL TORITO SPECIFICATION", 24));
+      return GRUB_ERR_READ_ERROR;
+    }
+  
+  /*
+   * All good! The BRVD will provide a pointer to the boot catalog.
+   * Attempt to read that block from the CD device.
+   */
+  err = disk->dev->read (disk, brvd->boot_catalog_pointer, 1,
+                        (char *)GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+  if (err != GRUB_ERR_NONE)
+    {
+      grub_printf ("Error reading the boot catalog from block 0x%x\n",
+                   brvd->boot_catalog_pointer);
+      return GRUB_ERR_READ_ERROR;
+    }
+  
+  /* The Validation Entry, VE, is the first entry in the Boot Catalog. */
+  ve = (grub_eltorito_validation_entry)GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+  
+  /* For debugging, dump the VE. */
+  eltorito_dump_ve (ve);
+
+  /*
+   * Make sure the VE makes sense:
+   *    + header_id must be 1
+   *    + reserved field must be 0
+   *    + key must be 0xaa55
+   * TODO: check the checksum
+   */
+  if ( !( ve->header_id == 0x01 &&
+          ve->reserved == 0x00 &&
+          ve->key == 0xaa55
+        ) )
+    {
+      grub_printf ("Error parsing the Validation Entry\n");
+      return GRUB_ERR_READ_ERROR;
+    }
+
+  /* Make sure we are running on the right platform. */
+  if (ve->platform_id == 0x00)
+    {
+      /* All good. */
+    }
+  else
+    {
+      /* Don't support non-x86 platforms yet, since it's not been ported yet. */
+      return GRUB_ERR_NOT_IMPLEMENTED_YET;
+    }
+
+  /* 
+   * The Validation Entry makes sense.
+   * The next entry is the Default/Initial Entry (DE).
+   */
+  de = (grub_eltorito_default_entry)(GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 32);
+
+  /* For debugging, dump the DE.*/
+  eltorito_dump_de (de);
+
+  /*
+   * Make sure the Default Entry is bootable.
+   * TODO: support entries that point to other entries, etc.
+   */
+  if ( de->boot_indicator != 0x88 )
+    {
+      grub_printf ("Error parsing the Default Entry\n");
+      return GRUB_ERR_READ_ERROR;
+    }
+
+  /* Figure out if we need to set up some sort of emulation. */
+  if (de->boot_media_type == 0x00)  /* No Emulation */
+    {
+      /* All good, nothing to do. */
+    }
+  else
+    {
+      /* Not so good, not sure what to do yet... */
+      /* TODO: fail gratiously */
+      return GRUB_ERR_NOT_IMPLEMENTED_YET;
+    }
+
+  /* Figure out at what address we need to load the boot image. */
+  if (de->load_segment == 0x00)
+    {
+      /* Load at the traditional 0x7c00. */
+    }
+  else
+    {
+      /*
+       * Other segments not supported/tested yet...
+       * TODO: make this work
+       */
+      return GRUB_ERR_NOT_IMPLEMENTED_YET;
+    }
+
+  /* All good, let's read the boot image. */
+  err = disk->dev->read (disk, de->load_rba, de->sector_count,
+                        (char *)GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
+  if (err != GRUB_ERR_NONE)
+    {
+      grub_printf ("Error reading the boot image from block 0x%x\n",
+                   de->load_rba);
+      return GRUB_ERR_READ_ERROR;
+    }
+
+  /* Okay, now let's try to boot... */
+  grub_eltorito_boot (disk->id, (char*)GRUB_MEMORY_MACHINE_SCRATCH_ADDR, 2048);
+
+  /* Should never get here... */
+  grub_printf ("Something BAD has happened...\n");
+
+  /* Dump the first 2K of the boot image. */
+  eltorito_dump_memory ((void*)0x7c00, 2048);
+
+  return GRUB_ERR_NONE;
+}
+
+GRUB_MOD_INIT(eltorito)
+{
+  (void)mod;			/* To stop warning. */
+  grub_register_command ("eltorito", grub_cmd_eltorito, GRUB_COMMAND_FLAG_BOTH,
+                         "eltorito", "ElTorito CD-ROM Booting", 0);
+}
+
+GRUB_MOD_FINI(eltorito)
+{
+  grub_unregister_command ("eltorito");
+}
Index: include/grub/eltorito.h
===================================================================
RCS file: include/grub/eltorito.h
diff -N include/grub/eltorito.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ include/grub/eltorito.h	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,150 @@
+/* eltorito.h - ElTorito CD-ROM Boot Standard */
+/*
+*  GRUB  --  GRand Unified Bootloader
+*  Copyright (C) 2003  Free Software Foundation, Inc.
+*  Copyright (C) 2003  NIIBE Yutaka <[EMAIL PROTECTED]>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef GRUB_ELTORITO_HEADER
+#define GRUB_ELTORITO_HEADER
+
+struct eltorito_spec_packet_tag
+{
+  grub_uint8_t  size;
+  grub_uint8_t  media_type;
+  grub_uint8_t  drive;
+  grub_uint8_t  controller_index;
+  grub_uint32_t lba;
+  grub_uint16_t dev_spec;
+  grub_uint16_t user_buf;
+  grub_uint16_t load_segment;
+  grub_uint16_t sector_count;
+  grub_uint8_t  cylinder_count_ch;
+  grub_uint8_t  cylinder_count_cl;
+  grub_uint8_t  head_count;
+
+} __attribute__ ((packed));
+typedef struct grub_eltorito_spec_packet_tag * eltorito_spec_packet;
+
+struct grub_eltorito_cmd_packet_tag
+{
+  grub_uint8_t  size;
+  grub_uint8_t  sector_count;
+  grub_uint32_t buffer;
+  grub_uint16_t start_sector;
+} __attribute__ ((packed));
+typedef struct grub_eltorito_cmd_packet_tage * grub_eltorito_cmd_packet;
+
+struct grub_eltorito_boot_record_vol_descr_tag
+{
+  // Boot Record Indicator, must be 0x00
+  grub_uint8_t    boot_record_indicator;
+
+  // ISO-9660 Identifier, must be "CD001"
+  grub_uint8_t    iso9660_identifier[5];
+
+  // Version of this descriptor, must be 1
+  grub_uint8_t    version;
+
+  // Boot System Identifier, must be "EL TORITO SPECIFICATION" padded
+  // with 0's
+  grub_uint8_t    boot_system_identifier[23];
+
+  // Unused, must be 0.
+  grub_uint8_t    unused1[41];
+
+  // Absolute pointer to first sector of Boot Catalog
+  grub_uint32_t   boot_catalog_pointer;
+
+  // Unused, must be 0.
+  grub_uint8_t    unused2[1973];
+} __attribute__ ((packed));
+typedef struct grub_eltorito_boot_record_vol_descr_tag* grub_eltorito_boot_record_vol_descr;
+
+struct grub_eltorito_validation_entry_tag 
+{
+  // Header ID, must be 0x01.
+  grub_uint8_t    header_id;
+
+  // Platform ID
+  //  0 = 80x86
+  //  1 = Power PC
+  //  2 = Mac
+  grub_uint8_t    platform_id;
+
+  // Reserved, must be 0.
+  grub_uint16_t   reserved;
+
+  // ID string. This is intended to identify the manufacturer/developer
+  // of this CD-ROM.
+  char            id_string[24];
+
+  // Checksum Word. This sum of all the words in this record should be 0.
+  grub_int16_t    checksum;
+
+  // Key word, must be 0x55AA. This value is included in the checksum
+  grub_uint16_t    key;
+} __attribute__ ((packed));
+typedef struct grub_eltorito_validation_entry_tag* grub_eltorito_validation_entry;
+
+struct grub_eltorito_default_entry_tag
+{
+  // Boot Indicator.
+  // 0x88 = Bootable, 0x00 = Not Bootable
+  grub_uint8_t    boot_indicator;
+
+  // Boot media type. This specifies what media the boot image is intended
+  // to emulate in bits 0-3 as follows, bits 4-7 are reserved and must be 0.
+  //
+  // Bits 0-3 count as follows:
+  //  0 = No Emulation
+  //  1 = 1.2 meg diskette
+  //  2 = 2.44 meg diskette
+  //  3 = 2.88 meg diskette
+  //  4 = Hard Disk (drive 80)
+  //
+  //  5-F Reserved, invalid at this time
+  grub_uint8_t    boot_media_type;
+
+  // Load Segment. This is the load segment for the initial boot image. If
+  // this value is 0 the system will use the traditional segment of 0x7C0.
+  // If this value is non-zero the system will use the specified segment.
+  // This applies to x86 architectures only. For "flat" model architectures
+  // (such as Motorola) this is the address divided by 0x10.
+  grub_uint16_t   load_segment;
+
+  // System Type. This must be a copy of byte 5 (System Type) from the
+  // Partition Table found in the boot image.
+  grub_uint8_t    system_type;
+
+  // Unused, must be 0
+  grub_uint8_t    unused1;
+
+  // Sector Count. This is the number of virtual/emulated sectors the system
+  // will store at Load Segment during the initial boot procedure
+  grub_uint16_t   sector_count;
+
+  // Load RBA. This is the start address of the virtual disk. CD's use
+  // Relative/Logical block addressing
+  grub_uint32_t   load_rba;
+
+  // Unused, must be 0
+  grub_uint8_t    unused2[20];
+} __attribute__ ((packed));
+typedef struct grub_eltorito_default_entry_tag* grub_eltorito_default_entry;
+
+#endif /* GRUB_ELTORITO_HEADER */

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to