2007-07-03 Alex Roman
* 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
+*
+* 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
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+/*
+ * 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; idisk;
+ 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
+*
+* 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 */