diff --git a/ChangeLog b/ChangeLog index 41f0f2950..5eeb9982c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2007-11-05 Robert Millan + + * kern/disk.c (grub_disk_firmware_fini) + (grub_disk_firmware_is_tainted): New variables. + + * include/grub/disk.h (grub_disk_firmware_fini) + (grub_disk_firmware_is_tainted): Likewise. + + * disk/i386/pc/biosdisk.c (GRUB_MOD_FINI(biosdisk)): Moved from here ... + (grub_disk_biosdisk_fini): ... to here. + (GRUB_MOD_FINI(biosdisk)): Implement using grub_disk_biosdisk_fini(). + (GRUB_MOD_INIT(biosdisk)): Abort when `grub_disk_firmware_is_tainted' + is set. Register grub_disk_biosdisk_fini() in + `grub_disk_firmware_fini'. + + * disk/ata.c: Remove `'. + (GRUB_MOD_INIT(ata)): Remove grub_biosdisk_fini() call. + Use `grub_disk_firmware_is_tainted' and `grub_disk_firmware_fini' + to finish existing firmware disk interface. + + * conf/i386-linuxbios.rmk (pkgdata_MODULES): Add `ata.mod'. + (ata_mod_SOURCES): New variable. + (ata_mod_CFLAGS): Likewise. + (ata_mod_LDFLAGS): Likewise. + 2007-11-05 Robert Millan * disk/ata.c: Remove `'. Include `'. diff --git a/conf/i386-linuxbios.mk b/conf/i386-linuxbios.mk index 346e1e1c7..a215db742 100644 --- a/conf/i386-linuxbios.mk +++ b/conf/i386-linuxbios.mk @@ -657,7 +657,7 @@ grub_emu_LDFLAGS = $(LIBCURSES) # Modules. pkgdata_MODULES = _linux.mod linux.mod normal.mod \ _multiboot.mod multiboot.mod play.mod \ - cpuid.mod serial.mod + cpuid.mod serial.mod ata.mod # For _linux.mod. _linux_mod_SOURCES = loader/i386/pc/linux.c @@ -1324,4 +1324,56 @@ fs-cpuid_mod-commands_i386_cpuid.lst: commands/i386/cpuid.c genfslist.sh cpuid_mod_CFLAGS = $(COMMON_CFLAGS) cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For ata.mod. +ata_mod_SOURCES = disk/ata.c +CLEANFILES += ata.mod mod-ata.o mod-ata.c pre-ata.o ata_mod-disk_ata.o und-ata.lst +ifneq ($(ata_mod_EXPORTS),no) +CLEANFILES += def-ata.lst +DEFSYMFILES += def-ata.lst +endif +MOSTLYCLEANFILES += ata_mod-disk_ata.d +UNDSYMFILES += und-ata.lst + +ata.mod: pre-ata.o mod-ata.o + -rm -f $@ + $(TARGET_CC) $(ata_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-ata.o: $(ata_mod_DEPENDENCIES) ata_mod-disk_ata.o + -rm -f $@ + $(TARGET_CC) $(ata_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ ata_mod-disk_ata.o + +mod-ata.o: mod-ata.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -c -o $@ $< + +mod-ata.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'ata' $< > $@ || (rm -f $@; exit 1) + +ifneq ($(ata_mod_EXPORTS),no) +def-ata.lst: pre-ata.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 ata/' > $@ +endif + +und-ata.lst: pre-ata.o + echo 'ata' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +ata_mod-disk_ata.o: disk/ata.c + $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -MD -c -o $@ $< +-include ata_mod-disk_ata.d + +CLEANFILES += cmd-ata_mod-disk_ata.lst fs-ata_mod-disk_ata.lst +COMMANDFILES += cmd-ata_mod-disk_ata.lst +FSFILES += fs-ata_mod-disk_ata.lst + +cmd-ata_mod-disk_ata.lst: disk/ata.c gencmdlist.sh + set -e; $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh ata > $@ || (rm -f $@; exit 1) + +fs-ata_mod-disk_ata.lst: disk/ata.c genfslist.sh + set -e; $(TARGET_CC) -Idisk -I$(srcdir)/disk $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(ata_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh ata > $@ || (rm -f $@; exit 1) + + +ata_mod_CFLAGS = $(COMMON_CFLAGS) +ata_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/common.mk diff --git a/conf/i386-linuxbios.rmk b/conf/i386-linuxbios.rmk index 7a1d3eab6..99aa5dc30 100644 --- a/conf/i386-linuxbios.rmk +++ b/conf/i386-linuxbios.rmk @@ -95,7 +95,7 @@ grub_emu_LDFLAGS = $(LIBCURSES) # Modules. pkgdata_MODULES = _linux.mod linux.mod normal.mod \ _multiboot.mod multiboot.mod play.mod \ - cpuid.mod serial.mod + cpuid.mod serial.mod ata.mod # For _linux.mod. _linux_mod_SOURCES = loader/i386/pc/linux.c @@ -146,4 +146,9 @@ cpuid_mod_SOURCES = commands/i386/cpuid.c cpuid_mod_CFLAGS = $(COMMON_CFLAGS) cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For ata.mod. +ata_mod_SOURCES = disk/ata.c +ata_mod_CFLAGS = $(COMMON_CFLAGS) +ata_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/common.mk diff --git a/disk/ata.c b/disk/ata.c index f6514548b..30dea7918 100644 --- a/disk/ata.c +++ b/disk/ata.c @@ -24,7 +24,6 @@ #include /* XXX: For now this only works on i386. */ #include -#include typedef enum { @@ -733,8 +732,13 @@ GRUB_MOD_INIT(ata) { (void) mod; /* To stop warning. */ - /* XXX: To prevent two drivers operating on the same disks. */ - grub_biosdisk_fini (); + /* To prevent two drivers operating on the same disks. */ + grub_disk_firmware_is_tainted = 1; + if (grub_disk_firmware_fini) + { + grub_disk_firmware_fini (); + grub_disk_firmware_fini = NULL; + } /* ATA initialization. */ grub_ata_initialize (); diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c index fe23a402d..618ae75e5 100644 --- a/disk/i386/pc/biosdisk.c +++ b/disk/i386/pc/biosdisk.c @@ -312,12 +312,25 @@ static struct grub_disk_dev grub_biosdisk_dev = .next = 0 }; +static void +grub_disk_biosdisk_fini (void) +{ + grub_disk_dev_unregister (&grub_biosdisk_dev); +} + GRUB_MOD_INIT(biosdisk) { + if (grub_disk_firmware_is_tainted) + { + grub_printf ("Firmware is marked as tainted, refusing to initialize.\n"); + return; + } + grub_disk_firmware_fini = grub_disk_biosdisk_fini; + grub_disk_dev_register (&grub_biosdisk_dev); } GRUB_MOD_FINI(biosdisk) { - grub_disk_dev_unregister (&grub_biosdisk_dev); + grub_disk_biosdisk_fini (); } diff --git a/include/grub/disk.h b/include/grub/disk.h index 8b23151c2..430194270 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -137,6 +137,9 @@ grub_err_t EXPORT_FUNC(grub_disk_write) (grub_disk_t disk, grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk); +extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void); +extern int EXPORT_VAR(grub_disk_firmware_is_tainted); + #ifdef GRUB_UTIL void grub_raid_init (void); void grub_raid_fini (void); diff --git a/kern/disk.c b/kern/disk.c index 4a6fb56fa..9e0f60b07 100644 --- a/kern/disk.c +++ b/kern/disk.c @@ -43,6 +43,9 @@ struct grub_disk_cache static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM]; +void (*grub_disk_firmware_fini) (void); +int grub_disk_firmware_is_tainted; + #if 0 static unsigned long grub_disk_cache_hits; static unsigned long grub_disk_cache_misses;