Merge mainline into bidi

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-03-30 11:24:28 +02:00
commit f651947b58
79 changed files with 4334 additions and 3313 deletions

View file

@ -25,6 +25,8 @@ docs/version.texi
*.exec *.exec
genkernsyms.sh genkernsyms.sh
gensymlist.sh gensymlist.sh
gentrigtables
grub-bin2h
grub-dumpbios grub-dumpbios
grub-editenv grub-editenv
grub-emu grub-emu
@ -40,8 +42,13 @@ grub-pe2elf
grub-probe grub-probe
grub_probe_init.c grub_probe_init.c
grub_probe_init.h grub_probe_init.h
grub-reboot
grub-script-check
grub_script_check_init.c
grub_script_check_init.h
grub_script.tab.c grub_script.tab.c
grub_script.tab.h grub_script.tab.h
grub-set-default
grub-setup grub-setup
grub_setup_init.c grub_setup_init.c
grub_setup_init.h grub_setup_init.h
@ -62,5 +69,6 @@ stamp-h
stamp-h1 stamp-h1
stamp-h.in stamp-h.in
symlist.c symlist.c
trigtables.c
update-grub_lib update-grub_lib
unidata.c unidata.c

252
ChangeLog
View file

@ -1,3 +1,255 @@
2010-03-30 Vladimir Serbinenko <phcoder@gmail.com>
* loader/i386/multiboot_mbi2.c (retrieve_video_parameters): Fix
compilation on coreboot and qemu
2010-03-28 Vladimir Serbinenko <phcoder@gmail.com>
* include/multiboot2.h: Resync with spec.
2010-03-28 Vladimir Serbinenko <phcoder@gmail.com>
Multiboot2 tag support
* conf/i386.rmk (multiboot2_mod_SOURCES): Replace
loader/i386/multiboot_mbi.c with loader/i386/multiboot_mbi2.c.
Remove loader/multiboot_loader.c.
* include/grub/i386/multiboot.h (grub_multiboot_real_boot): Removed.
(grub_multiboot2_real_boot): Likewise.
* include/grub/multiboot.h (grub_multiboot_set_accepts_video): Removed.
(grub_get_multiboot_mmap_count): New proto.
(grub_fill_multiboot_mmap): Likewise.
(grub_multiboot_set_video_mode): Likewise.
(grub_multiboot_set_console): Likewise.
(grub_multiboot_load): Likewise.
(grub_multiboot_load_elf): Likewise.
(GRUB_MULTIBOOT_CONSOLE_EGA_TEXT): New definition.
(GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER): Likewise.
* include/multiboot.h: Resynced with specification.
* include/multiboot2.h: Resynced with specification.
* loader/i386/multiboot_mbi.c (DEFAULT_VIDEO_MODE): Moved from here...
* loader/i386/multiboot.c (DEFAULT_VIDEO_MODE): ... here.
* loader/i386/multiboot_mbi.c (HAS_VGA_TEXT): Moved from here ..
* include/grub/multiboot.h (GRUB_MACHINE_HAS_VGA_TEXT): ... here. All
users updated.
* loader/i386/multiboot_mbi.c (accepts_video): Moved from here...
* loader/i386/multiboot.c (accepts_video): ... here. All users updated.
* loader/i386/multiboot_mbi.c (grub_multiboot_set_accepts_video):
Removed.
* loader/i386/multiboot_mbi.c (grub_get_multiboot_mmap_len):
Moved from here...
* loader/i386/multiboot.c (grub_get_multiboot_mmap_len): ... here.
* loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap):
Moved from here...
* loader/i386/multiboot.c (grub_fill_multiboot_mmap): ... here.
* loader/i386/multiboot_mbi.c (set_video_mode): Moved from here...
* loader/i386/multiboot.c (grub_multiboot_set_video_mode): ... here.
All users updated.
* loader/i386/multiboot_mbi2.c: New file.
2010-03-27 Vladimir Serbinenko <phcoder@gmail.com>
Resync with gnulib.
* Makefile.in (GNULIB_CFLAGS): New variable.
* conf/common.rmk (grub_mkisofs_CFLAGS): Add GNULIB_CFLAGS.
(grub_script_check_CFLAGS): New variable.
* gnulib/alloca.h: Resync with gnulib.
* gnulib/error.c: Likewise.
* gnulib/error.h: Likewise.
* gnulib/fnmatch.c: Likewise.
* gnulib/fnmatch_loop.c: Likewise.
* gnulib/getdelim.c: Likewise.
* gnulib/getline.c: Likewise.
* gnulib/getopt.c: Likewise.
* gnulib/getopt1.c: Likewise.
* gnulib/getopt_int.h: Likewise.
* gnulib/gettext.h: Likewise.
* gnulib/progname.c: Likewise.
* gnulib/progname.h: Likewise.
2010-03-27 Grégoire Sutre <gregoire.sutre@gmail.com>
Fix a build failure (-Wundef -Werror) when ENABLE_NLS is not defined,
which is the case with --disabled-nls.
* include/grub/i18n.h: Use (defined(ENABLE_NLS)
&& ENABLE_NLS) instead of ENABLE_NLS in all #if preprocessor macros.
* util/misc.c: Likewise.
* util/mkisofs/mkisofs.c: Likewise.
* util/mkisofs/mkisofs.h: Likewise.
2010-03-27 Vladimir Serbinenko <phcoder@gmail.com>
Simplify Apple CC support.
* commands/i386/pc/drivemap_int13h.S: Use LOCAL when possible.
Add 0 byte at the end not to have a symbol with empty target.
* mmap/i386/pc/mmap_helper.S: Likewise.
* genmk.rb: Ignore errors 2030 and 2050.
* kern/i386/pc/startup.S: Use LOCAL when possible.
2010-03-26 BVK Chaitanya <bvk.groups@gmail.com>
Testcase and the fix for final semicolon on cmdline.
* tests/grub_script_final_semicolon.in: New testcase.
* conf/tests.rmk: Rules for the new testcase.
* script/parser.y: Grammar fix.
2010-03-26 BVK Chaitanya <bvk@localhost>
Blank lines testcase for GRUB script.
* tests/grub_script_blanklines.in: New testcase.
* conf/tests.rmk: Rules for the new testcase.
2010-03-26 Vladimir Serbinenko <phcoder@gmail.com>
Don't use __FILE__.
* genmk.rb: Add -DGRUB_FILE to all C targets.
* fs/reiserfs.c: Replace __FILE__ with GRUB_FILE.
* include/grub/list.h: Likewise.
* include/grub/misc.h: Likewise.
* include/grub/mm.h: Likewise.
* include/grub/test.h: Likewise.
* kern/mm.c: Likewise.
* lib/libgcrypt_wrap/cipher_wrap.h: Likewise.
2010-03-26 Vladimir Serbinenko <phcoder@gmail.com>
Sunpc partitions support.
* conf/common.rmk (grub_probe_SOURCES): Add partmap/sunpc.c.
(grub_fstest_SOURCES): Likewise.
(pkglib_MODULES): Add part_sunpc.mod.
(part_sunpc_mod_SOURCES): New variable.
(part_sunpc_mod_CFLAGS): Likewise.
(part_sunpc_mod_LDFLAGS): Likewise.
* conf/i386-pc.rmk (grub_setup_SOURCES): Add partmap/sunpc.c.
* partmap/sunpc.c: New file.
2010-03-26 BVK Chaitanya <bvk@localhost>
For loop support to GRUB script.
* include/grub/script_sh.h (grub_script_cmdfor): New struct.
(grub_script_create_cmdfor): New function prototype.
(grub_script_execute_cmdfor): New function prototype.
* script/execute.c (grub_script_execute_cmdfor): New function.
* script/parser.y (command): New for command.
(forcmd): New grammar rule.
* script/script.c (grub_script_create_cmdfor): New function.
* util/grub-script-check.c (grub_script_execute_cmdfor): New
function.
* tests/grub_script_for1.in: New testcase.
* conf/tests.rmk: Rules for new testcase.
2010-03-26 Vladimir Serbinenko <phcoder@gmail.com>
Nested partitions
* commands/blocklist.c (grub_cmd_blocklist): Don't check whether
'partition' is NULL, grub_partition_get_start already does that.
* commands/loadenv.c (check_blocklists): Likewise.
(write_blocklists): Likewise.
* conf/common.rmk (grub_probe_SOURCES): Add partmap/bsdlabel.c.
(grub_fstest_SOURCES): Likewise.
(pkglib_MODULES): Add part_bsd.mod.
(part_bsd_mod_SOURCES): New variable.
(part_bsd_mod_CFLAGS): Likewise.
(part_bsd_mod_LDFLAGS): Likewise.
* conf/i386-pc.rmk (grub_setup_SOURCES): Add partmap/bsdlabel.c.
(grub_emu_SOURCES): Likewise.
* conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise.
* include/grub/bsdlabel.h: New file.
* include/grub/partition.h (grub_partition_map): Remove 'probe' and
'get_name'.
(grub_partition): Add 'parent' and 'number'. Remove 'data'.
(grub_partition_map_list): New variable.
(grub_partition_map_register): Inline.
(grub_partition_map_unregister): Likewise.
(FOR_PARTITION_MAPS): New macro.
(grub_partition_map_iterate): Removed.
(grub_partition_get_start): Handle nested partitions.
* include/grub/msdos_partition.h: Remove bsd-related entries.
(grub_pc_partition): Remove.
* kern/disk.c (grub_disk_close): Free partition data.
(grub_disk_adjust_range): Handle nested partitions.
* kern/partition.c (grub_partition_map_probe): New function.
(grub_partition_probe): Parse name to number, handle subpartitions.
(get_partmap): New function.
(grub_partition_iterate): Handle subpartitions.
(grub_partition_get_name): Likewise.
* loader/i386/pc/bsd.c (grub_bsd_get_device): Likewise.
* loader/i386/multiboot.c (grub_multiboot_get_bootdev): Likewise.
* loader/i386/pc/chainloader.c (grub_chainloader_cmd): Likewise.
* partmap/acorn.c (acorn_partition_map_iterate): Don't force raw access.
Set 'number'.
(acorn_partition_map_probe): Remove.
(acorn_partition_map_get_name): Likewise.
* partmap/amiga.c (amiga_partition_map_iterate): Don't force raw access.
Set 'number'.
Set 'index' to 0 since there can be only one partition entry per sector.
(amiga_partition_map_probe): Remove.
(amiga_partition_map_get_name): Likewise.
* partmap/apple.c (apple_partition_map_iterate): Don't force raw access.
Set 'number'.
Set 'offset' and 'index' to real positions of partitions.
(apple_partition_map_probe): Remove.
(apple_partition_map_get_name): Likewise.
* partmap/bsdlabel.c: New file.
* partmap/gpt.c (gpt_partition_map_iterate): Don't force raw access.
Set 'number'.
Allocate 'data' so it can be correctly freed.
Set 'index' to offset inside sector.
(gpt_partition_map_probe): Remove.
(gpt_partition_map_get_name): Likewise.
* partmap/msdos.c (grub_partition_parse): Remove.
(pc_partition_map_iterate): Don't force raw access.
Set 'number'.
Make 'ext_offset' a local variable.
(pc_partition_map_probe): Remove.
(pc_partition_map_get_name): Remove.
* partmap/sun.c (sun_partition_map_iterate): Don't force raw access.
Set 'number'.
(sun_partition_map_probe): Remove.
(sun_partition_map_get_name): Likewise.
* parttool/msdospart.c (grub_pcpart_boot): Handle nested partitions.
(grub_pcpart_type): Likewise.
* util/hostdisk.c (open_device): Handle new numbering scheme.
(grub_util_biosdisk_get_grub_dev): Handle nested partitions.
* util/i386/pc/grub-setup.c (setup): Handle new numbering scheme.
* util/grub-probe.c (probe_partmap): Handle nested paritions.
* util/grub-install.in: Insert all subpartition modules.
* util/ieee1275/grub-install.in: Likewise.
2010-03-24 Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
* kern/dl.c (grub_dl_resolve_symbols): Improve error message
grammar.
2010-03-24 Colin Watson <cjwatson@ubuntu.com>
* .bzrignore: Add grub-bin2h, grub-reboot, and grub-set-default.
2010-03-21 Colin Watson <cjwatson@ubuntu.com>
* util/grub-install.in: Copy .mo files from @datadir@/locale, to
match where 'make install' puts them.
* util/i386/efi/grub-install.in: Likewise.
2010-03-19 Colin Watson <cjwatson@ubuntu.com>
* .bzrignore: Add gentrigtables, grub-script-check,
grub_script_check_init.c, grub_script_check_init.h, and
trigtables.c.
2010-03-18 Vladimir Serbinenko <phcoder@gmail.com>
* kern/parser.c: Indented.
2010-03-17 Vladimir Serbinenko <phcoder@gmail.com> 2010-03-17 Vladimir Serbinenko <phcoder@gmail.com>
* term/i386/pc/vesafb.c: Removed (orphaned, deprecated and broken). * term/i386/pc/vesafb.c: Removed (orphaned, deprecated and broken).

View file

@ -79,6 +79,7 @@ LIBS = @LIBS@ $(LIBINTL)
CC = @CC@ CC = @CC@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
GNULIB_CFLAGS = -Wno-undef -D_GL_UNUSED="__attribute__ ((unused))"
ASFLAGS = @ASFLAGS@ ASFLAGS = @ASFLAGS@
LDFLAGS = @LDFLAGS@ $(LIBS) LDFLAGS = @LDFLAGS@ $(LIBS)
CPPFLAGS = @CPPFLAGS@ -I$(builddir) -I$(builddir)/include -I$(srcdir)/gnulib -I$(srcdir)/include -Wall -W \ CPPFLAGS = @CPPFLAGS@ -I$(builddir) -I$(builddir)/include -I$(srcdir)/gnulib -I$(srcdir)/include -Wall -W \

View file

@ -90,8 +90,7 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
return grub_error (GRUB_ERR_BAD_DEVICE, return grub_error (GRUB_ERR_BAD_DEVICE,
"this command is available only for disk devices"); "this command is available only for disk devices");
if (file->device->disk->partition) part_start = grub_partition_get_start (file->device->disk->partition);
part_start = grub_partition_get_start (file->device->disk->partition);
file->read_hook = read_blocklist; file->read_hook = read_blocklist;

View file

@ -19,7 +19,7 @@
#include <grub/symbol.h> #include <grub/symbol.h>
#define INT13H_OFFSET(x) ((x) - EXT_C(grub_drivemap_handler)) #define INT13H_OFFSET(x) ((x) - LOCAL (base))
.code16 .code16
@ -27,6 +27,7 @@
/* The replacement int13 handler. Preserve all registers. */ /* The replacement int13 handler. Preserve all registers. */
FUNCTION(grub_drivemap_handler) FUNCTION(grub_drivemap_handler)
LOCAL (base):
/* Save %dx for future restore. */ /* Save %dx for future restore. */
push %dx push %dx
/* Push flags. Used to simulate interrupt with original flags. */ /* Push flags. Used to simulate interrupt with original flags. */
@ -35,12 +36,7 @@ FUNCTION(grub_drivemap_handler)
/* Map the drive number (always in DL). */ /* Map the drive number (always in DL). */
push %ax push %ax
push %bx push %bx
#ifdef APPLE_CC movw $INT13H_OFFSET(LOCAL (mapstart)), %bx
grub_drivemap_mapstart_ofs = INT13H_OFFSET(EXT_C(grub_drivemap_mapstart))
movw $grub_drivemap_mapstart_ofs, %bx
#else
movw $INT13H_OFFSET(EXT_C(grub_drivemap_mapstart)), %bx
#endif
more_remaining: more_remaining:
movw %cs:(%bx), %ax movw %cs:(%bx), %ax
@ -66,12 +62,7 @@ not_found:
popf popf
pushf pushf
#ifdef APPLE_CC lcall *%cs:INT13H_OFFSET (LOCAL (oldhandler))
grub_drivemap_oldhandler_ofs = INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
lcall *%cs:grub_drivemap_oldhandler_ofs
#else
lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
#endif
push %bp push %bp
mov %sp, %bp mov %sp, %bp
@ -94,11 +85,7 @@ norestore:
popf popf
pushf pushf
#ifdef APPLE_CC lcall *%cs:INT13H_OFFSET (LOCAL (oldhandler))
lcall *%cs:grub_drivemap_oldhandler_ofs
#else
lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
#endif
push %bp push %bp
mov %sp, %bp mov %sp, %bp
@ -111,9 +98,13 @@ norestore:
/* Far pointer to the old handler. Stored as a CS:IP in the style of real-mode /* Far pointer to the old handler. Stored as a CS:IP in the style of real-mode
IVT entries (thus PI:SC in mem). */ IVT entries (thus PI:SC in mem). */
VARIABLE(grub_drivemap_oldhandler) VARIABLE(grub_drivemap_oldhandler)
LOCAL (oldhandler):
.word 0x0, 0x0 .word 0x0, 0x0
/* This label MUST be at the end of the copied block, since the installer code /* This label MUST be at the end of the copied block, since the installer code
reserves additional space for mappings at runtime and copies them over it. */ reserves additional space for mappings at runtime and copies them over it. */
.align 2 .align 2
VARIABLE(grub_drivemap_mapstart) VARIABLE(grub_drivemap_mapstart)
LOCAL (mapstart):
.byte 0

View file

@ -235,10 +235,8 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
/* One more sanity check. Re-read all sectors by blocklists, and compare /* One more sanity check. Re-read all sectors by blocklists, and compare
those with the data read via a file. */ those with the data read via a file. */
disk = file->device->disk; disk = file->device->disk;
if (disk->partition)
part_start = grub_partition_get_start (disk->partition); part_start = grub_partition_get_start (disk->partition);
else
part_start = 0;
buf = grub_envblk_buffer (envblk); buf = grub_envblk_buffer (envblk);
for (p = blocklists, index = 0; p; index += p->length, p = p->next) for (p = blocklists, index = 0; p; index += p->length, p = p->next)
@ -268,10 +266,7 @@ write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
buf = grub_envblk_buffer (envblk); buf = grub_envblk_buffer (envblk);
disk = file->device->disk; disk = file->device->disk;
if (disk->partition) part_start = grub_partition_get_start (disk->partition);
part_start = grub_partition_get_start (disk->partition);
else
part_start = 0;
index = 0; index = 0;
for (p = blocklists; p; index += p->length, p = p->next) for (p = blocklists; p; index += p->length, p = p->next)

View file

@ -35,7 +35,8 @@ grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c \
fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c \ fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c \
fs/befs.c fs/befs_be.c fs/tar.c \ fs/befs.c fs/befs_be.c fs/tar.c \
\ \
partmap/msdos.c partmap/apple.c partmap/sun.c partmap/gpt.c\ partmap/msdos.c partmap/bsdlabel.c partmap/apple.c \
partmap/sun.c partmap/sunpc.c partmap/gpt.c \
kern/fs.c kern/env.c fs/fshelp.c \ kern/fs.c kern/env.c fs/fshelp.c \
disk/raid.c disk/mdraid_linux.c disk/lvm.c grub_probe_init.c disk/raid.c disk/mdraid_linux.c disk/lvm.c grub_probe_init.c
@ -55,7 +56,7 @@ grub_mkisofs_SOURCES = util/mkisofs/eltorito.c \
gnulib/error.c gnulib/progname.c gnulib/error.c gnulib/progname.c
grub_mkisofs_CFLAGS = -D_FILE_OFFSET_BITS=64 \ grub_mkisofs_CFLAGS = -D_FILE_OFFSET_BITS=64 \
-I$(srcdir)/util/mkisofs/include \ -I$(srcdir)/util/mkisofs/include \
-Wno-all -Werror -Wno-all -Werror $(GNULIB_CFLAGS)
# For grub-fstest. # For grub-fstest.
util/grub-fstest.c_DEPENDENCIES = grub_fstest_init.h util/grub-fstest.c_DEPENDENCIES = grub_fstest_init.h
@ -72,8 +73,8 @@ grub_fstest_SOURCES = gnulib/progname.c util/grub-fstest.c util/hostfs.c \
fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c fs/befs.c \ fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c fs/befs.c \
fs/befs_be.c fs/tar.c \ fs/befs_be.c fs/tar.c \
\ \
kern/partition.c partmap/msdos.c partmap/apple.c partmap/sun.c \ kern/partition.c partmap/msdos.c partmap/bsdlabel.c \
partmap/gpt.c \ partmap/apple.c partmap/sun.c partmap/sunpc.c partmap/gpt.c \
kern/fs.c kern/env.c fs/fshelp.c disk/raid.c \ kern/fs.c kern/env.c fs/fshelp.c disk/raid.c \
disk/raid5_recover.c disk/raid6_recover.c \ disk/raid5_recover.c disk/raid6_recover.c \
disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \ disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
@ -110,7 +111,7 @@ grub_script_check_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c
kern/handler.c kern/err.c kern/parser.c kern/list.c \ kern/handler.c kern/err.c kern/parser.c kern/list.c \
kern/misc.c kern/env.c grub_script_check_init.c grub_script.tab.c \ kern/misc.c kern/env.c grub_script_check_init.c grub_script.tab.c \
grub_script.yy.c grub_script.yy.c
grub_script_check_CFLAGS = $(GNULIB_CFLAGS)
MOSTLYCLEANFILES += symlist.c kernel_syms.lst MOSTLYCLEANFILES += symlist.c kernel_syms.lst
DEFSYMFILES += kernel_syms.lst DEFSYMFILES += kernel_syms.lst
@ -403,6 +404,16 @@ part_gpt_mod_SOURCES = partmap/gpt.c
part_gpt_mod_CFLAGS = $(COMMON_CFLAGS) part_gpt_mod_CFLAGS = $(COMMON_CFLAGS)
part_gpt_mod_LDFLAGS = $(COMMON_LDFLAGS) part_gpt_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += part_bsd.mod
part_bsd_mod_SOURCES = partmap/bsdlabel.c
part_bsd_mod_CFLAGS = $(COMMON_CFLAGS)
part_bsd_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += part_sunpc.mod
part_sunpc_mod_SOURCES = partmap/sunpc.c
part_sunpc_mod_CFLAGS = $(COMMON_CFLAGS)
part_sunpc_mod_LDFLAGS = $(COMMON_LDFLAGS)
# Special disk structures and generic drivers # Special disk structures and generic drivers
pkglib_MODULES += raid.mod raid5rec.mod raid6rec.mod mdraid.mod dm_nv.mod \ pkglib_MODULES += raid.mod raid5rec.mod raid6rec.mod mdraid.mod dm_nv.mod \

View file

@ -80,13 +80,14 @@ grub_setup_SOURCES = gnulib/progname.c \
kern/file.c kern/fs.c kern/env.c kern/list.c \ kern/file.c kern/fs.c kern/env.c kern/list.c \
fs/fshelp.c \ fs/fshelp.c \
\ \
fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \ fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \
fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \ fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \ fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \
fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c \ fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c \
fs/befs.c fs/befs_be.c fs/tar.c \ fs/befs.c fs/befs_be.c fs/tar.c \
\ \
partmap/msdos.c partmap/gpt.c \ partmap/msdos.c partmap/bsdlabel.c partmap/sunpc.c \
partmap/gpt.c \
\ \
disk/raid.c disk/mdraid_linux.c disk/lvm.c \ disk/raid.c disk/mdraid_linux.c disk/lvm.c \
util/raid.c util/lvm.c \ util/raid.c util/lvm.c \

View file

@ -34,16 +34,14 @@ setpci_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += multiboot.mod pkglib_MODULES += multiboot.mod
multiboot_mod_SOURCES = loader/i386/multiboot.c \ multiboot_mod_SOURCES = loader/i386/multiboot.c \
loader/i386/multiboot_mbi.c \ loader/i386/multiboot_mbi.c
loader/multiboot_loader.c
multiboot_mod_CFLAGS = $(COMMON_CFLAGS) multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS) multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS)
pkglib_MODULES += multiboot2.mod pkglib_MODULES += multiboot2.mod
multiboot2_mod_SOURCES = loader/i386/multiboot.c \ multiboot2_mod_SOURCES = loader/i386/multiboot.c \
loader/i386/multiboot_mbi.c \ loader/i386/multiboot_mbi2.c
loader/multiboot_loader.c
multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2 multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2
multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS) multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS) multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS)

View file

@ -61,8 +61,8 @@ grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c util/hostdisk.c \
fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c \ fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c \
fs/befs.c fs/befs_be.c fs/tar.c \ fs/befs.c fs/befs_be.c fs/tar.c \
\ \
partmap/amiga.c partmap/apple.c partmap/msdos.c \ partmap/amiga.c partmap/apple.c partmap/msdos.c \
partmap/sun.c partmap/acorn.c \ partmap/bsdlabel.c partmap/sun.c partmap/acorn.c \
\ \
disk/raid.c disk/mdraid_linux.c disk/lvm.c \ disk/raid.c disk/mdraid_linux.c disk/lvm.c \
util/raid.c util/lvm.c gnulib/progname.c \ util/raid.c util/lvm.c gnulib/progname.c \

View file

@ -50,6 +50,15 @@ grub_script_echo_keywords_SOURCES = tests/grub_script_echo_keywords.in
check_SCRIPTS += grub_script_vars1 check_SCRIPTS += grub_script_vars1
grub_script_vars1_SOURCES = tests/grub_script_vars1.in grub_script_vars1_SOURCES = tests/grub_script_vars1.in
check_SCRIPTS += grub_script_for1
grub_script_for1_SOURCES = tests/grub_script_for1.in
check_SCRIPTS += grub_script_blanklines
grub_script_blanklines_SOURCES = tests/grub_script_blanklines.in
check_SCRIPTS += grub_script_final_semicolon
grub_script_final_semicolon_SOURCES = tests/grub_script_final_semicolon.in
# List of tests to execute on "make check" # List of tests to execute on "make check"
# SCRIPTED_TESTS = example_scripted_test # SCRIPTED_TESTS = example_scripted_test
# SCRIPTED_TESTS += example_grub_script_test # SCRIPTED_TESTS += example_grub_script_test
@ -59,6 +68,9 @@ grub_script_vars1_SOURCES = tests/grub_script_vars1.in
SCRIPTED_TESTS = grub_script_echo1 SCRIPTED_TESTS = grub_script_echo1
SCRIPTED_TESTS += grub_script_echo_keywords SCRIPTED_TESTS += grub_script_echo_keywords
SCRIPTED_TESTS += grub_script_vars1 SCRIPTED_TESTS += grub_script_vars1
SCRIPTED_TESTS += grub_script_for1
SCRIPTED_TESTS += grub_script_blanklines
SCRIPTED_TESTS += grub_script_final_semicolon
# dependencies between tests and testing-tools # dependencies between tests and testing-tools
$(SCRIPTED_TESTS): grub-shell grub-shell-tester $(SCRIPTED_TESTS): grub-shell grub-shell-tester

View file

@ -62,7 +62,7 @@
static grub_dl_t my_mod; static grub_dl_t my_mod;
#define assert(boolean) real_assert (boolean, __FILE__, __LINE__) #define assert(boolean) real_assert (boolean, GRUB_FILE, __LINE__)
static inline void static inline void
real_assert (int boolean, const char *file, const int line) real_assert (int boolean, const char *file, const int line)
{ {

View file

@ -91,7 +91,7 @@ endif
dir = File.dirname(src) dir = File.dirname(src)
"#{obj}: #{src} $(#{src}_DEPENDENCIES) "#{obj}: #{src} $(#{src}_DEPENDENCIES)
$(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $< $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -DGRUB_FILE=\\\"#{src}\\\" -MD -c -o $@ $<
-include #{dep} -include #{dep}
" "
@ -161,7 +161,7 @@ else
-rm -f $@ -rm -f $@
-rm -f $@.bin -rm -f $@.bin
$(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin #{pre_obj} #{mod_obj} $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin #{pre_obj} #{mod_obj}
$(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -nu -nd $@.bin $@ $(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -ew2030 -ew2050 -nu -nd $@.bin $@
-rm -f $@.bin -rm -f $@.bin
endif endif
endif endif
@ -171,7 +171,7 @@ endif
$(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ #{objs_str} $(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ #{objs_str}
#{mod_obj}: #{mod_src} #{mod_obj}: #{mod_src}
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(#{prefix}_CFLAGS) -c -o $@ $< $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(#{prefix}_CFLAGS) -DGRUB_FILE=\\\"#{mod_src}\\\" -c -o $@ $<
#{mod_src}: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh #{mod_src}: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1) sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1)
@ -205,7 +205,7 @@ endif
dir = File.dirname(src) dir = File.dirname(src)
"#{obj}: #{src} $(#{src}_DEPENDENCIES) "#{obj}: #{src} $(#{src}_DEPENDENCIES)
$(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $< $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -DGRUB_FILE=\\\"#{src}\\\" -MD -c -o $@ $<
-include #{dep} -include #{dep}
clean-module-#{extra_target}.#{@rule_count}: clean-module-#{extra_target}.#{@rule_count}:
@ -307,7 +307,7 @@ MOSTLYCLEAN_UTILITY_TARGETS += mostlyclean-utility-#{@name}.#{@rule_count}
dir = File.dirname(src) dir = File.dirname(src)
"#{obj}: #{src} $(#{src}_DEPENDENCIES) "#{obj}: #{src} $(#{src}_DEPENDENCIES)
$(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(#{prefix}_CFLAGS) -MD -c -o $@ $< $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(#{prefix}_CFLAGS) -DGRUB_FILE=\\\"#{src}\\\" -MD -c -o $@ $<
-include #{dep} -include #{dep}
" "
@ -354,7 +354,7 @@ endif
dir = File.dirname(src) dir = File.dirname(src)
"#{obj}: #{src} $(#{src}_DEPENDENCIES) "#{obj}: #{src} $(#{src}_DEPENDENCIES)
$(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $< $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -DGRUB_FILE=\\\"#{src}\\\" -MD -c -o $@ $<
-include #{dep} -include #{dep}

View file

@ -1,7 +1,7 @@
/* Memory allocation on the stack. /* Memory allocation on the stack.
Copyright (C) 1995, 1999, 2001-2004, 2006-2008 Free Software Copyright (C) 1995, 1999, 2001-2004, 2006-2010 Free Software Foundation,
Foundation, Inc. Inc.
This program is free software; you can redistribute it and/or modify it This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published under the terms of the GNU General Public License as published

View file

@ -1,5 +1,5 @@
/* Error handler for noninteractive utilities /* Error handler for noninteractive utilities
Copyright (C) 1990-1998, 2000-2007, 2009 Free Software Foundation, Inc. Copyright (C) 1990-1998, 2000-2007, 2009-2010 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -70,8 +70,8 @@ unsigned int error_message_count;
extern void __error (int status, int errnum, const char *message, ...) extern void __error (int status, int errnum, const char *message, ...)
__attribute__ ((__format__ (__printf__, 3, 4))); __attribute__ ((__format__ (__printf__, 3, 4)));
extern void __error_at_line (int status, int errnum, const char *file_name, extern void __error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message, unsigned int line_number, const char *message,
...) ...)
__attribute__ ((__format__ (__printf__, 5, 6)));; __attribute__ ((__format__ (__printf__, 5, 6)));;
# define error __error # define error __error
# define error_at_line __error_at_line # define error_at_line __error_at_line
@ -86,6 +86,7 @@ extern void __error_at_line (int status, int errnum, const char *file_name,
#else /* not _LIBC */ #else /* not _LIBC */
# include <fcntl.h> # include <fcntl.h>
# include <unistd.h>
# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
# ifndef HAVE_DECL_STRERROR_R # ifndef HAVE_DECL_STRERROR_R
@ -100,8 +101,33 @@ extern char *program_name;
# if HAVE_STRERROR_R || defined strerror_r # if HAVE_STRERROR_R || defined strerror_r
# define __strerror_r strerror_r # define __strerror_r strerror_r
# endif /* HAVE_STRERROR_R || defined strerror_r */ # endif /* HAVE_STRERROR_R || defined strerror_r */
#endif /* not _LIBC */ #endif /* not _LIBC */
static inline void
flush_stdout (void)
{
#if !_LIBC && defined F_GETFL
int stdout_fd;
# if GNULIB_FREOPEN_SAFER
/* Use of gnulib's freopen-safer module normally ensures that
fileno (stdout) == 1
whenever stdout is open. */
stdout_fd = STDOUT_FILENO;
# else
/* POSIX states that fileno (stdout) after fclose is unspecified. But in
practice it is not a problem, because stdout is statically allocated and
the fd of a FILE stream is stored as a field in its allocated memory. */
stdout_fd = fileno (stdout);
# endif
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= stdout_fd && 0 <= fcntl (stdout_fd, F_GETFL))
#endif
fflush (stdout);
}
static void static void
print_errno_message (int errnum) print_errno_message (int errnum)
@ -149,58 +175,58 @@ error_tail (int status, int errnum, const char *message, va_list args)
bool use_malloc = false; bool use_malloc = false;
while (1) while (1)
{ {
if (__libc_use_alloca (len * sizeof (wchar_t))) if (__libc_use_alloca (len * sizeof (wchar_t)))
wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
else else
{ {
if (!use_malloc) if (!use_malloc)
wmessage = NULL; wmessage = NULL;
wchar_t *p = (wchar_t *) realloc (wmessage, wchar_t *p = (wchar_t *) realloc (wmessage,
len * sizeof (wchar_t)); len * sizeof (wchar_t));
if (p == NULL) if (p == NULL)
{ {
free (wmessage); free (wmessage);
fputws_unlocked (L"out of memory\n", stderr); fputws_unlocked (L"out of memory\n", stderr);
return; return;
} }
wmessage = p; wmessage = p;
use_malloc = true; use_malloc = true;
} }
memset (&st, '\0', sizeof (st)); memset (&st, '\0', sizeof (st));
tmp = message; tmp = message;
res = mbsrtowcs (wmessage, &tmp, len, &st); res = mbsrtowcs (wmessage, &tmp, len, &st);
if (res != len) if (res != len)
break; break;
if (__builtin_expect (len >= SIZE_MAX / 2, 0)) if (__builtin_expect (len >= SIZE_MAX / 2, 0))
{ {
/* This really should not happen if everything is fine. */ /* This really should not happen if everything is fine. */
res = (size_t) -1; res = (size_t) -1;
break; break;
} }
len *= 2; len *= 2;
} }
if (res == (size_t) -1) if (res == (size_t) -1)
{ {
/* The string cannot be converted. */ /* The string cannot be converted. */
if (use_malloc) if (use_malloc)
{ {
free (wmessage); free (wmessage);
use_malloc = false; use_malloc = false;
} }
wmessage = (wchar_t *) L"???"; wmessage = (wchar_t *) L"???";
} }
__vfwprintf (stderr, wmessage, args); __vfwprintf (stderr, wmessage, args);
if (use_malloc) if (use_malloc)
free (wmessage); free (wmessage);
} }
else else
#endif #endif
@ -235,16 +261,10 @@ error (int status, int errnum, const char *message, ...)
cancellation. Therefore disable cancellation for now. */ cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE; int state = PTHREAD_CANCEL_ENABLE;
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
0); 0);
#endif #endif
#if !_LIBC && defined F_GETFL flush_stdout ();
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= fcntl (1, F_GETFL))
#endif
fflush (stdout);
#ifdef _LIBC #ifdef _LIBC
_IO_flockfile (stderr); _IO_flockfile (stderr);
#endif #endif
@ -276,7 +296,7 @@ int error_one_per_line;
void void
error_at_line (int status, int errnum, const char *file_name, error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message, ...) unsigned int line_number, const char *message, ...)
{ {
va_list args; va_list args;
@ -286,10 +306,10 @@ error_at_line (int status, int errnum, const char *file_name,
static unsigned int old_line_number; static unsigned int old_line_number;
if (old_line_number == line_number if (old_line_number == line_number
&& (file_name == old_file_name && (file_name == old_file_name
|| strcmp (old_file_name, file_name) == 0)) || strcmp (old_file_name, file_name) == 0))
/* Simply return and print nothing. */ /* Simply return and print nothing. */
return; return;
old_file_name = file_name; old_file_name = file_name;
old_line_number = line_number; old_line_number = line_number;
@ -300,16 +320,10 @@ error_at_line (int status, int errnum, const char *file_name,
cancellation. Therefore disable cancellation for now. */ cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE; int state = PTHREAD_CANCEL_ENABLE;
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
0); 0);
#endif #endif
#if !_LIBC && defined F_GETFL flush_stdout ();
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= fcntl (1, F_GETFL))
#endif
fflush (stdout);
#ifdef _LIBC #ifdef _LIBC
_IO_flockfile (stderr); _IO_flockfile (stderr);
#endif #endif
@ -326,10 +340,10 @@ error_at_line (int status, int errnum, const char *file_name,
#if _LIBC #if _LIBC
__fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ", __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
file_name, line_number); file_name, line_number);
#else #else
fprintf (stderr, file_name != NULL ? "%s:%d: " : " ", fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
file_name, line_number); file_name, line_number);
#endif #endif
va_start (args, message); va_start (args, message);

View file

@ -1,5 +1,6 @@
/* Declaration for error-reporting function /* Declaration for error-reporting function
Copyright (C) 1995, 1996, 1997, 2003, 2006, 2008 Free Software Foundation, Inc. Copyright (C) 1995, 1996, 1997, 2003, 2006, 2008, 2009, 2010 Free Software
Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -19,19 +20,18 @@
#define _ERROR_H 1 #define _ERROR_H 1
#ifndef __attribute__ #ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */ /* The __attribute__ feature is available in gcc versions 2.5 and later.
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) The __-protected variants of the attributes 'format' and 'printf' are
# define __attribute__(Spec) /* empty */ accepted by gcc versions 2.6.4 (effectively 2.7) and later.
# endif We enable __attribute__ only if these are supported too, because
/* The __-protected variants of `format' and `printf' attributes gnulib and libintl do '#define printf __printf__' when they override
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ the 'printf' function. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __format__ format # define __attribute__(Spec) /* empty */
# define __printf__ printf
# endif # endif
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -43,7 +43,7 @@ extern void error (int __status, int __errnum, const char *__format, ...)
__attribute__ ((__format__ (__printf__, 3, 4))); __attribute__ ((__format__ (__printf__, 3, 4)));
extern void error_at_line (int __status, int __errnum, const char *__fname, extern void error_at_line (int __status, int __errnum, const char *__fname,
unsigned int __lineno, const char *__format, ...) unsigned int __lineno, const char *__format, ...)
__attribute__ ((__format__ (__printf__, 5, 6))); __attribute__ ((__format__ (__printf__, 5, 6)));
/* If NULL, error will flush stdout, then print on stderr the program /* If NULL, error will flush stdout, then print on stderr the program
@ -58,7 +58,7 @@ extern unsigned int error_message_count;
variable controls whether this mode is selected or not. */ variable controls whether this mode is selected or not. */
extern int error_one_per_line; extern int error_one_per_line;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -1,5 +1,5 @@
/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007 /* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
Free Software Foundation, Inc. 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -21,7 +21,7 @@
/* Enable GNU extensions in fnmatch.h. */ /* Enable GNU extensions in fnmatch.h. */
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
# define _GNU_SOURCE 1 # define _GNU_SOURCE 1
#endif #endif
#if ! defined __builtin_expect && __GNUC__ < 3 #if ! defined __builtin_expect && __GNUC__ < 3
@ -89,7 +89,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
# define isblank(c) ((c) == ' ' || (c) == '\t') # define isblank(c) ((c) == ' ' || (c) == '\t')
# endif # endif
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) # define STREQ(s1, s2) (strcmp (s1, s2) == 0)
# if defined _LIBC || WIDE_CHAR_SUPPORT # if defined _LIBC || WIDE_CHAR_SUPPORT
/* The GNU C library provides support for user-defined character classes /* The GNU C library provides support for user-defined character classes
@ -109,25 +109,25 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
# endif # endif
# ifdef _LIBC # ifdef _LIBC
# define ISWCTYPE(WC, WT) __iswctype (WC, WT) # define ISWCTYPE(WC, WT) __iswctype (WC, WT)
# else # else
# define ISWCTYPE(WC, WT) iswctype (WC, WT) # define ISWCTYPE(WC, WT) iswctype (WC, WT)
# endif # endif
# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC # if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
/* In this case we are implementing the multibyte character handling. */ /* In this case we are implementing the multibyte character handling. */
# define HANDLE_MULTIBYTE 1 # define HANDLE_MULTIBYTE 1
# endif # endif
# else # else
# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ # define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
# define IS_CHAR_CLASS(string) \ # define IS_CHAR_CLASS(string) \
(STREQ (string, "alpha") || STREQ (string, "upper") \ (STREQ (string, "alpha") || STREQ (string, "upper") \
|| STREQ (string, "lower") || STREQ (string, "digit") \ || STREQ (string, "lower") || STREQ (string, "digit") \
|| STREQ (string, "alnum") || STREQ (string, "xdigit") \ || STREQ (string, "alnum") || STREQ (string, "xdigit") \
|| STREQ (string, "space") || STREQ (string, "print") \ || STREQ (string, "space") || STREQ (string, "print") \
|| STREQ (string, "punct") || STREQ (string, "graph") \ || STREQ (string, "punct") || STREQ (string, "graph") \
|| STREQ (string, "cntrl") || STREQ (string, "blank")) || STREQ (string, "cntrl") || STREQ (string, "blank"))
# endif # endif
@ -145,17 +145,17 @@ static int posixly_correct;
/* Note that this evaluates C many times. */ /* Note that this evaluates C many times. */
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) # define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
# define CHAR char # define CHAR char
# define UCHAR unsigned char # define UCHAR unsigned char
# define INT int # define INT int
# define FCT internal_fnmatch # define FCT internal_fnmatch
# define EXT ext_match # define EXT ext_match
# define END end_pattern # define END end_pattern
# define L_(CS) CS # define L_(CS) CS
# ifdef _LIBC # ifdef _LIBC
# define BTOWC(C) __btowc (C) # define BTOWC(C) __btowc (C)
# else # else
# define BTOWC(C) btowc (C) # define BTOWC(C) btowc (C)
# endif # endif
# define STRLEN(S) strlen (S) # define STRLEN(S) strlen (S)
# define STRCAT(D, S) strcat (D, S) # define STRCAT(D, S) strcat (D, S)
@ -175,14 +175,14 @@ static int posixly_correct;
# if HANDLE_MULTIBYTE # if HANDLE_MULTIBYTE
# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c)) # define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
# define CHAR wchar_t # define CHAR wchar_t
# define UCHAR wint_t # define UCHAR wint_t
# define INT wint_t # define INT wint_t
# define FCT internal_fnwmatch # define FCT internal_fnwmatch
# define EXT ext_wmatch # define EXT ext_wmatch
# define END end_wpattern # define END end_wpattern
# define L_(CS) L##CS # define L_(CS) L##CS
# define BTOWC(C) (C) # define BTOWC(C) (C)
# ifdef _LIBC # ifdef _LIBC
# define STRLEN(S) __wcslen (S) # define STRLEN(S) __wcslen (S)
# define STRCAT(D, S) __wcscat (D, S) # define STRCAT(D, S) __wcscat (D, S)
@ -218,40 +218,40 @@ is_char_class (const wchar_t *wcs)
/* Test for a printable character from the portable character set. */ /* Test for a printable character from the portable character set. */
# ifdef _LIBC # ifdef _LIBC
if (*wcs < 0x20 || *wcs > 0x7e if (*wcs < 0x20 || *wcs > 0x7e
|| *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
return (wctype_t) 0; return (wctype_t) 0;
# else # else
switch (*wcs) switch (*wcs)
{ {
case L' ': case L'!': case L'"': case L'#': case L'%': case L' ': case L'!': case L'"': case L'#': case L'%':
case L'&': case L'\'': case L'(': case L')': case L'*': case L'&': case L'\'': case L'(': case L')': case L'*':
case L'+': case L',': case L'-': case L'.': case L'/': case L'+': case L',': case L'-': case L'.': case L'/':
case L'0': case L'1': case L'2': case L'3': case L'4': case L'0': case L'1': case L'2': case L'3': case L'4':
case L'5': case L'6': case L'7': case L'8': case L'9': case L'5': case L'6': case L'7': case L'8': case L'9':
case L':': case L';': case L'<': case L'=': case L'>': case L':': case L';': case L'<': case L'=': case L'>':
case L'?': case L'?':
case L'A': case L'B': case L'C': case L'D': case L'E': case L'A': case L'B': case L'C': case L'D': case L'E':
case L'F': case L'G': case L'H': case L'I': case L'J': case L'F': case L'G': case L'H': case L'I': case L'J':
case L'K': case L'L': case L'M': case L'N': case L'O': case L'K': case L'L': case L'M': case L'N': case L'O':
case L'P': case L'Q': case L'R': case L'S': case L'T': case L'P': case L'Q': case L'R': case L'S': case L'T':
case L'U': case L'V': case L'W': case L'X': case L'Y': case L'U': case L'V': case L'W': case L'X': case L'Y':
case L'Z': case L'Z':
case L'[': case L'\\': case L']': case L'^': case L'_': case L'[': case L'\\': case L']': case L'^': case L'_':
case L'a': case L'b': case L'c': case L'd': case L'e': case L'a': case L'b': case L'c': case L'd': case L'e':
case L'f': case L'g': case L'h': case L'i': case L'j': case L'f': case L'g': case L'h': case L'i': case L'j':
case L'k': case L'l': case L'm': case L'n': case L'o': case L'k': case L'l': case L'm': case L'n': case L'o':
case L'p': case L'q': case L'r': case L's': case L't': case L'p': case L'q': case L'r': case L's': case L't':
case L'u': case L'v': case L'w': case L'x': case L'y': case L'u': case L'v': case L'w': case L'x': case L'y':
case L'z': case L'{': case L'|': case L'}': case L'~': case L'z': case L'{': case L'|': case L'}': case L'~':
break; break;
default: default:
return (wctype_t) 0; return (wctype_t) 0;
} }
# endif # endif
/* Avoid overrunning the buffer. */ /* Avoid overrunning the buffer. */
if (cp == s + CHAR_CLASS_MAX_LENGTH) if (cp == s + CHAR_CLASS_MAX_LENGTH)
return (wctype_t) 0; return (wctype_t) 0;
*cp++ = (char) *wcs++; *cp++ = (char) *wcs++;
} }
@ -287,58 +287,58 @@ fnmatch (const char *pattern, const char *string, int flags)
int res; int res;
/* Calculate the size needed to convert the strings to /* Calculate the size needed to convert the strings to
wide characters. */ wide characters. */
memset (&ps, '\0', sizeof (ps)); memset (&ps, '\0', sizeof (ps));
patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1; patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1;
if (__builtin_expect (patsize != 0, 1)) if (__builtin_expect (patsize != 0, 1))
{ {
assert (mbsinit (&ps)); assert (mbsinit (&ps));
strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1; strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
if (__builtin_expect (strsize != 0, 1)) if (__builtin_expect (strsize != 0, 1))
{ {
assert (mbsinit (&ps)); assert (mbsinit (&ps));
totsize = patsize + strsize; totsize = patsize + strsize;
if (__builtin_expect (! (patsize <= totsize if (__builtin_expect (! (patsize <= totsize
&& totsize <= SIZE_MAX / sizeof (wchar_t)), && totsize <= SIZE_MAX / sizeof (wchar_t)),
0)) 0))
{ {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
/* Allocate room for the wide characters. */ /* Allocate room for the wide characters. */
if (__builtin_expect (totsize < ALLOCA_LIMIT, 1)) if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t)); wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
else else
{ {
wpattern = malloc (totsize * sizeof (wchar_t)); wpattern = malloc (totsize * sizeof (wchar_t));
if (__builtin_expect (! wpattern, 0)) if (__builtin_expect (! wpattern, 0))
{ {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
} }
wstring = wpattern + patsize; wstring = wpattern + patsize;
/* Convert the strings into wide characters. */ /* Convert the strings into wide characters. */
mbsrtowcs (wpattern, &pattern, patsize, &ps); mbsrtowcs (wpattern, &pattern, patsize, &ps);
assert (mbsinit (&ps)); assert (mbsinit (&ps));
mbsrtowcs (wstring, &string, strsize, &ps); mbsrtowcs (wstring, &string, strsize, &ps);
res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1, res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
flags & FNM_PERIOD, flags); flags & FNM_PERIOD, flags);
if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0)) if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
free (wpattern); free (wpattern);
return res; return res;
} }
} }
} }
# endif /* HANDLE_MULTIBYTE */ # endif /* HANDLE_MULTIBYTE */
return internal_fnmatch (pattern, string, string + strlen (string), return internal_fnmatch (pattern, string, string + strlen (string),
flags & FNM_PERIOD, flags); flags & FNM_PERIOD, flags);
} }
# ifdef _LIBC # ifdef _LIBC
@ -351,4 +351,4 @@ compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
libc_hidden_ver (__fnmatch, fnmatch) libc_hidden_ver (__fnmatch, fnmatch)
# endif # endif
#endif /* _LIBC or not __GNU_LIBRARY__. */ #endif /* _LIBC or not __GNU_LIBRARY__. */

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* getdelim.c --- Implementation of replacement getdelim function. /* getdelim.c --- Implementation of replacement getdelim function.
Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006, 2007, Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006, 2007, 2008,
2008, 2009 Free Software Foundation, Inc. 2009, 2010 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU General Public License as
@ -21,13 +21,16 @@
#include <config.h> #include <config.h>
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below. */
#define _GL_ARG_NONNULL(params)
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <unistd.h>
#ifndef SSIZE_MAX #ifndef SSIZE_MAX
# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
@ -35,15 +38,15 @@
#if USE_UNLOCKED_IO #if USE_UNLOCKED_IO
# include "unlocked-io.h" # include "unlocked-io.h"
# define getc_maybe_unlocked(fp) getc(fp) # define getc_maybe_unlocked(fp) getc(fp)
#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED #elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED
# undef flockfile # undef flockfile
# undef funlockfile # undef funlockfile
# define flockfile(x) ((void) 0) # define flockfile(x) ((void) 0)
# define funlockfile(x) ((void) 0) # define funlockfile(x) ((void) 0)
# define getc_maybe_unlocked(fp) getc(fp) # define getc_maybe_unlocked(fp) getc(fp)
#else #else
# define getc_maybe_unlocked(fp) getc_unlocked(fp) # define getc_maybe_unlocked(fp) getc_unlocked(fp)
#endif #endif
/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and /* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
@ -72,10 +75,10 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
*n = 120; *n = 120;
new_lineptr = (char *) realloc (*lineptr, *n); new_lineptr = (char *) realloc (*lineptr, *n);
if (new_lineptr == NULL) if (new_lineptr == NULL)
{ {
result = -1; result = -1;
goto unlock_return; goto unlock_return;
} }
*lineptr = new_lineptr; *lineptr = new_lineptr;
} }
@ -85,44 +88,44 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
i = getc_maybe_unlocked (fp); i = getc_maybe_unlocked (fp);
if (i == EOF) if (i == EOF)
{ {
result = -1; result = -1;
break; break;
} }
/* Make enough space for len+1 (for final NUL) bytes. */ /* Make enough space for len+1 (for final NUL) bytes. */
if (cur_len + 1 >= *n) if (cur_len + 1 >= *n)
{ {
size_t needed_max = size_t needed_max =
SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
size_t needed = 2 * *n + 1; /* Be generous. */ size_t needed = 2 * *n + 1; /* Be generous. */
char *new_lineptr; char *new_lineptr;
if (needed_max < needed) if (needed_max < needed)
needed = needed_max; needed = needed_max;
if (cur_len + 1 >= needed) if (cur_len + 1 >= needed)
{ {
result = -1; result = -1;
errno = EOVERFLOW; errno = EOVERFLOW;
goto unlock_return; goto unlock_return;
} }
new_lineptr = (char *) realloc (*lineptr, needed); new_lineptr = (char *) realloc (*lineptr, needed);
if (new_lineptr == NULL) if (new_lineptr == NULL)
{ {
result = -1; result = -1;
goto unlock_return; goto unlock_return;
} }
*lineptr = new_lineptr; *lineptr = new_lineptr;
*n = needed; *n = needed;
} }
(*lineptr)[cur_len] = i; (*lineptr)[cur_len] = i;
cur_len++; cur_len++;
if (i == delimiter) if (i == delimiter)
break; break;
} }
(*lineptr)[cur_len] = '\0'; (*lineptr)[cur_len] = '\0';
result = cur_len ? cur_len : result; result = cur_len ? cur_len : result;

View file

@ -1,5 +1,5 @@
/* getline.c --- Implementation of replacement getline function. /* getline.c --- Implementation of replacement getline function.
Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU General Public License as

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* getopt_long and getopt_long_only entry points for GNU getopt. /* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006 Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997,
Free Software Foundation, Inc. 1998, 2004, 2006, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -32,25 +32,25 @@
#include <stdlib.h> #include <stdlib.h>
#endif #endif
#ifndef NULL #ifndef NULL
#define NULL 0 #define NULL 0
#endif #endif
int int
getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
const struct option *long_options, int *opt_index) const struct option *long_options, int *opt_index)
{ {
return _getopt_internal (argc, (char **) argv, options, long_options, return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 0, 0); opt_index, 0, 0);
} }
int int
_getopt_long_r (int argc, char **argv, const char *options, _getopt_long_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index, const struct option *long_options, int *opt_index,
struct _getopt_data *d) struct _getopt_data *d)
{ {
return _getopt_internal_r (argc, argv, options, long_options, opt_index, return _getopt_internal_r (argc, argv, options, long_options, opt_index,
0, 0, d); 0, d, 0);
} }
/* Like getopt_long, but '-' as well as '--' can indicate a long option. /* Like getopt_long, but '-' as well as '--' can indicate a long option.
@ -60,20 +60,20 @@ _getopt_long_r (int argc, char **argv, const char *options,
int int
getopt_long_only (int argc, char *__getopt_argv_const *argv, getopt_long_only (int argc, char *__getopt_argv_const *argv,
const char *options, const char *options,
const struct option *long_options, int *opt_index) const struct option *long_options, int *opt_index)
{ {
return _getopt_internal (argc, (char **) argv, options, long_options, return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 1, 0); opt_index, 1, 0);
} }
int int
_getopt_long_only_r (int argc, char **argv, const char *options, _getopt_long_only_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index, const struct option *long_options, int *opt_index,
struct _getopt_data *d) struct _getopt_data *d)
{ {
return _getopt_internal_r (argc, argv, options, long_options, opt_index, return _getopt_internal_r (argc, argv, options, long_options, opt_index,
1, 0, d); 1, d, 0);
} }
@ -91,76 +91,76 @@ main (int argc, char **argv)
{ {
int this_option_optind = optind ? optind : 1; int this_option_optind = optind ? optind : 1;
int option_index = 0; int option_index = 0;
static struct option long_options[] = static const struct option long_options[] =
{ {
{"add", 1, 0, 0}, {"add", 1, 0, 0},
{"append", 0, 0, 0}, {"append", 0, 0, 0},
{"delete", 1, 0, 0}, {"delete", 1, 0, 0},
{"verbose", 0, 0, 0}, {"verbose", 0, 0, 0},
{"create", 0, 0, 0}, {"create", 0, 0, 0},
{"file", 1, 0, 0}, {"file", 1, 0, 0},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long (argc, argv, "abc:d:0123456789", c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index); long_options, &option_index);
if (c == -1) if (c == -1)
break; break;
switch (c) switch (c)
{ {
case 0: case 0:
printf ("option %s", long_options[option_index].name); printf ("option %s", long_options[option_index].name);
if (optarg) if (optarg)
printf (" with arg %s", optarg); printf (" with arg %s", optarg);
printf ("\n"); printf ("\n");
break; break;
case '0': case '0':
case '1': case '1':
case '2': case '2':
case '3': case '3':
case '4': case '4':
case '5': case '5':
case '6': case '6':
case '7': case '7':
case '8': case '8':
case '9': case '9':
if (digit_optind != 0 && digit_optind != this_option_optind) if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n"); printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind; digit_optind = this_option_optind;
printf ("option %c\n", c); printf ("option %c\n", c);
break; break;
case 'a': case 'a':
printf ("option a\n"); printf ("option a\n");
break; break;
case 'b': case 'b':
printf ("option b\n"); printf ("option b\n");
break; break;
case 'c': case 'c':
printf ("option c with value `%s'\n", optarg); printf ("option c with value `%s'\n", optarg);
break; break;
case 'd': case 'd':
printf ("option d with value `%s'\n", optarg); printf ("option d with value `%s'\n", optarg);
break; break;
case '?': case '?':
break; break;
default: default:
printf ("?? getopt returned character code 0%o ??\n", c); printf ("?? getopt returned character code 0%o ??\n", c);
} }
} }
if (optind < argc) if (optind < argc)
{ {
printf ("non-option ARGV-elements: "); printf ("non-option ARGV-elements: ");
while (optind < argc) while (optind < argc)
printf ("%s ", argv[optind++]); printf ("%s ", argv[optind++]);
printf ("\n"); printf ("\n");
} }

View file

@ -1,6 +1,6 @@
/* Internal declarations for getopt. /* Internal declarations for getopt.
Copyright (C) 1989-1994,1996-1999,2001,2003,2004 Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2004, 2009-2010 Free Software
Free Software Foundation, Inc. Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -17,12 +17,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef _GETOPT_INT_H #ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1 #define _GETOPT_INT_H 1
#include <getopt.h>
extern int _getopt_internal (int ___argc, char **___argv, extern int _getopt_internal (int ___argc, char **___argv,
const char *__shortopts, const char *__shortopts,
const struct option *__longopts, int *__longind, const struct option *__longopts, int *__longind,
int __long_only, int __posixly_correct); int __long_only, int __posixly_correct);
/* Reentrant versions which can handle parsing multiple argument /* Reentrant versions which can handle parsing multiple argument
@ -108,23 +110,23 @@ struct _getopt_data
/* The initializer is necessary to set OPTIND and OPTERR to their /* The initializer is necessary to set OPTIND and OPTERR to their
default values and to clear the initialization flag. */ default values and to clear the initialization flag. */
#define _GETOPT_DATA_INITIALIZER { 1, 1 } #define _GETOPT_DATA_INITIALIZER { 1, 1 }
extern int _getopt_internal_r (int ___argc, char **___argv, extern int _getopt_internal_r (int ___argc, char **___argv,
const char *__shortopts, const char *__shortopts,
const struct option *__longopts, int *__longind, const struct option *__longopts, int *__longind,
int __long_only, int __posixly_correct, int __long_only, struct _getopt_data *__data,
struct _getopt_data *__data); int __posixly_correct);
extern int _getopt_long_r (int ___argc, char **___argv, extern int _getopt_long_r (int ___argc, char **___argv,
const char *__shortopts, const char *__shortopts,
const struct option *__longopts, int *__longind, const struct option *__longopts, int *__longind,
struct _getopt_data *__data); struct _getopt_data *__data);
extern int _getopt_long_only_r (int ___argc, char **___argv, extern int _getopt_long_only_r (int ___argc, char **___argv,
const char *__shortopts, const char *__shortopts,
const struct option *__longopts, const struct option *__longopts,
int *__longind, int *__longind,
struct _getopt_data *__data); struct _getopt_data *__data);
#endif /* getopt_int.h */ #endif /* getopt_int.h */

View file

@ -1,5 +1,6 @@
/* Convenience header for conditional use of GNU <libintl.h>. /* Convenience header for conditional use of GNU <libintl.h>.
Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc. Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2010 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -63,21 +64,30 @@
for invalid uses of the value returned from these functions. for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */ contain "#define const". */
# undef gettext
# define gettext(Msgid) ((const char *) (Msgid)) # define gettext(Msgid) ((const char *) (Msgid))
# undef dgettext
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
# undef dcgettext
# define dcgettext(Domainname, Msgid, Category) \ # define dcgettext(Domainname, Msgid, Category) \
((void) (Category), dgettext (Domainname, Msgid)) ((void) (Category), dgettext (Domainname, Msgid))
# undef ngettext
# define ngettext(Msgid1, Msgid2, N) \ # define ngettext(Msgid1, Msgid2, N) \
((N) == 1 \ ((N) == 1 \
? ((void) (Msgid2), (const char *) (Msgid1)) \ ? ((void) (Msgid2), (const char *) (Msgid1)) \
: ((void) (Msgid1), (const char *) (Msgid2))) : ((void) (Msgid1), (const char *) (Msgid2)))
# undef dngettext
# define dngettext(Domainname, Msgid1, Msgid2, N) \ # define dngettext(Domainname, Msgid1, Msgid2, N) \
((void) (Domainname), ngettext (Msgid1, Msgid2, N)) ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
# undef dcngettext
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N)) ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
# undef textdomain
# define textdomain(Domainname) ((const char *) (Domainname)) # define textdomain(Domainname) ((const char *) (Domainname))
# undef bindtextdomain
# define bindtextdomain(Domainname, Dirname) \ # define bindtextdomain(Domainname, Dirname) \
((void) (Domainname), (const char *) (Dirname)) ((void) (Domainname), (const char *) (Dirname))
# undef bind_textdomain_codeset
# define bind_textdomain_codeset(Domainname, Codeset) \ # define bind_textdomain_codeset(Domainname, Codeset) \
((void) (Domainname), (const char *) (Codeset)) ((void) (Domainname), (const char *) (Codeset))
@ -131,8 +141,8 @@ inline
#endif #endif
static const char * static const char *
pgettext_aux (const char *domain, pgettext_aux (const char *domain,
const char *msg_ctxt_id, const char *msgid, const char *msg_ctxt_id, const char *msgid,
int category) int category)
{ {
const char *translation = dcgettext (domain, msg_ctxt_id, category); const char *translation = dcgettext (domain, msg_ctxt_id, category);
if (translation == msg_ctxt_id) if (translation == msg_ctxt_id)
@ -150,9 +160,9 @@ inline
#endif #endif
static const char * static const char *
npgettext_aux (const char *domain, npgettext_aux (const char *domain,
const char *msg_ctxt_id, const char *msgid, const char *msg_ctxt_id, const char *msgid,
const char *msgid_plural, unsigned long int n, const char *msgid_plural, unsigned long int n,
int category) int category)
{ {
const char *translation = const char *translation =
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
@ -190,8 +200,8 @@ inline
#endif #endif
static const char * static const char *
dcpgettext_expr (const char *domain, dcpgettext_expr (const char *domain,
const char *msgctxt, const char *msgid, const char *msgctxt, const char *msgid,
int category) int category)
{ {
size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1; size_t msgid_len = strlen (msgid) + 1;
@ -213,10 +223,10 @@ dcpgettext_expr (const char *domain,
translation = dcgettext (domain, msg_ctxt_id, category); translation = dcgettext (domain, msg_ctxt_id, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf) if (msg_ctxt_id != buf)
free (msg_ctxt_id); free (msg_ctxt_id);
#endif #endif
if (translation != msg_ctxt_id) if (translation != msg_ctxt_id)
return translation; return translation;
} }
return msgid; return msgid;
} }
@ -235,9 +245,9 @@ inline
#endif #endif
static const char * static const char *
dcnpgettext_expr (const char *domain, dcnpgettext_expr (const char *domain,
const char *msgctxt, const char *msgid, const char *msgctxt, const char *msgid,
const char *msgid_plural, unsigned long int n, const char *msgid_plural, unsigned long int n,
int category) int category)
{ {
size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1; size_t msgid_len = strlen (msgid) + 1;
@ -259,10 +269,10 @@ dcnpgettext_expr (const char *domain,
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf) if (msg_ctxt_id != buf)
free (msg_ctxt_id); free (msg_ctxt_id);
#endif #endif
if (!(translation == msg_ctxt_id || translation == msgid_plural)) if (!(translation == msg_ctxt_id || translation == msgid_plural))
return translation; return translation;
} }
return (n == 1 ? msgid : msgid_plural); return (n == 1 ? msgid : msgid_plural);
} }

View file

@ -1,6 +1,6 @@
/* Program name management. /* Program name management.
Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc. Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001. Written by Bruno Haible <bruno@clisp.org>, 2001.
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -23,6 +23,8 @@
#include "progname.h" #include "progname.h"
#include <errno.h> /* get program_invocation_name declaration */ #include <errno.h> /* get program_invocation_name declaration */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
@ -30,7 +32,9 @@
To be initialized by main(). */ To be initialized by main(). */
const char *program_name = NULL; const char *program_name = NULL;
/* Set program_name, based on argv[0]. */ /* Set program_name, based on argv[0].
argv0 must be a string allocated with indefinite extent, and must not be
modified after this call. */
void void
set_program_name (const char *argv0) set_program_name (const char *argv0)
{ {
@ -42,20 +46,30 @@ set_program_name (const char *argv0)
const char *slash; const char *slash;
const char *base; const char *base;
/* Sanity check. POSIX requires the invoking process to pass a non-NULL
argv[0]. */
if (argv0 == NULL)
{
/* It's a bug in the invoking program. Help diagnosing it. */
fputs ("A NULL argv[0] was passed through an exec system call.\n",
stderr);
abort ();
}
slash = strrchr (argv0, '/'); slash = strrchr (argv0, '/');
base = (slash != NULL ? slash + 1 : argv0); base = (slash != NULL ? slash + 1 : argv0);
if (base - argv0 >= 7 && strncmp (base - 7, "/.libs/", 7) == 0) if (base - argv0 >= 7 && strncmp (base - 7, "/.libs/", 7) == 0)
{ {
argv0 = base; argv0 = base;
if (strncmp (base, "lt-", 3) == 0) if (strncmp (base, "lt-", 3) == 0)
{ {
argv0 = base + 3; argv0 = base + 3;
/* On glibc systems, remove the "lt-" prefix from the variable /* On glibc systems, remove the "lt-" prefix from the variable
program_invocation_short_name. */ program_invocation_short_name. */
#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME #if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
program_invocation_short_name = (char *) argv0; program_invocation_short_name = (char *) argv0;
#endif #endif
} }
} }
/* But don't strip off a leading <dirname>/ in general, because when the user /* But don't strip off a leading <dirname>/ in general, because when the user

View file

@ -1,6 +1,6 @@
/* Program name management. /* Program name management.
Copyright (C) 2001-2004, 2006 Free Software Foundation, Inc. Copyright (C) 2001-2004, 2006, 2009-2010 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001. Written by Bruno Haible <bruno@clisp.org>, 2001.
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -31,7 +31,9 @@ extern "C" {
/* String containing name the program is called with. */ /* String containing name the program is called with. */
extern const char *program_name; extern const char *program_name;
/* Set program_name, based on argv[0]. */ /* Set program_name, based on argv[0].
argv0 must be a string allocated with indefinite extent, and must not be
modified after this call. */
extern void set_program_name (const char *argv0); extern void set_program_name (const char *argv0);
#if ENABLE_RELOCATABLE #if ENABLE_RELOCATABLE
@ -39,8 +41,8 @@ extern void set_program_name (const char *argv0);
/* Set program_name, based on argv[0], and original installation prefix and /* Set program_name, based on argv[0], and original installation prefix and
directory, for relocatability. */ directory, for relocatability. */
extern void set_program_name_and_installdir (const char *argv0, extern void set_program_name_and_installdir (const char *argv0,
const char *orig_installprefix, const char *orig_installprefix,
const char *orig_installdir); const char *orig_installdir);
#undef set_program_name #undef set_program_name
#define set_program_name(ARG0) \ #define set_program_name(ARG0) \
set_program_name_and_installdir (ARG0, INSTALLPREFIX, INSTALLDIR) set_program_name_and_installdir (ARG0, INSTALLPREFIX, INSTALLDIR)

89
include/grub/bsdlabel.h Normal file
View file

@ -0,0 +1,89 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2004,2007 Free Software Foundation, Inc.
*
* GRUB 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 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_BSDLABEL_PARTITION_HEADER
#define GRUB_BSDLABEL_PARTITION_HEADER 1
/* Constants for BSD disk label. */
#define GRUB_PC_PARTITION_BSD_LABEL_SECTOR 1
#define GRUB_PC_PARTITION_BSD_LABEL_MAGIC 0x82564557
/* BSD partition types. */
#define GRUB_PC_PARTITION_BSD_TYPE_UNUSED 0
#define GRUB_PC_PARTITION_BSD_TYPE_SWAP 1
#define GRUB_PC_PARTITION_BSD_TYPE_V6 2
#define GRUB_PC_PARTITION_BSD_TYPE_V7 3
#define GRUB_PC_PARTITION_BSD_TYPE_SYSV 4
#define GRUB_PC_PARTITION_BSD_TYPE_V71K 5
#define GRUB_PC_PARTITION_BSD_TYPE_V8 6
#define GRUB_PC_PARTITION_BSD_TYPE_BSDFFS 7
#define GRUB_PC_PARTITION_BSD_TYPE_MSDOS 8
#define GRUB_PC_PARTITION_BSD_TYPE_BSDLFS 9
#define GRUB_PC_PARTITION_BSD_TYPE_OTHER 10
#define GRUB_PC_PARTITION_BSD_TYPE_HPFS 11
#define GRUB_PC_PARTITION_BSD_TYPE_ISO9660 12
#define GRUB_PC_PARTITION_BSD_TYPE_BOOT 13
/* FreeBSD-specific types. */
#define GRUB_PC_PARTITION_FREEBSD_TYPE_VINUM 14
#define GRUB_PC_PARTITION_FREEBSD_TYPE_RAID 15
#define GRUB_PC_PARTITION_FREEBSD_TYPE_JFS2 21
/* NetBSD-specific types. */
#define GRUB_PC_PARTITION_NETBSD_TYPE_ADOS 14
#define GRUB_PC_PARTITION_NETBSD_TYPE_HFS 15
#define GRUB_PC_PARTITION_NETBSD_TYPE_FILECORE 16
#define GRUB_PC_PARTITION_NETBSD_TYPE_EXT2FS 17
#define GRUB_PC_PARTITION_NETBSD_TYPE_NTFS 18
#define GRUB_PC_PARTITION_NETBSD_TYPE_RAID 19
#define GRUB_PC_PARTITION_NETBSD_TYPE_CCD 20
#define GRUB_PC_PARTITION_NETBSD_TYPE_JFS2 21
#define GRUB_PC_PARTITION_NETBSD_TYPE_APPLEUFS 22
/* OpenBSD-specific types. */
#define GRUB_PC_PARTITION_OPENBSD_TYPE_ADOS 14
#define GRUB_PC_PARTITION_OPENBSD_TYPE_HFS 15
#define GRUB_PC_PARTITION_OPENBSD_TYPE_FILECORE 16
#define GRUB_PC_PARTITION_OPENBSD_TYPE_EXT2FS 17
#define GRUB_PC_PARTITION_OPENBSD_TYPE_NTFS 18
#define GRUB_PC_PARTITION_OPENBSD_TYPE_RAID 19
/* The BSD partition entry. */
struct grub_partition_bsd_entry
{
grub_uint32_t size;
grub_uint32_t offset;
grub_uint32_t fragment_size;
grub_uint8_t fs_type;
grub_uint8_t fs_fragments;
grub_uint16_t fs_cylinders;
} __attribute__ ((packed));
/* The BSD disk label. Only define members useful for GRUB. */
struct grub_partition_bsd_disk_label
{
grub_uint32_t magic;
grub_uint8_t padding[128];
grub_uint32_t magic2;
grub_uint16_t checksum;
grub_uint16_t num_partitions;
grub_uint32_t boot_size;
grub_uint32_t superblock_size;
} __attribute__ ((packed));
#endif /* ! GRUB_PC_PARTITION_HEADER */

View file

@ -25,7 +25,7 @@
extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s); extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s);
/* NLS can be disabled through the configure --disable-nls option. */ /* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS #if (defined(ENABLE_NLS) && ENABLE_NLS)
# ifdef GRUB_UTIL # ifdef GRUB_UTIL
@ -34,7 +34,7 @@ extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s);
# endif /* GRUB_UTIL */ # endif /* GRUB_UTIL */
#else /* ! ENABLE_NLS */ #else /* ! (defined(ENABLE_NLS) && ENABLE_NLS) */
/* Disabled NLS. /* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings The casts to 'const char *' serve the purpose of producing warnings
@ -47,7 +47,7 @@ extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s);
# define grub_gettext(str) ((const char *) (str)) # define grub_gettext(str) ((const char *) (str))
# endif /* GRUB_UTIL */ # endif /* GRUB_UTIL */
#endif /* ENABLE_NLS */ #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
# define _(str) gettext(str) # define _(str) gettext(str)

View file

@ -19,14 +19,6 @@
#ifndef GRUB_MULTIBOOT_CPU_HEADER #ifndef GRUB_MULTIBOOT_CPU_HEADER
#define GRUB_MULTIBOOT_CPU_HEADER 1 #define GRUB_MULTIBOOT_CPU_HEADER 1
/* The asm part of the multiboot loader. */
void grub_multiboot_real_boot (grub_addr_t entry,
struct multiboot_info *mbi)
__attribute__ ((noreturn));
void grub_multiboot2_real_boot (grub_addr_t entry,
struct multiboot_info *mbi)
__attribute__ ((noreturn));
extern grub_uint32_t grub_multiboot_payload_eip; extern grub_uint32_t grub_multiboot_payload_eip;
extern char *grub_multiboot_payload_orig; extern char *grub_multiboot_payload_orig;
extern grub_addr_t grub_multiboot_payload_dest; extern grub_addr_t grub_multiboot_payload_dest;

View file

@ -52,7 +52,7 @@ grub_bad_type_cast_real (int line, const char *file)
return 0; return 0;
} }
#define grub_bad_type_cast() grub_bad_type_cast_real(__LINE__, __FILE__) #define grub_bad_type_cast() grub_bad_type_cast_real(__LINE__, GRUB_FILE)
#define GRUB_FIELD_MATCH(ptr, type, field) \ #define GRUB_FIELD_MATCH(ptr, type, field) \
((char *) &(ptr)->field == (char *) &((type) (ptr))->field) ((char *) &(ptr)->field == (char *) &((type) (ptr))->field)

View file

@ -46,7 +46,7 @@
#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
#define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; }
#define grub_dprintf(condition, fmt, args...) grub_real_dprintf(__FILE__, __LINE__, condition, fmt, ## args) #define grub_dprintf(condition, fmt, args...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, fmt, ## args)
/* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */ /* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */
#define grub_memcpy(d,s,n) grub_memmove ((d), (s), (n)) #define grub_memcpy(d,s,n) grub_memmove ((d), (s), (n))

View file

@ -44,19 +44,19 @@ void grub_mm_dump_free (void);
void grub_mm_dump (unsigned lineno); void grub_mm_dump (unsigned lineno);
#define grub_malloc(size) \ #define grub_malloc(size) \
grub_debug_malloc (__FILE__, __LINE__, size) grub_debug_malloc (GRUB_FILE, __LINE__, size)
#define grub_zalloc(size) \ #define grub_zalloc(size) \
grub_debug_zalloc (__FILE__, __LINE__, size) grub_debug_zalloc (GRUB_FILE, __LINE__, size)
#define grub_realloc(ptr,size) \ #define grub_realloc(ptr,size) \
grub_debug_realloc (__FILE__, __LINE__, ptr, size) grub_debug_realloc (GRUB_FILE, __LINE__, ptr, size)
#define grub_memalign(align,size) \ #define grub_memalign(align,size) \
grub_debug_memalign (__FILE__, __LINE__, align, size) grub_debug_memalign (GRUB_FILE, __LINE__, align, size)
#define grub_free(ptr) \ #define grub_free(ptr) \
grub_debug_free (__FILE__, __LINE__, ptr) grub_debug_free (GRUB_FILE, __LINE__, ptr)
void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line, void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line,
grub_size_t size); grub_size_t size);

View file

@ -53,75 +53,6 @@
#define GRUB_PC_PARTITION_TYPE_GPT_DISK 0xee #define GRUB_PC_PARTITION_TYPE_GPT_DISK 0xee
#define GRUB_PC_PARTITION_TYPE_LINUX_RAID 0xfd #define GRUB_PC_PARTITION_TYPE_LINUX_RAID 0xfd
/* Constants for BSD disk label. */
#define GRUB_PC_PARTITION_BSD_LABEL_SECTOR 1
#define GRUB_PC_PARTITION_BSD_LABEL_MAGIC 0x82564557
#define GRUB_PC_PARTITION_BSD_MAX_ENTRIES 8
/* BSD partition types. */
#define GRUB_PC_PARTITION_BSD_TYPE_UNUSED 0
#define GRUB_PC_PARTITION_BSD_TYPE_SWAP 1
#define GRUB_PC_PARTITION_BSD_TYPE_V6 2
#define GRUB_PC_PARTITION_BSD_TYPE_V7 3
#define GRUB_PC_PARTITION_BSD_TYPE_SYSV 4
#define GRUB_PC_PARTITION_BSD_TYPE_V71K 5
#define GRUB_PC_PARTITION_BSD_TYPE_V8 6
#define GRUB_PC_PARTITION_BSD_TYPE_BSDFFS 7
#define GRUB_PC_PARTITION_BSD_TYPE_MSDOS 8
#define GRUB_PC_PARTITION_BSD_TYPE_BSDLFS 9
#define GRUB_PC_PARTITION_BSD_TYPE_OTHER 10
#define GRUB_PC_PARTITION_BSD_TYPE_HPFS 11
#define GRUB_PC_PARTITION_BSD_TYPE_ISO9660 12
#define GRUB_PC_PARTITION_BSD_TYPE_BOOT 13
/* FreeBSD-specific types. */
#define GRUB_PC_PARTITION_FREEBSD_TYPE_VINUM 14
#define GRUB_PC_PARTITION_FREEBSD_TYPE_RAID 15
#define GRUB_PC_PARTITION_FREEBSD_TYPE_JFS2 21
/* NetBSD-specific types. */
#define GRUB_PC_PARTITION_NETBSD_TYPE_ADOS 14
#define GRUB_PC_PARTITION_NETBSD_TYPE_HFS 15
#define GRUB_PC_PARTITION_NETBSD_TYPE_FILECORE 16
#define GRUB_PC_PARTITION_NETBSD_TYPE_EXT2FS 17
#define GRUB_PC_PARTITION_NETBSD_TYPE_NTFS 18
#define GRUB_PC_PARTITION_NETBSD_TYPE_RAID 19
#define GRUB_PC_PARTITION_NETBSD_TYPE_CCD 20
#define GRUB_PC_PARTITION_NETBSD_TYPE_JFS2 21
#define GRUB_PC_PARTITION_NETBSD_TYPE_APPLEUFS 22
/* OpenBSD-specific types. */
#define GRUB_PC_PARTITION_OPENBSD_TYPE_ADOS 14
#define GRUB_PC_PARTITION_OPENBSD_TYPE_HFS 15
#define GRUB_PC_PARTITION_OPENBSD_TYPE_FILECORE 16
#define GRUB_PC_PARTITION_OPENBSD_TYPE_EXT2FS 17
#define GRUB_PC_PARTITION_OPENBSD_TYPE_NTFS 18
#define GRUB_PC_PARTITION_OPENBSD_TYPE_RAID 19
/* The BSD partition entry. */
struct grub_msdos_partition_bsd_entry
{
grub_uint32_t size;
grub_uint32_t offset;
grub_uint32_t fragment_size;
grub_uint8_t fs_type;
grub_uint8_t fs_fragments;
grub_uint16_t fs_cylinders;
} __attribute__ ((packed));
/* The BSD disk label. Only define members useful for GRUB. */
struct grub_msdos_partition_disk_label
{
grub_uint32_t magic;
grub_uint8_t padding[128];
grub_uint32_t magic2;
grub_uint16_t checksum;
grub_uint16_t num_partitions;
grub_uint32_t boot_size;
grub_uint32_t superblock_size;
struct grub_msdos_partition_bsd_entry entries[GRUB_PC_PARTITION_BSD_MAX_ENTRIES];
} __attribute__ ((packed));
/* The partition entry. */ /* The partition entry. */
struct grub_msdos_partition_entry struct grub_msdos_partition_entry
{ {
@ -168,23 +99,6 @@ struct grub_msdos_partition_mbr
} __attribute__ ((packed)); } __attribute__ ((packed));
struct grub_msdos_partition
{
/* The DOS partition number. */
int dos_part;
/* The BSD partition number (a == 0). */
int bsd_part;
/* The DOS partition type. */
int dos_type;
/* The BSD partition type. */
int bsd_type;
/* The offset of the extended partition. */
unsigned long ext_offset;
};
static inline int static inline int
grub_msdos_partition_is_empty (int type) grub_msdos_partition_is_empty (int type)
@ -200,12 +114,4 @@ grub_msdos_partition_is_extended (int type)
|| type == GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED); || type == GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED);
} }
static inline int
grub_msdos_partition_is_bsd (int type)
{
return (type == GRUB_PC_PARTITION_TYPE_FREEBSD
|| type == GRUB_PC_PARTITION_TYPE_OPENBSD
|| type == GRUB_PC_PARTITION_TYPE_NETBSD);
}
#endif /* ! GRUB_PC_PARTITION_HEADER */ #endif /* ! GRUB_PC_PARTITION_HEADER */

View file

@ -20,6 +20,8 @@
#ifndef GRUB_MULTIBOOT_HEADER #ifndef GRUB_MULTIBOOT_HEADER
#define GRUB_MULTIBOOT_HEADER 1 #define GRUB_MULTIBOOT_HEADER 1
#include <grub/file.h>
#ifdef GRUB_USE_MULTIBOOT2 #ifdef GRUB_USE_MULTIBOOT2
#include <multiboot2.h> #include <multiboot2.h>
/* Same thing as far as our loader is concerned. */ /* Same thing as far as our loader is concerned. */
@ -35,8 +37,6 @@
void grub_multiboot (int argc, char *argv[]); void grub_multiboot (int argc, char *argv[]);
void grub_module (int argc, char *argv[]); void grub_module (int argc, char *argv[]);
void grub_multiboot_set_accepts_video (int val);
grub_size_t grub_multiboot_get_mbi_size (void); grub_size_t grub_multiboot_get_mbi_size (void);
grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest,
grub_off_t buf_off, grub_size_t bufsize); grub_off_t buf_off, grub_size_t bufsize);
@ -46,5 +46,29 @@ grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
int argc, char *argv[]); int argc, char *argv[]);
void grub_multiboot_set_bootdev (void); void grub_multiboot_set_bootdev (void);
grub_uint32_t grub_get_multiboot_mmap_count (void);
grub_err_t grub_multiboot_set_video_mode (void);
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
#include <grub/i386/pc/vbe.h>
#define GRUB_MACHINE_HAS_VGA_TEXT 1
#else
#define GRUB_MACHINE_HAS_VGA_TEXT 0
#endif
#define GRUB_MULTIBOOT_CONSOLE_EGA_TEXT 1
#define GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER 2
grub_err_t
grub_multiboot_set_console (int console_type, int accepted_consoles,
int width, int height, int depth,
int console_required);
grub_err_t
grub_multiboot_load (grub_file_t file);
/* Load ELF32 or ELF64. */
grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer);
extern grub_size_t grub_multiboot_pure_size;
extern grub_size_t grub_multiboot_alloc_mbi;
#endif /* ! GRUB_MULTIBOOT_HEADER */ #endif /* ! GRUB_MULTIBOOT_HEADER */

View file

@ -20,6 +20,7 @@
#define GRUB_PART_HEADER 1 #define GRUB_PART_HEADER 1
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/list.h>
struct grub_disk; struct grub_disk;
@ -28,6 +29,9 @@ typedef struct grub_partition *grub_partition_t;
/* Partition map type. */ /* Partition map type. */
struct grub_partition_map struct grub_partition_map
{ {
/* The next partition map type. */
struct grub_partition_map *next;
/* The name of the partition map type. */ /* The name of the partition map type. */
const char *name; const char *name;
@ -35,22 +39,15 @@ struct grub_partition_map
grub_err_t (*iterate) (struct grub_disk *disk, grub_err_t (*iterate) (struct grub_disk *disk,
int (*hook) (struct grub_disk *disk, int (*hook) (struct grub_disk *disk,
const grub_partition_t partition)); const grub_partition_t partition));
/* Return the partition named STR on the disk DISK. */
grub_partition_t (*probe) (struct grub_disk *disk,
const char *str);
/* Return the name of the partition PARTITION. */
char *(*get_name) (const grub_partition_t partition);
/* The next partition map type. */
struct grub_partition_map *next;
}; };
typedef struct grub_partition_map *grub_partition_map_t; typedef struct grub_partition_map *grub_partition_map_t;
/* Partition description. */ /* Partition description. */
struct grub_partition struct grub_partition
{ {
/* The partition number. */
int number;
/* The start sector. */ /* The start sector. */
grub_disk_addr_t start; grub_disk_addr_t start;
@ -63,8 +60,8 @@ struct grub_partition
/* The index of this partition in the partition table. */ /* The index of this partition in the partition table. */
int index; int index;
/* Partition map type specific data. */ /* Parent partition map. */
void *data; struct grub_partition *parent;
/* The type partition map. */ /* The type partition map. */
grub_partition_map_t partmap; grub_partition_map_t partmap;
@ -77,17 +74,36 @@ int EXPORT_FUNC(grub_partition_iterate) (struct grub_disk *disk,
const grub_partition_t partition)); const grub_partition_t partition));
char *EXPORT_FUNC(grub_partition_get_name) (const grub_partition_t partition); char *EXPORT_FUNC(grub_partition_get_name) (const grub_partition_t partition);
int EXPORT_FUNC(grub_partition_map_iterate) (int (*hook) (const grub_partition_map_t partmap));
void EXPORT_FUNC(grub_partition_map_register) (grub_partition_map_t partmap); extern grub_partition_map_t EXPORT_VAR(grub_partition_map_list);
void EXPORT_FUNC(grub_partition_map_unregister) (grub_partition_map_t partmap); static inline void
grub_partition_map_register (grub_partition_map_t partmap)
{
grub_list_push (GRUB_AS_LIST_P (&grub_partition_map_list),
GRUB_AS_LIST (partmap));
}
static inline void
grub_partition_map_unregister (grub_partition_map_t partmap)
{
grub_list_remove (GRUB_AS_LIST_P (&grub_partition_map_list),
GRUB_AS_LIST (partmap));
}
#define FOR_PARTITION_MAPS(var) for (var = grub_partition_map_list; var; var = var->next)
static inline grub_disk_addr_t static inline grub_disk_addr_t
grub_partition_get_start (const grub_partition_t p) grub_partition_get_start (const grub_partition_t p)
{ {
return p->start; grub_partition_t part;
grub_uint64_t part_start = 0;
for (part = p; part; part = part->parent)
part_start += part->start;
return part_start;
} }
static inline grub_uint64_t static inline grub_uint64_t

View file

@ -106,6 +106,21 @@ struct grub_script_cmdif
struct grub_script_cmd *exec_on_false; struct grub_script_cmd *exec_on_false;
}; };
/* A for statement. */
struct grub_script_cmdfor
{
struct grub_script_cmd cmd;
/* The name used as looping variable. */
struct grub_script_arg *name;
/* The words loop iterates over. */
struct grub_script_arglist *words;
/* The command list executed in each loop. */
struct grub_script_cmd *list;
};
/* A menu entry generate statement. */ /* A menu entry generate statement. */
struct grub_script_cmd_menuentry struct grub_script_cmd_menuentry
{ {
@ -213,6 +228,12 @@ grub_script_create_cmdif (struct grub_parser_param *state,
struct grub_script_cmd *exec_on_true, struct grub_script_cmd *exec_on_true,
struct grub_script_cmd *exec_on_false); struct grub_script_cmd *exec_on_false);
struct grub_script_cmd *
grub_script_create_cmdfor (struct grub_parser_param *state,
struct grub_script_arg *name,
struct grub_script_arglist *words,
struct grub_script_cmd *list);
struct grub_script_cmd * struct grub_script_cmd *
grub_script_create_cmdmenu (struct grub_parser_param *state, grub_script_create_cmdmenu (struct grub_parser_param *state,
struct grub_script_arglist *arglist, struct grub_script_arglist *arglist,
@ -261,6 +282,7 @@ void grub_script_yyerror (struct grub_parser_param *, char const *);
grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_cmdfor (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd);
/* Execute any GRUB pre-parsed command or script. */ /* Execute any GRUB pre-parsed command or script. */

View file

@ -54,7 +54,7 @@ void grub_test_nonzero (int cond, const char *file,
/* Macro to fill in location details and an optional error message. */ /* Macro to fill in location details and an optional error message. */
#define grub_test_assert(cond, ...) \ #define grub_test_assert(cond, ...) \
grub_test_nonzero(cond, __FILE__, __FUNCTION__, __LINE__, \ grub_test_nonzero(cond, GRUB_FILE, __FUNCTION__, __LINE__, \
## __VA_ARGS__, \ ## __VA_ARGS__, \
"assert failed: %s", #cond) "assert failed: %s", #cond)

View file

@ -24,6 +24,7 @@
/* How many bytes from the start of the file we search for the header. */ /* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192 #define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_HEADER_ALIGN 4
/* The magic field should contain this. */ /* The magic field should contain this. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 #define MULTIBOOT_HEADER_MAGIC 0x1BADB002

View file

@ -23,7 +23,8 @@
#define MULTIBOOT_HEADER 1 #define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */ /* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192 #define MULTIBOOT_SEARCH 32768
#define MULTIBOOT_HEADER_ALIGN 8
/* The magic field should contain this. */ /* The magic field should contain this. */
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6 #define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
@ -35,58 +36,36 @@
#define MULTIBOOT_MOD_ALIGN 0x00001000 #define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */ /* Alignment of the multiboot info structure. */
#define MULTIBOOT_INFO_ALIGN 0x00000004 #define MULTIBOOT_INFO_ALIGN 0x00000008
/* Flags set in the 'flags' member of the multiboot header. */ /* Flags set in the 'flags' member of the multiboot header. */
/* Align all boot modules on i386 page (4KB) boundaries. */ #define MULTIBOOT_TAG_ALIGN 8
#define MULTIBOOT_PAGE_ALIGN 0x00000001 #define MULTIBOOT_TAG_TYPE_END 0
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
#define MULTIBOOT_TAG_TYPE_MODULE 3
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
#define MULTIBOOT_TAG_TYPE_MMAP 6
#define MULTIBOOT_TAG_TYPE_VBE 7
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
#define MULTIBOOT_TAG_TYPE_APM 10
/* Must pass memory information to OS. */ #define MULTIBOOT_HEADER_TAG_END 0
#define MULTIBOOT_MEMORY_INFO 0x00000002 #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
/* Must pass video information to OS. */ #define GRUB_MULTIBOOT_ARCHITECTURE_I386 0
#define MULTIBOOT_VIDEO_MODE 0x00000004 #define MULTIBOOT_HEADER_TAG_OPTIONAL 1
/* This flag indicates the use of the address fields in the header. */ #define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
#define MULTIBOOT_AOUT_KLUDGE 0x00010000 #define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
/* Flags to be set in the 'flags' member of the multiboot info structure. */
/* is there basic lower/upper memory information? */
#define MULTIBOOT_INFO_MEMORY 0x00000001
/* is there a boot device set? */
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
/* is the command-line defined? */
#define MULTIBOOT_INFO_CMDLINE 0x00000004
/* are there modules to do something with? */
#define MULTIBOOT_INFO_MODS 0x00000008
/* These next two are mutually exclusive */
/* is there a symbol table loaded? */
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
/* is there an ELF section header table? */
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
/* is there a full memory map? */
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
/* Is there drive info? */
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
/* Is there a config table? */
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
/* Is there a boot loader name? */
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
/* Is there a APM table? */
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
/* Is there video information? */
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
#ifndef ASM_FILE #ifndef ASM_FILE
@ -100,96 +79,175 @@ struct multiboot_header
/* Must be MULTIBOOT_MAGIC - see above. */ /* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic; multiboot_uint32_t magic;
/* Feature flags. */ /* ISA */
multiboot_uint32_t flags; multiboot_uint32_t architecture;
/* Total header length. */
multiboot_uint32_t header_length;
/* The above fields plus this one must equal 0 mod 2^32. */ /* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum; multiboot_uint32_t checksum;
};
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ struct multiboot_header_tag
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
};
struct multiboot_header_tag_information_request
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t requests[0];
};
struct multiboot_header_tag_address
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t header_addr; multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr; multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr; multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr; multiboot_uint32_t bss_end_addr;
multiboot_uint32_t entry_addr; };
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ struct multiboot_header_tag_entry_address
multiboot_uint32_t mode_type; {
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t entry_addr;
};
struct multiboot_header_tag_console_flags
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t console_flags;
};
struct multiboot_header_tag_framebuffer
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t width; multiboot_uint32_t width;
multiboot_uint32_t height; multiboot_uint32_t height;
multiboot_uint32_t depth; multiboot_uint32_t depth;
}; };
/* The symbol table for a.out. */ struct multiboot_header_tag_module_align
struct multiboot_aout_symbol_table
{ {
multiboot_uint32_t tabsize; multiboot_uint16_t type;
multiboot_uint32_t strsize; multiboot_uint16_t flags;
multiboot_uint32_t addr;
multiboot_uint32_t reserved;
};
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
/* The section header table for ELF. */
struct multiboot_elf_section_header_table
{
multiboot_uint32_t num;
multiboot_uint32_t size; multiboot_uint32_t size;
multiboot_uint32_t addr; multiboot_uint32_t width;
multiboot_uint32_t shndx; multiboot_uint32_t height;
multiboot_uint32_t depth;
}; };
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
struct multiboot_info struct multiboot_color
{ {
/* Multiboot info version number */ multiboot_uint8_t red;
multiboot_uint32_t flags; multiboot_uint8_t green;
multiboot_uint8_t blue;
};
/* Available memory from BIOS */ struct multiboot_mmap_entry
{
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
multiboot_uint32_t type;
multiboot_uint32_t zero;
} __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_tag
{
multiboot_uint32_t type;
multiboot_uint32_t size;
};
struct multiboot_tag_string
{
multiboot_uint32_t type;
multiboot_uint32_t size;
char string[0];
};
struct multiboot_tag_module
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
char cmdline[0];
};
struct multiboot_tag_basic_meminfo
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t mem_lower; multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper; multiboot_uint32_t mem_upper;
};
/* "root" partition */ struct multiboot_tag_bootdev
multiboot_uint32_t boot_device; {
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t biosdev;
multiboot_uint32_t slice;
multiboot_uint32_t part;
};
/* Kernel command line */ struct multiboot_tag_mmap
multiboot_uint32_t cmdline; {
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t entry_size;
multiboot_uint32_t entry_version;
struct multiboot_mmap_entry entries[0];
};
/* Boot-Module list */ struct multiboot_vbe_info_block
multiboot_uint32_t mods_count; {
multiboot_uint32_t mods_addr; multiboot_uint8_t external_specification[512];
};
union struct multiboot_vbe_mode_info_block
{ {
multiboot_aout_symbol_table_t aout_sym; multiboot_uint8_t external_specification[256];
multiboot_elf_section_header_table_t elf_sec; };
} u;
/* Memory Mapping buffer */ struct multiboot_tag_vbe
multiboot_uint32_t mmap_length; {
multiboot_uint32_t mmap_addr; multiboot_uint32_t type;
multiboot_uint32_t size;
/* Drive Info buffer */
multiboot_uint32_t drives_length;
multiboot_uint32_t drives_addr;
/* ROM configuration table */
multiboot_uint32_t config_table;
/* Boot Loader Name */
multiboot_uint32_t boot_loader_name;
/* APM table */
multiboot_uint32_t apm_table;
/* Video */
multiboot_uint32_t vbe_control_info;
multiboot_uint32_t vbe_mode_info;
multiboot_uint16_t vbe_mode; multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg; multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off; multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len; multiboot_uint16_t vbe_interface_len;
struct multiboot_vbe_info_block vbe_control_info;
struct multiboot_vbe_mode_info_block vbe_mode_info;
};
struct multiboot_tag_framebuffer_common
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint64_t framebuffer_addr; multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch; multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width; multiboot_uint32_t framebuffer_width;
@ -199,12 +257,19 @@ struct multiboot_info
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 #define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 #define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type; multiboot_uint8_t framebuffer_type;
multiboot_uint16_t reserved;
};
struct multiboot_tag_framebuffer
{
struct multiboot_tag_framebuffer_common common;
union union
{ {
struct struct
{ {
multiboot_uint32_t framebuffer_palette_addr;
multiboot_uint16_t framebuffer_palette_num_colors; multiboot_uint16_t framebuffer_palette_num_colors;
struct multiboot_color framebuffer_palette[0];
}; };
struct struct
{ {
@ -217,41 +282,31 @@ struct multiboot_info
}; };
}; };
}; };
typedef struct multiboot_info multiboot_info_t;
struct multiboot_color struct multiboot_tag_elf_sections
{ {
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
struct multiboot_mmap_entry
{
multiboot_uint32_t size;
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
multiboot_uint32_t type; multiboot_uint32_t type;
} __attribute__((packed)); multiboot_uint32_t size;
typedef struct multiboot_mmap_entry multiboot_memory_map_t; multiboot_uint32_t num;
multiboot_uint32_t entsize;
struct multiboot_mod_list multiboot_uint32_t shndx;
{ char sections[0];
/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ };
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end; struct multiboot_tag_apm
{
/* Module command line */ multiboot_uint32_t type;
multiboot_uint32_t cmdline; multiboot_uint32_t size;
multiboot_uint16_t version;
/* padding to take it to 16 bytes (must be zero) */ multiboot_uint16_t cseg;
multiboot_uint32_t pad; multiboot_uint32_t offset;
multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg;
multiboot_uint16_t flags;
multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len;
}; };
typedef struct multiboot_mod_list multiboot_module_t;
#endif /* ! ASM_FILE */ #endif /* ! ASM_FILE */

View file

@ -330,6 +330,7 @@ grub_disk_open (const char *name)
void void
grub_disk_close (grub_disk_t disk) grub_disk_close (grub_disk_t disk)
{ {
grub_partition_t part;
grub_dprintf ("disk", "Closing `%s'.\n", disk->name); grub_dprintf ("disk", "Closing `%s'.\n", disk->name);
if (disk->dev && disk->dev->close) if (disk->dev && disk->dev->close)
@ -338,7 +339,12 @@ grub_disk_close (grub_disk_t disk)
/* Reset the timer. */ /* Reset the timer. */
grub_last_time = grub_get_time_ms (); grub_last_time = grub_get_time_ms ();
grub_free (disk->partition); while (disk->partition)
{
part = disk->partition->parent;
grub_free (disk->partition);
disk->partition = part;
}
grub_free ((void *) disk->name); grub_free ((void *) disk->name);
grub_free (disk); grub_free (disk);
} }
@ -349,18 +355,19 @@ grub_disk_close (grub_disk_t disk)
- Verify that the range is inside the partition. */ - Verify that the range is inside the partition. */
static grub_err_t static grub_err_t
grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector, grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector,
grub_off_t *offset, grub_size_t size) grub_off_t *offset, grub_size_t size)
{ {
grub_partition_t part;
*sector += *offset >> GRUB_DISK_SECTOR_BITS; *sector += *offset >> GRUB_DISK_SECTOR_BITS;
*offset &= GRUB_DISK_SECTOR_SIZE - 1; *offset &= GRUB_DISK_SECTOR_SIZE - 1;
if (disk->partition) for (part = disk->partition; part; part = part->parent)
{ {
grub_disk_addr_t start; grub_disk_addr_t start;
grub_uint64_t len; grub_uint64_t len;
start = grub_partition_get_start (disk->partition); start = part->start;
len = grub_partition_get_len (disk->partition); len = part->len;
if (*sector >= len if (*sector >= len
|| len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) || len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1)

View file

@ -348,7 +348,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
sym->st_value = (Elf_Addr) grub_dl_resolve_symbol (name); sym->st_value = (Elf_Addr) grub_dl_resolve_symbol (name);
if (! sym->st_value) if (! sym->st_value)
return grub_error (GRUB_ERR_BAD_MODULE, return grub_error (GRUB_ERR_BAD_MODULE,
"the symbol `%s' not found", name); "symbol not found: `%s'", name);
} }
else else
{ {

View file

@ -53,7 +53,7 @@
#include <multiboot.h> #include <multiboot.h>
#include <multiboot2.h> #include <multiboot2.h>
#define ABS(x) ((x) - _start + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200) #define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
.file "startup.S" .file "startup.S"
@ -66,16 +66,15 @@
.globl start, _start .globl start, _start
start: start:
_start: _start:
LOCAL (base):
/* /*
* Guarantee that "main" is loaded at 0x0:0x8200. * Guarantee that "main" is loaded at 0x0:0x8200.
*/ */
#ifdef APPLE_CC #ifdef __APPLE__
codestart_abs = ABS(codestart) - 0x10000 ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
ljmp $0, $(codestart_abs)
#else #else
ljmp $0, $ABS(codestart) ljmp $0, $ABS(LOCAL (codestart))
#endif #endif
/* /*
* Compatibility version number * Compatibility version number
* *
@ -183,7 +182,7 @@ multiboot_trampoline:
.code16 .code16
/* the real mode code continues... */ /* the real mode code continues... */
codestart: LOCAL (codestart):
cli /* we're not safe here! */ cli /* we're not safe here! */
/* set up %ds, %ss, and %es */ /* set up %ds, %ss, and %es */
@ -1157,7 +1156,7 @@ FUNCTION(grub_console_putchar)
*/ */
/* this table is used in translate_keycode below */ /* this table is used in translate_keycode below */
translation_table: LOCAL (translation_table):
.word GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT .word GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT
.word GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT .word GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT
.word GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP .word GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP
@ -1179,11 +1178,10 @@ translate_keycode:
pushw %bx pushw %bx
pushw %si pushw %si
#ifdef APPLE_CC #ifdef __APPLE__
translation_table_abs = ABS (translation_table) - 0x10000 movw $(ABS(LOCAL (translation_table)) - 0x10000), %si
movw $(translation_table_abs), %si
#else #else
movw $ABS(translation_table), %si movw $ABS(LOCAL (translation_table)), %si
#endif #endif
1: lodsw 1: lodsw

View file

@ -388,7 +388,7 @@ grub_free (void *ptr)
do do
{ {
grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n", grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n",
__FILE__, __LINE__, q, q->size, q->magic); GRUB_FILE, __LINE__, q, q->size, q->magic);
q = q->next; q = q->next;
} }
while (q != r->first); while (q != r->first);

View file

@ -26,32 +26,31 @@
/* All the possible state transitions on the command line. If a /* All the possible state transitions on the command line. If a
transition can not be found, it is assumed that there is no transition can not be found, it is assumed that there is no
transition and keep_value is assumed to be 1. */ transition and keep_value is assumed to be 1. */
static struct grub_parser_state_transition state_transitions[] = static struct grub_parser_state_transition state_transitions[] = {
{ {GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_QUOTE, '\'', 0},
{ GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_QUOTE, '\'', 0}, {GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_DQUOTE, '\"', 0},
{ GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_DQUOTE, '\"', 0}, {GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_VAR, '$', 0},
{ GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_VAR, '$', 0}, {GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_ESC, '\\', 0},
{ GRUB_PARSER_STATE_TEXT, GRUB_PARSER_STATE_ESC, '\\', 0},
{ GRUB_PARSER_STATE_ESC, GRUB_PARSER_STATE_TEXT, 0, 1}, {GRUB_PARSER_STATE_ESC, GRUB_PARSER_STATE_TEXT, 0, 1},
{ GRUB_PARSER_STATE_QUOTE, GRUB_PARSER_STATE_TEXT, '\'', 0}, {GRUB_PARSER_STATE_QUOTE, GRUB_PARSER_STATE_TEXT, '\'', 0},
{ GRUB_PARSER_STATE_DQUOTE, GRUB_PARSER_STATE_TEXT, '\"', 0}, {GRUB_PARSER_STATE_DQUOTE, GRUB_PARSER_STATE_TEXT, '\"', 0},
{ GRUB_PARSER_STATE_DQUOTE, GRUB_PARSER_STATE_QVAR, '$', 0}, {GRUB_PARSER_STATE_DQUOTE, GRUB_PARSER_STATE_QVAR, '$', 0},
{ GRUB_PARSER_STATE_VAR, GRUB_PARSER_STATE_VARNAME2, '{', 0}, {GRUB_PARSER_STATE_VAR, GRUB_PARSER_STATE_VARNAME2, '{', 0},
{ GRUB_PARSER_STATE_VAR, GRUB_PARSER_STATE_VARNAME, 0, 1}, {GRUB_PARSER_STATE_VAR, GRUB_PARSER_STATE_VARNAME, 0, 1},
{ GRUB_PARSER_STATE_VARNAME, GRUB_PARSER_STATE_TEXT, ' ', 1}, {GRUB_PARSER_STATE_VARNAME, GRUB_PARSER_STATE_TEXT, ' ', 1},
{ GRUB_PARSER_STATE_VARNAME2, GRUB_PARSER_STATE_TEXT, '}', 0}, {GRUB_PARSER_STATE_VARNAME2, GRUB_PARSER_STATE_TEXT, '}', 0},
{ GRUB_PARSER_STATE_QVAR, GRUB_PARSER_STATE_QVARNAME2, '{', 0}, {GRUB_PARSER_STATE_QVAR, GRUB_PARSER_STATE_QVARNAME2, '{', 0},
{ GRUB_PARSER_STATE_QVAR, GRUB_PARSER_STATE_QVARNAME, 0, 1}, {GRUB_PARSER_STATE_QVAR, GRUB_PARSER_STATE_QVARNAME, 0, 1},
{ GRUB_PARSER_STATE_QVARNAME, GRUB_PARSER_STATE_TEXT, '\"', 0}, {GRUB_PARSER_STATE_QVARNAME, GRUB_PARSER_STATE_TEXT, '\"', 0},
{ GRUB_PARSER_STATE_QVARNAME, GRUB_PARSER_STATE_DQUOTE, ' ', 1}, {GRUB_PARSER_STATE_QVARNAME, GRUB_PARSER_STATE_DQUOTE, ' ', 1},
{ GRUB_PARSER_STATE_QVARNAME2, GRUB_PARSER_STATE_DQUOTE, '}', 0}, {GRUB_PARSER_STATE_QVARNAME2, GRUB_PARSER_STATE_DQUOTE, '}', 0},
{ 0, 0, 0, 0} {0, 0, 0, 0}
}; };
@ -74,17 +73,17 @@ grub_parser_cmdline_state (grub_parser_state_t state, char c, char *result)
if (transition->input == c) if (transition->input == c)
break; break;
if (transition->input == ' ' && ! grub_isalpha (c) if (transition->input == ' ' && !grub_isalpha (c)
&& ! grub_isdigit (c) && c != '_') && !grub_isdigit (c) && c != '_')
break; break;
/* A less perfect match was found, use this one if no exact /* A less perfect match was found, use this one if no exact
match can be found. */ match can be found. */
if (transition->input == 0) if (transition->input == 0)
break; break;
} }
if (! transition->from_state) if (!transition->from_state)
transition = &default_transition; transition = &default_transition;
if (transition->keep_value) if (transition->keep_value)
@ -113,43 +112,44 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline,
auto int check_varstate (grub_parser_state_t s); auto int check_varstate (grub_parser_state_t s);
int check_varstate (grub_parser_state_t s) int check_varstate (grub_parser_state_t s)
{ {
return (s == GRUB_PARSER_STATE_VARNAME return (s == GRUB_PARSER_STATE_VARNAME
|| s == GRUB_PARSER_STATE_VARNAME2 || s == GRUB_PARSER_STATE_VARNAME2
|| s == GRUB_PARSER_STATE_QVARNAME || s == GRUB_PARSER_STATE_QVARNAME
|| s == GRUB_PARSER_STATE_QVARNAME2); || s == GRUB_PARSER_STATE_QVARNAME2);
} }
auto void add_var (grub_parser_state_t newstate); auto void add_var (grub_parser_state_t newstate);
void add_var (grub_parser_state_t newstate) void add_var (grub_parser_state_t newstate)
{ {
char *val; char *val;
/* Check if a variable was being read in and the end of the name /* Check if a variable was being read in and the end of the name
was reached. */ was reached. */
if (! (check_varstate (state) && !check_varstate (newstate))) if (!(check_varstate (state) && !check_varstate (newstate)))
return; return;
*(vp++) = '\0'; *(vp++) = '\0';
val = grub_env_get (varname); val = grub_env_get (varname);
vp = varname; vp = varname;
if (! val) if (!val)
return; return;
/* Insert the contents of the variable in the buffer. */ /* Insert the contents of the variable in the buffer. */
for (; *val; val++) for (; *val; val++)
*(bp++) = *val; *(bp++) = *val;
} }
*argc = 0; *argc = 0;
do do
{ {
if (! rd || !*rd) if (!rd || !*rd)
{ {
if (getline) if (getline)
getline (&rd, 1); getline (&rd, 1);
else break; else
break;
} }
if (!rd) if (!rd)
@ -190,7 +190,8 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline,
} }
state = newstate; state = newstate;
} }
} while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state)); }
while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state));
/* A special case for when the last character was part of a /* A special case for when the last character was part of a
variable. */ variable. */
@ -204,12 +205,12 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline,
/* Reserve memory for the return values. */ /* Reserve memory for the return values. */
args = grub_malloc (bp - buffer); args = grub_malloc (bp - buffer);
if (! args) if (!args)
return grub_errno; return grub_errno;
grub_memcpy (args, buffer, bp - buffer); grub_memcpy (args, buffer, bp - buffer);
*argv = grub_malloc (sizeof (char *) * (*argc + 1)); *argv = grub_malloc (sizeof (char *) * (*argc + 1));
if (! *argv) if (!*argv)
{ {
grub_free (args); grub_free (args);
return grub_errno; return grub_errno;
@ -229,35 +230,34 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline,
return 0; return 0;
} }
struct grub_handler_class grub_parser_class = struct grub_handler_class grub_parser_class = {
{ .name = "parser"
.name = "parser" };
};
grub_err_t grub_err_t
grub_parser_execute (char *source) grub_parser_execute (char *source)
{ {
auto grub_err_t getline (char **line, int cont); auto grub_err_t getline (char **line, int cont);
grub_err_t getline (char **line, int cont __attribute__ ((unused))) grub_err_t getline (char **line, int cont __attribute__ ((unused)))
{ {
char *p; char *p;
if (! source) if (!source)
{ {
*line = 0; *line = 0;
return 0; return 0;
} }
p = grub_strchr (source, '\n'); p = grub_strchr (source, '\n');
if (p) if (p)
*p = 0; *p = 0;
*line = grub_strdup (source); *line = grub_strdup (source);
if (p) if (p)
*p = '\n'; *p = '\n';
source = p ? p + 1 : 0; source = p ? p + 1 : 0;
return 0; return 0;
} }
while (source) while (source)
{ {

View file

@ -17,40 +17,44 @@
*/ */
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/mm.h>
#include <grub/partition.h> #include <grub/partition.h>
#include <grub/disk.h> #include <grub/disk.h>
static grub_partition_map_t grub_partition_map_list; grub_partition_map_t grub_partition_map_list;
void static grub_partition_t
grub_partition_map_register (grub_partition_map_t partmap) grub_partition_map_probe (const grub_partition_map_t partmap,
grub_disk_t disk, int partnum)
{ {
partmap->next = grub_partition_map_list; grub_partition_t p = 0;
grub_partition_map_list = partmap;
}
void auto int find_func (grub_disk_t d, const grub_partition_t partition);
grub_partition_map_unregister (grub_partition_map_t partmap)
{
grub_partition_map_t *p, q;
for (p = &grub_partition_map_list, q = *p; q; p = &(q->next), q = q->next) int find_func (grub_disk_t d __attribute__ ((unused)),
if (q == partmap) const grub_partition_t partition)
{ {
*p = q->next; if (partnum == partition->number)
break; {
} p = (grub_partition_t) grub_malloc (sizeof (*p));
} if (! p)
return 1;
int grub_memcpy (p, partition, sizeof (*p));
grub_partition_map_iterate (int (*hook) (const grub_partition_map_t partmap)) return 1;
{ }
grub_partition_map_t p;
for (p = grub_partition_map_list; p; p = p->next) return 0;
if (hook (p)) }
return 1;
partmap->iterate (disk, find_func);
if (grub_errno)
goto fail;
return p;
fail:
grub_free (p);
return 0; return 0;
} }
@ -58,28 +62,66 @@ grub_partition_t
grub_partition_probe (struct grub_disk *disk, const char *str) grub_partition_probe (struct grub_disk *disk, const char *str)
{ {
grub_partition_t part = 0; grub_partition_t part = 0;
grub_partition_t curpart = 0;
grub_partition_t tail;
const char *ptr;
auto int part_map_probe (const grub_partition_map_t partmap); part = tail = disk->partition;
int part_map_probe (const grub_partition_map_t partmap) for (ptr = str; *ptr;)
{ {
part = partmap->probe (disk, str); grub_partition_map_t partmap;
if (part) int num;
return 1; const char *partname, *partname_end;
if (grub_errno == GRUB_ERR_BAD_PART_TABLE) partname = ptr;
while (*ptr && grub_isalpha (*ptr))
ptr++;
partname_end = ptr;
num = grub_strtoul (ptr, (char **) &ptr, 0) - 1;
curpart = 0;
/* Use the first partition map type found. */
FOR_PARTITION_MAPS(partmap)
{
if (partname_end != partname &&
(grub_strncmp (partmap->name, partname, partname_end - partname)
!= 0 || partmap->name[partname_end - partname] != 0))
continue;
disk->partition = part;
curpart = grub_partition_map_probe (partmap, disk, num);
disk->partition = tail;
if (curpart)
break;
if (grub_errno == GRUB_ERR_BAD_PART_TABLE)
{
/* Continue to next partition map type. */
grub_errno = GRUB_ERR_NONE;
continue;
}
break;
}
if (! curpart)
{ {
/* Continue to next partition map type. */ while (part)
grub_errno = GRUB_ERR_NONE; {
curpart = part->parent;
grub_free (part);
part = curpart;
}
return 0; return 0;
} }
curpart->parent = part;
return 1; part = curpart;
if (! ptr || *ptr != ',')
break;
ptr++;
} }
/* Use the first partition map type found. */
grub_partition_map_iterate (part_map_probe);
return part; return part;
} }
@ -88,40 +130,51 @@ grub_partition_iterate (struct grub_disk *disk,
int (*hook) (grub_disk_t disk, int (*hook) (grub_disk_t disk,
const grub_partition_t partition)) const grub_partition_t partition))
{ {
grub_partition_map_t partmap = 0;
int ret = 0; int ret = 0;
auto int part_map_iterate (const grub_partition_map_t p); auto int part_iterate (grub_disk_t dsk, const grub_partition_t p);
auto int part_map_iterate_hook (grub_disk_t d,
const grub_partition_t partition);
int part_map_iterate_hook (grub_disk_t d __attribute__ ((unused)), int part_iterate (grub_disk_t dsk,
const grub_partition_t partition __attribute__ ((unused))) const grub_partition_t partition)
{ {
return 1; struct grub_partition p = *partition;
} p.parent = dsk->partition;
dsk->partition = 0;
int part_map_iterate (const grub_partition_map_t p) if (hook (dsk, &p))
{
grub_dprintf ("partition", "Detecting %s...\n", p->name);
p->iterate (disk, part_map_iterate_hook);
if (grub_errno != GRUB_ERR_NONE)
{ {
/* Continue to next partition map type. */ ret = 1;
grub_dprintf ("partition", "%s detection failed.\n", p->name); return 1;
grub_errno = GRUB_ERR_NONE;
return 0;
} }
if (p.start != 0)
grub_dprintf ("partition", "%s detection succeeded.\n", p->name); {
partmap = p; const struct grub_partition_map *partmap;
return 1; dsk->partition = &p;
FOR_PARTITION_MAPS(partmap)
{
grub_err_t err;
err = partmap->iterate (dsk, part_iterate);
if (err)
grub_errno = GRUB_ERR_NONE;
if (ret)
break;
}
}
dsk->partition = p.parent;
return ret;
} }
grub_partition_map_iterate (part_map_iterate); {
if (partmap) const struct grub_partition_map *partmap;
ret = partmap->iterate (disk, hook); FOR_PARTITION_MAPS(partmap)
{
grub_err_t err;
err = partmap->iterate (disk, part_iterate);
if (err)
grub_errno = GRUB_ERR_NONE;
if (ret)
break;
}
}
return ret; return ret;
} }
@ -129,5 +182,32 @@ grub_partition_iterate (struct grub_disk *disk,
char * char *
grub_partition_get_name (const grub_partition_t partition) grub_partition_get_name (const grub_partition_t partition)
{ {
return partition->partmap->get_name (partition); char *out = 0;
int curlen = 0;
grub_partition_t part;
for (part = partition; part; part = part->parent)
{
/* Even on 64-bit machines this buffer is enough to hold
longest number. */
char buf[grub_strlen (part->partmap->name) + 25];
int strl;
grub_snprintf (buf, sizeof (buf), "%s%d", part->partmap->name,
part->number + 1);
strl = grub_strlen (buf);
if (curlen)
{
out = grub_realloc (out, curlen + strl + 2);
grub_memcpy (out + strl + 1, out, curlen);
out[curlen + 1 + strl] = 0;
grub_memcpy (out, buf, strl);
out[strl] = ',';
curlen = curlen + 1 + strl;
}
else
{
curlen = strl;
out = grub_strdup (buf);
}
}
return out;
} }

View file

@ -59,7 +59,7 @@ typedef union {
double g; double g;
} PROPERLY_ALIGNED_TYPE; } PROPERLY_ALIGNED_TYPE;
#define gcry_assert(x) grub_assert_real(__FILE__, __LINE__, x) #define gcry_assert(x) grub_assert_real(GRUB_FILE, __LINE__, x)
static inline void static inline void
grub_assert_real (const char *file, int line, int cond) grub_assert_real (const char *file, int line, int cond)

View file

@ -140,7 +140,6 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
grub_uint32_t * unit, grub_uint32_t * unit,
grub_uint32_t * slice, grub_uint32_t * part) grub_uint32_t * slice, grub_uint32_t * part)
{ {
char *p;
grub_device_t dev; grub_device_t dev;
#ifdef GRUB_MACHINE_PCBIOS #ifdef GRUB_MACHINE_PCBIOS
@ -154,22 +153,13 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
dev = grub_device_open (0); dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition) if (dev && dev->disk && dev->disk->partition)
{ {
char *p0; if (dev->disk->partition->parent)
p0 = p = dev->disk->partition->partmap->get_name (dev->disk->partition);
if (p)
{ {
if ((p[0] >= '0') && (p[0] <= '9')) *part = dev->disk->partition->number;
{ *slice = dev->disk->partition->parent->number + 1;
*slice = grub_strtoul (p, &p, 0);
if ((p) && (p[0] == ','))
p++;
}
if ((p[0] >= 'a') && (p[0] <= 'z'))
*part = p[0] - 'a';
} }
grub_free (p0); else
*slice = dev->disk->partition->number + 1;
} }
if (dev) if (dev)
grub_device_close (dev); grub_device_close (dev);

View file

@ -27,10 +27,8 @@
* - APM table * - APM table
*/ */
/* The bits in the required part of flags field we don't support. */
#define UNSUPPORTED_FLAGS 0x0000fff8
#include <grub/loader.h> #include <grub/loader.h>
#include <grub/command.h>
#include <grub/machine/loader.h> #include <grub/machine/loader.h>
#include <grub/multiboot.h> #include <grub/multiboot.h>
#include <grub/cpu/multiboot.h> #include <grub/cpu/multiboot.h>
@ -45,18 +43,78 @@
#include <grub/env.h> #include <grub/env.h>
#include <grub/i386/relocator.h> #include <grub/i386/relocator.h>
#include <grub/video.h> #include <grub/video.h>
#include <grub/memory.h>
#include <grub/i18n.h>
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h> #include <grub/efi/efi.h>
#endif #endif
extern grub_dl_t my_mod; #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
static grub_size_t code_size, alloc_mbi; #define DEFAULT_VIDEO_MODE "text"
#else
#define DEFAULT_VIDEO_MODE "auto"
#endif
grub_size_t grub_multiboot_alloc_mbi;
char *grub_multiboot_payload_orig; char *grub_multiboot_payload_orig;
grub_addr_t grub_multiboot_payload_dest; grub_addr_t grub_multiboot_payload_dest;
grub_size_t grub_multiboot_pure_size; grub_size_t grub_multiboot_pure_size;
grub_uint32_t grub_multiboot_payload_eip; grub_uint32_t grub_multiboot_payload_eip;
static int accepts_video;
static int accepts_ega_text;
static int console_required;
static grub_dl_t my_mod;
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
grub_uint32_t
grub_get_multiboot_mmap_count (void)
{
grub_size_t count = 0;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
{
count++;
return 0;
}
grub_mmap_iterate (hook);
return count;
}
grub_err_t
grub_multiboot_set_video_mode (void)
{
grub_err_t err;
const char *modevar;
if (accepts_video || !GRUB_MACHINE_HAS_VGA_TEXT)
{
modevar = grub_env_get ("gfxpayload");
if (! modevar || *modevar == 0)
err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
else
{
char *tmp;
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_errno;
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}
}
else
err = grub_video_set_mode ("text", 0, 0);
return err;
}
static grub_err_t static grub_err_t
grub_multiboot_boot (void) grub_multiboot_boot (void)
@ -75,14 +133,14 @@ grub_multiboot_boot (void)
}; };
mbi_size = grub_multiboot_get_mbi_size (); mbi_size = grub_multiboot_get_mbi_size ();
if (alloc_mbi < mbi_size) if (grub_multiboot_alloc_mbi < mbi_size)
{ {
grub_multiboot_payload_orig grub_multiboot_payload_orig
= grub_relocator32_realloc (grub_multiboot_payload_orig, = grub_relocator32_realloc (grub_multiboot_payload_orig,
grub_multiboot_pure_size + mbi_size); grub_multiboot_pure_size + mbi_size);
if (!grub_multiboot_payload_orig) if (!grub_multiboot_payload_orig)
return grub_errno; return grub_errno;
alloc_mbi = mbi_size; grub_multiboot_alloc_mbi = mbi_size;
} }
state.ebx = grub_multiboot_payload_dest + grub_multiboot_pure_size; state.ebx = grub_multiboot_payload_dest + grub_multiboot_pure_size;
@ -112,7 +170,7 @@ grub_multiboot_unload (void)
grub_relocator32_free (grub_multiboot_payload_orig); grub_relocator32_free (grub_multiboot_payload_orig);
alloc_mbi = 0; grub_multiboot_alloc_mbi = 0;
grub_multiboot_payload_orig = NULL; grub_multiboot_payload_orig = NULL;
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -129,7 +187,7 @@ grub_multiboot_unload (void)
#undef MULTIBOOT_LOAD_ELF32 #undef MULTIBOOT_LOAD_ELF32
/* Load ELF32 or ELF64. */ /* Load ELF32 or ELF64. */
static grub_err_t grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer) grub_multiboot_load_elf (grub_file_t file, void *buffer)
{ {
if (grub_multiboot_is_elf32 (buffer)) if (grub_multiboot_is_elf32 (buffer))
@ -140,137 +198,77 @@ grub_multiboot_load_elf (grub_file_t file, void *buffer)
return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class"); return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
} }
void grub_err_t
grub_multiboot (int argc, char *argv[]) grub_multiboot_set_console (int console_type, int accepted_consoles,
int width, int height, int depth,
int console_req)
{
console_required = console_req;
if (!(accepted_consoles
& (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
| (GRUB_MACHINE_HAS_VGA_TEXT ? GRUB_MULTIBOOT_CONSOLE_EGA_TEXT : 0))))
{
if (console_required)
return grub_error (GRUB_ERR_BAD_OS,
"OS requires a console but none is available");
grub_printf ("WARNING: no console will be available to OS");
accepts_video = 0;
accepts_ega_text = 0;
return GRUB_ERR_NONE;
}
if (console_type == GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER)
{
char *buf;
if (depth && width && height)
buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", width,
height, depth, width, height);
else if (width && height)
buf = grub_xasprintf ("%dx%d,auto", width, height);
else
buf = grub_strdup ("auto");
if (!buf)
return grub_errno;
grub_env_set ("gfxpayload", buf);
grub_free (buf);
}
else
grub_env_set ("gfxpayload", "text");
accepts_video = !!(accepted_consoles & GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER);
accepts_ega_text = !!(accepted_consoles & GRUB_MULTIBOOT_CONSOLE_EGA_TEXT);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{ {
grub_file_t file = 0; grub_file_t file = 0;
char buffer[MULTIBOOT_SEARCH]; grub_err_t err;
struct multiboot_header *header;
grub_ssize_t len;
grub_loader_unset (); grub_loader_unset ();
if (argc == 0) if (argc == 0)
{ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
goto fail;
}
file = grub_gzfile_open (argv[0], 1); file = grub_gzfile_open (argv[0], 1);
if (! file) if (! file)
{ return grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
goto fail;
}
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH); grub_dl_ref (my_mod);
if (len < 32)
{
grub_error (GRUB_ERR_BAD_OS, "file too small");
goto fail;
}
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + 4))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
break;
}
if (header == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
goto fail;
}
if (header->flags & UNSUPPORTED_FLAGS)
{
grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported flag: 0x%x", header->flags);
goto fail;
}
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_payload_orig = NULL;
/* Skip filename. */ /* Skip filename. */
grub_multiboot_init_mbi (argc - 1, argv + 1); grub_multiboot_init_mbi (argc - 1, argv + 1);
if (header->flags & MULTIBOOT_AOUT_KLUDGE) grub_relocator32_free (grub_multiboot_payload_orig);
{ grub_multiboot_payload_orig = NULL;
int offset = ((char *) header - buffer -
(header->header_addr - header->load_addr));
int load_size = ((header->load_end_addr == 0) ? file->size - offset :
header->load_end_addr - header->load_addr);
if (header->bss_end_addr) err = grub_multiboot_load (file);
code_size = (header->bss_end_addr - header->load_addr); if (err)
else
code_size = load_size;
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi);
if (! grub_multiboot_payload_orig)
goto fail;
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
goto fail;
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
goto fail;
if (header->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_eip = header->entry_addr;
}
else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
goto fail; goto fail;
if (header->flags & MULTIBOOT_VIDEO_MODE)
{
switch (header->mode_type)
{
case 1:
grub_env_set ("gfxpayload", "text");
break;
case 0:
{
char *buf;
if (header->depth && header->width && header->height)
buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", header->width,
header->height, header->depth, header->width,
header->height);
else if (header->width && header->height)
buf = grub_xasprintf ("%dx%d,auto", header->width, header->height);
else
buf = grub_strdup ("auto");
if (!buf)
goto fail;
grub_env_set ("gfxpayload", buf);
grub_free (buf);
break;
}
}
}
grub_multiboot_set_accepts_video (!!(header->flags & MULTIBOOT_VIDEO_MODE));
grub_multiboot_set_bootdev (); grub_multiboot_set_bootdev ();
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0); grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
@ -282,12 +280,16 @@ grub_multiboot (int argc, char *argv[])
if (grub_errno != GRUB_ERR_NONE) if (grub_errno != GRUB_ERR_NONE)
{ {
grub_relocator32_free (grub_multiboot_payload_orig); grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_free_mbi ();
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
} }
return grub_errno;
} }
void static grub_err_t
grub_module (int argc, char *argv[]) grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{ {
grub_file_t file = 0; grub_file_t file = 0;
grub_ssize_t size; grub_ssize_t size;
@ -295,40 +297,64 @@ grub_module (int argc, char *argv[])
grub_err_t err; grub_err_t err;
if (argc == 0) if (argc == 0)
{ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
goto fail;
}
if (!grub_multiboot_payload_orig) if (!grub_multiboot_payload_orig)
{ return grub_error (GRUB_ERR_BAD_ARGUMENT,
grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the multiboot kernel first");
"you need to load the multiboot kernel first");
goto fail;
}
file = grub_gzfile_open (argv[0], 1); file = grub_gzfile_open (argv[0], 1);
if (! file) if (! file)
goto fail; return grub_errno;
size = grub_file_size (file); size = grub_file_size (file);
module = grub_memalign (MULTIBOOT_MOD_ALIGN, size); module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
if (! module) if (! module)
goto fail; {
grub_file_close (file);
return grub_errno;
}
err = grub_multiboot_add_module ((grub_addr_t) module, size, err = grub_multiboot_add_module ((grub_addr_t) module, size,
argc - 1, argv + 1); argc - 1, argv + 1);
if (err) if (err)
goto fail; {
grub_file_close (file);
return err;
}
if (grub_file_read (file, module, size) != size) if (grub_file_read (file, module, size) != size)
{ {
grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); grub_file_close (file);
goto fail; return grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
} }
fail: grub_file_close (file);
if (file) return GRUB_ERR_NONE;;
grub_file_close (file);
} }
static grub_command_t cmd_multiboot, cmd_module;
GRUB_MOD_INIT(multiboot)
{
cmd_multiboot =
#ifdef GRUB_USE_MULTIBOOT2
grub_register_command ("multiboot2", grub_cmd_multiboot,
0, N_("Load a multiboot 2 kernel."));
#else
grub_register_command ("multiboot", grub_cmd_multiboot,
0, N_("Load a multiboot kernel."));
#endif
cmd_module =
grub_register_command ("module", grub_cmd_module,
0, N_("Load a multiboot module."));
my_mod = mod;
}
GRUB_MOD_FINI(multiboot)
{
grub_unregister_command (cmd_multiboot);
grub_unregister_command (cmd_module);
}

View file

@ -53,6 +53,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
char *phdr_base; char *phdr_base;
int lowest_segment = -1, highest_segment = -1; int lowest_segment = -1, highest_segment = -1;
int i; int i;
grub_size_t code_size;
if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX) if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX)
return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class"); return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
@ -102,9 +103,9 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
grub_multiboot_pure_size += code_size; grub_multiboot_pure_size += code_size;
alloc_mbi = grub_multiboot_get_mbi_size (); grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi + 65536); = grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (!grub_multiboot_payload_orig) if (!grub_multiboot_payload_orig)
return grub_errno; return grub_errno;

View file

@ -23,6 +23,7 @@
#endif #endif
#include <grub/multiboot.h> #include <grub/multiboot.h>
#include <grub/cpu/multiboot.h> #include <grub/cpu/multiboot.h>
#include <grub/cpu/relocator.h>
#include <grub/disk.h> #include <grub/disk.h>
#include <grub/device.h> #include <grub/device.h>
#include <grub/partition.h> #include <grub/partition.h>
@ -30,15 +31,10 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/video.h> #include <grub/video.h>
#include <grub/file.h>
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU) /* The bits in the required part of flags field we don't support. */
#include <grub/i386/pc/vbe.h> #define UNSUPPORTED_FLAGS 0x0000fff8
#define DEFAULT_VIDEO_MODE "text"
#define HAS_VGA_TEXT 1
#else
#define DEFAULT_VIDEO_MODE "auto"
#define HAS_VGA_TEXT 0
#endif
struct module struct module
{ {
@ -56,33 +52,131 @@ static unsigned modcnt;
static char *cmdline = NULL; static char *cmdline = NULL;
static grub_uint32_t bootdev; static grub_uint32_t bootdev;
static int bootdev_set; static int bootdev_set;
static int accepts_video;
void grub_err_t
grub_multiboot_set_accepts_video (int val) grub_multiboot_load (grub_file_t file)
{ {
accepts_video = val; char *buffer;
} grub_ssize_t len;
struct multiboot_header *header;
grub_err_t err;
/* Return the length of the Multiboot mmap that will be needed to allocate buffer = grub_malloc (MULTIBOOT_SEARCH);
our platform's map. */ if (!buffer)
static grub_uint32_t return grub_errno;
grub_get_multiboot_mmap_len (void)
{
grub_size_t count = 0;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)), if (len < 32)
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
{ {
count++; grub_free (buffer);
return 0; return grub_error (GRUB_ERR_BAD_OS, "file too small");
} }
grub_mmap_iterate (hook); /* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
break;
}
return count * sizeof (struct multiboot_mmap_entry); if (header == 0)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
}
if (header->flags & UNSUPPORTED_FLAGS)
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported flag: 0x%x", header->flags);
}
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
{
int offset = ((char *) header - buffer -
(header->header_addr - header->load_addr));
int load_size = ((header->load_end_addr == 0) ? file->size - offset :
header->load_end_addr - header->load_addr);
grub_size_t code_size;
if (header->bss_end_addr)
code_size = (header->bss_end_addr - header->load_addr);
else
code_size = load_size;
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (! grub_multiboot_payload_orig)
{
grub_free (buffer);
return grub_errno;
}
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
{
grub_free (buffer);
return grub_errno;
}
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
{
grub_free (buffer);
return grub_errno;
}
if (header->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_eip = header->entry_addr;
}
else
{
err = grub_multiboot_load_elf (file, buffer);
if (err)
{
grub_free (buffer);
return err;
}
}
if (header->flags & MULTIBOOT_VIDEO_MODE)
{
switch (header->mode_type)
{
case 1:
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
| GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
0, 0, 0, 0);
break;
case 0:
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
| GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
header->width, header->height,
header->depth, 0);
break;
}
}
else
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
0, 0, 0, 0);
return err;
} }
grub_size_t grub_size_t
@ -90,7 +184,8 @@ grub_multiboot_get_mbi_size (void)
{ {
return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len () + ALIGN_UP (sizeof(PACKAGE_STRING), 4)
+ grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
+ 256 * sizeof (struct multiboot_color); + 256 * sizeof (struct multiboot_color);
} }
@ -136,33 +231,6 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
grub_mmap_iterate (hook); grub_mmap_iterate (hook);
} }
static grub_err_t
set_video_mode (void)
{
grub_err_t err;
const char *modevar;
if (accepts_video || !HAS_VGA_TEXT)
{
modevar = grub_env_get ("gfxpayload");
if (! modevar || *modevar == 0)
err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
else
{
char *tmp;
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_errno;
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}
}
else
err = grub_video_set_mode ("text", 0, 0);
return err;
}
static grub_err_t static grub_err_t
retrieve_video_parameters (struct multiboot_info *mbi, retrieve_video_parameters (struct multiboot_info *mbi,
grub_uint8_t *ptrorig, grub_uint32_t ptrdest) grub_uint8_t *ptrorig, grub_uint32_t ptrdest)
@ -173,7 +241,7 @@ retrieve_video_parameters (struct multiboot_info *mbi,
grub_video_driver_id_t driv_id; grub_video_driver_id_t driv_id;
struct grub_video_palette_data palette[256]; struct grub_video_palette_data palette[256];
err = set_video_mode (); err = grub_multiboot_set_video_mode ();
if (err) if (err)
{ {
grub_print_error (); grub_print_error ();
@ -293,7 +361,8 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
mbi->mods_count = 0; mbi->mods_count = 0;
} }
mmap_size = grub_get_multiboot_mmap_len (); mmap_size = grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry);
grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig); grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig);
mbi->mmap_length = mmap_size; mbi->mmap_length = mmap_size;
mbi->mmap_addr = ptrdest; mbi->mmap_addr = ptrdest;
@ -435,7 +504,6 @@ grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
void void
grub_multiboot_set_bootdev (void) grub_multiboot_set_bootdev (void)
{ {
char *p;
grub_uint32_t biosdev, slice = ~0, part = ~0; grub_uint32_t biosdev, slice = ~0, part = ~0;
grub_device_t dev; grub_device_t dev;
@ -445,25 +513,19 @@ grub_multiboot_set_bootdev (void)
biosdev = 0xffffffff; biosdev = 0xffffffff;
#endif #endif
if (biosdev == 0xffffffff)
return;
dev = grub_device_open (0); dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition) if (dev && dev->disk && dev->disk->partition)
{ {
char *p0; if (dev->disk->partition->parent)
p = p0 = dev->disk->partition->partmap->get_name (dev->disk->partition); {
if (p) part = dev->disk->partition->number;
{ slice = dev->disk->partition->parent->number;
if ((p[0] >= '0') && (p[0] <= '9'))
{
slice = grub_strtoul (p, &p, 0) - 1;
if ((p) && (p[0] == ','))
p++;
}
if ((p[0] >= 'a') && (p[0] <= 'z'))
part = p[0] - 'a';
} }
grub_free (p0); else
slice = dev->disk->partition->number;
} }
if (dev) if (dev)
grub_device_close (dev); grub_device_close (dev);

View file

@ -0,0 +1,700 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB 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 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/machine/memory.h>
#include <grub/memory.h>
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/biosnum.h>
#endif
#include <grub/multiboot.h>
#include <grub/cpu/multiboot.h>
#include <grub/cpu/relocator.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/video.h>
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
#include <grub/i386/pc/vbe.h>
#define HAS_VGA_TEXT 1
#else
#define HAS_VGA_TEXT 0
#endif
struct module
{
struct module *next;
grub_addr_t start;
grub_size_t size;
char *cmdline;
int cmdline_size;
};
struct module *modules, *modules_last;
static grub_size_t cmdline_size;
static grub_size_t total_modcmd;
static unsigned modcnt;
static char *cmdline = NULL;
static int bootdev_set;
static grub_uint32_t biosdev, slice, part;
grub_err_t
grub_multiboot_load (grub_file_t file)
{
char *buffer;
grub_ssize_t len;
struct multiboot_header *header;
grub_err_t err;
struct multiboot_header_tag *tag;
struct multiboot_header_tag_address *addr_tag = NULL;
int entry_specified = 0;
grub_addr_t entry = 0;
grub_uint32_t console_required = 0;
struct multiboot_header_tag_framebuffer *fbtag = NULL;
int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
buffer = grub_malloc (MULTIBOOT_SEARCH);
if (!buffer)
return grub_errno;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_OS, "file too small");
}
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->architecture
+ header->header_length + header->checksum))
break;
}
if (header == 0)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
}
for (tag = (struct multiboot_header_tag *) (header + 1);
tag->type != MULTIBOOT_TAG_TYPE_END;
tag = (struct multiboot_header_tag *) ((char *) tag + tag->size))
switch (tag->type)
{
case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
{
unsigned i;
struct multiboot_header_tag_information_request *request_tag
= (struct multiboot_header_tag_information_request *) tag;
if (request_tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
break;
for (i = 0; i < (request_tag->size - sizeof (request_tag))
/ sizeof (request_tag->requests[0]); i++)
switch (request_tag->requests[i])
{
case MULTIBOOT_TAG_TYPE_END:
case MULTIBOOT_TAG_TYPE_CMDLINE:
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
case MULTIBOOT_TAG_TYPE_MODULE:
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
case MULTIBOOT_TAG_TYPE_BOOTDEV:
case MULTIBOOT_TAG_TYPE_MMAP:
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
break;
case MULTIBOOT_TAG_TYPE_VBE:
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
case MULTIBOOT_TAG_TYPE_APM:
default:
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported information tag: 0x%x",
request_tag->requests[i]);
}
break;
}
case MULTIBOOT_HEADER_TAG_ADDRESS:
addr_tag = (struct multiboot_header_tag_address *) tag;
break;
case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
entry_specified = 1;
entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
break;
case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
accepted_consoles &= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
console_required = 1;
break;
case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
fbtag = (struct multiboot_header_tag_framebuffer *) tag;
accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
break;
/* GRUB always page-aligns modules. */
case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
break;
default:
if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported tag: 0x%x", tag->type);
}
break;
}
if (addr_tag && !entry_specified)
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"load address tag without entry address tag");
}
if (addr_tag)
{
int offset = ((char *) header - buffer -
(addr_tag->header_addr - addr_tag->load_addr));
int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
addr_tag->load_end_addr - addr_tag->load_addr);
grub_size_t code_size;
if (addr_tag->bss_end_addr)
code_size = (addr_tag->bss_end_addr - addr_tag->load_addr);
else
code_size = load_size;
grub_multiboot_payload_dest = addr_tag->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (! grub_multiboot_payload_orig)
{
grub_free (buffer);
return grub_errno;
}
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
{
grub_free (buffer);
return grub_errno;
}
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
{
grub_free (buffer);
return grub_errno;
}
if (addr_tag->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
addr_tag->bss_end_addr - addr_tag->load_addr - load_size);
}
else
{
err = grub_multiboot_load_elf (file, buffer);
if (err)
{
grub_free (buffer);
return err;
}
}
if (entry_specified)
grub_multiboot_payload_eip = entry;
if (fbtag)
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
accepted_consoles,
fbtag->width, fbtag->height,
fbtag->depth, console_required);
else
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
accepted_consoles,
0, 0, 0, console_required);
return err;
}
grub_size_t
grub_multiboot_get_mbi_size (void)
{
return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
+ (sizeof (struct multiboot_tag_string)
+ ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN))
+ (sizeof (struct multiboot_tag_string)
+ ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN))
+ (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd)
+ sizeof (struct multiboot_tag_basic_meminfo)
+ ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN)
+ (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry))
+ sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1;
}
/* Fill previously allocated Multiboot mmap. */
static void
grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
{
struct multiboot_mmap_entry *mmap_entry = tag->entries;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
{
mmap_entry->addr = addr;
mmap_entry->len = size;
switch (type)
{
case GRUB_MACHINE_MEMORY_AVAILABLE:
mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
break;
#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE
case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE:
mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
break;
#endif
#ifdef GRUB_MACHINE_MEMORY_NVS
case GRUB_MACHINE_MEMORY_NVS:
mmap_entry->type = MULTIBOOT_MEMORY_NVS;
break;
#endif
default:
mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
break;
}
mmap_entry++;
return 0;
}
tag->type = MULTIBOOT_TAG_TYPE_MMAP;
tag->size = sizeof (struct multiboot_tag_mmap)
+ sizeof (struct multiboot_mmap_entry) * grub_get_multiboot_mmap_count ();
tag->entry_size = sizeof (struct multiboot_mmap_entry);
tag->entry_version = 0;
grub_mmap_iterate (hook);
}
static grub_err_t
retrieve_video_parameters (grub_uint8_t **ptrorig)
{
grub_err_t err;
struct grub_video_mode_info mode_info;
void *framebuffer;
grub_video_driver_id_t driv_id;
struct grub_video_palette_data palette[256];
struct multiboot_tag_framebuffer *tag
= (struct multiboot_tag_framebuffer *) *ptrorig;
err = grub_multiboot_set_video_mode ();
if (err)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
driv_id = grub_video_get_driver_id ();
#if HAS_VGA_TEXT
if (driv_id == GRUB_VIDEO_DRIVER_NONE)
{
struct grub_vbe_mode_info_block vbe_mode_info;
grub_uint32_t vbe_mode;
#if defined (GRUB_MACHINE_PCBIOS)
{
grub_vbe_status_t status;
void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
status = grub_vbe_bios_get_mode (scratch);
vbe_mode = *(grub_uint32_t *) scratch;
if (status != GRUB_VBE_STATUS_OK)
return GRUB_ERR_NONE;
}
#else
vbe_mode = 3;
#endif
/* get_mode_info isn't available for mode 3. */
if (vbe_mode == 3)
{
grub_memset (&vbe_mode_info, 0,
sizeof (struct grub_vbe_mode_info_block));
vbe_mode_info.memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
vbe_mode_info.x_resolution = 80;
vbe_mode_info.y_resolution = 25;
}
#if defined (GRUB_MACHINE_PCBIOS)
else
{
grub_vbe_status_t status;
void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
if (status != GRUB_VBE_STATUS_OK)
return GRUB_ERR_NONE;
grub_memcpy (&vbe_mode_info, scratch,
sizeof (struct grub_vbe_mode_info_block));
}
#endif
if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
{
tag = (struct multiboot_tag_framebuffer *) *ptrorig;
tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
tag->common.size = 0;
tag->common.framebuffer_addr = 0xb8000;
tag->common.framebuffer_pitch = 2 * vbe_mode_info.x_resolution;
tag->common.framebuffer_width = vbe_mode_info.x_resolution;
tag->common.framebuffer_height = vbe_mode_info.y_resolution;
tag->common.framebuffer_bpp = 16;
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
tag->common.size = sizeof (tag->common);
tag->common.reserved = 0;
*ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
}
return GRUB_ERR_NONE;
}
#else
if (driv_id == GRUB_VIDEO_DRIVER_NONE)
return GRUB_ERR_NONE;
#endif
err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
if (err)
return err;
tag = (struct multiboot_tag_framebuffer *) *ptrorig;
tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
tag->common.size = 0;
tag->common.framebuffer_addr = (grub_addr_t) framebuffer;
tag->common.framebuffer_pitch = mode_info.pitch;
tag->common.framebuffer_width = mode_info.width;
tag->common.framebuffer_height = mode_info.height;
tag->common.framebuffer_bpp = mode_info.bpp;
tag->common.reserved = 0;
if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
{
unsigned i;
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
tag->framebuffer_palette_num_colors = mode_info.number_of_colors;
if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
tag->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
tag->common.size = sizeof (struct multiboot_tag_framebuffer_common)
+ sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors
* sizeof (struct multiboot_color);
for (i = 0; i < tag->framebuffer_palette_num_colors; i++)
{
tag->framebuffer_palette[i].red = palette[i].r;
tag->framebuffer_palette[i].green = palette[i].g;
tag->framebuffer_palette[i].blue = palette[i].b;
}
}
else
{
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
tag->framebuffer_red_field_position = mode_info.green_field_pos;
tag->framebuffer_red_mask_size = mode_info.green_mask_size;
tag->framebuffer_green_field_position = mode_info.green_field_pos;
tag->framebuffer_green_mask_size = mode_info.green_mask_size;
tag->framebuffer_blue_field_position = mode_info.blue_field_pos;
tag->framebuffer_blue_mask_size = mode_info.blue_mask_size;
tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6;
}
*ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
return GRUB_ERR_NONE;
}
grub_err_t
grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
grub_size_t bufsize)
{
grub_uint8_t *ptrorig;
grub_uint8_t *mbistart = (grub_uint8_t *) orig + buf_off
+ (ALIGN_UP (dest + buf_off, MULTIBOOT_TAG_ALIGN) - (dest + buf_off));
grub_err_t err;
if (bufsize < grub_multiboot_get_mbi_size ())
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
ptrorig = mbistart + 2 * sizeof (grub_uint32_t);
{
struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
tag->size = sizeof (struct multiboot_tag_string) + cmdline_size;
grub_memcpy (tag->string, cmdline, cmdline_size);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING);
grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
unsigned i;
struct module *cur;
for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
{
struct multiboot_tag_module *tag
= (struct multiboot_tag_module *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_MODULE;
tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size;
tag->mod_start = dest + cur->start;
tag->mod_end = tag->mod_start + cur->size;
grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
}
{
struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
grub_fill_multiboot_mmap (tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
struct multiboot_tag_basic_meminfo *tag
= (struct multiboot_tag_basic_meminfo *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
tag->size = sizeof (struct multiboot_tag_basic_meminfo);
/* Convert from bytes to kilobytes. */
tag->mem_lower = grub_mmap_get_lower () / 1024;
tag->mem_upper = grub_mmap_get_upper () / 1024;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
if (bootdev_set)
{
struct multiboot_tag_bootdev *tag
= (struct multiboot_tag_bootdev *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
tag->size = sizeof (struct multiboot_tag_bootdev);
tag->biosdev = biosdev;
tag->slice = slice;
tag->part = part;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
err = retrieve_video_parameters (&ptrorig);
if (err)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
}
{
struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_END;
tag->size = sizeof (struct multiboot_tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
((grub_uint32_t *) mbistart)[0] = ptrorig - mbistart;
((grub_uint32_t *) mbistart)[1] = 0;
return GRUB_ERR_NONE;
}
void
grub_multiboot_free_mbi (void)
{
struct module *cur, *next;
cmdline_size = 0;
total_modcmd = 0;
modcnt = 0;
grub_free (cmdline);
cmdline = NULL;
bootdev_set = 0;
for (cur = modules; cur; cur = next)
{
next = cur->next;
grub_free (cur->cmdline);
grub_free (cur);
}
modules = NULL;
modules_last = NULL;
}
grub_err_t
grub_multiboot_init_mbi (int argc, char *argv[])
{
grub_ssize_t len = 0;
char *p;
int i;
grub_multiboot_free_mbi ();
for (i = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;
if (len == 0)
len = 1;
cmdline = p = grub_malloc (len);
if (! cmdline)
return grub_errno;
cmdline_size = len;
for (i = 0; i < argc; i++)
{
p = grub_stpcpy (p, argv[i]);
*(p++) = ' ';
}
/* Remove the space after the last word. */
if (p != cmdline)
p--;
*p = '\0';
return GRUB_ERR_NONE;
}
grub_err_t
grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
int argc, char *argv[])
{
struct module *newmod;
char *p;
grub_ssize_t len = 0;
int i;
newmod = grub_malloc (sizeof (*newmod));
if (!newmod)
return grub_errno;
newmod->start = start;
newmod->size = size;
for (i = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;
if (len == 0)
len = 1;
newmod->cmdline = p = grub_malloc (len);
if (! newmod->cmdline)
{
grub_free (newmod);
return grub_errno;
}
newmod->cmdline_size = len;
total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
for (i = 0; i < argc; i++)
{
p = grub_stpcpy (p, argv[i]);
*(p++) = ' ';
}
/* Remove the space after the last word. */
if (p != newmod->cmdline)
p--;
*p = '\0';
if (modules_last)
modules_last->next = newmod;
else
{
modules = newmod;
modules_last->next = NULL;
}
modules_last = newmod;
modcnt++;
return GRUB_ERR_NONE;
}
void
grub_multiboot_set_bootdev (void)
{
grub_device_t dev;
slice = ~0;
part = ~0;
#ifdef GRUB_MACHINE_PCBIOS
biosdev = grub_get_root_biosnumber ();
#else
biosdev = 0xffffffff;
#endif
if (biosdev == 0xffffffff)
return;
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition)
{
if (dev->disk->partition->parent)
{
part = dev->disk->partition->number;
slice = dev->disk->partition->parent->number;
}
else
slice = dev->disk->partition->number;
}
if (dev)
grub_device_close (dev);
bootdev_set = 1;
}

View file

@ -31,6 +31,7 @@
#include <grub/machine/memory.h> #include <grub/machine/memory.h>
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/msdos_partition.h>
#include <grub/machine/biosnum.h> #include <grub/machine/biosnum.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/video.h> #include <grub/video.h>
@ -98,10 +99,22 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
dev = grub_device_open (0); dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition) if (dev && dev->disk && dev->disk->partition)
{ {
grub_disk_read (dev->disk, dev->disk->partition->offset, 446, 64, grub_disk_t disk = dev->disk;
(void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR if (disk)
+ (dev->disk->partition->index << 4)); {
grub_partition_t p = disk->partition;
if (p && grub_strcmp (p->partmap->name, "msdos") == 0)
{
disk->partition = p->parent;
grub_disk_read (disk, p->offset, 446, 64,
(void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR);
part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR
+ (p->index << 4));
disk->partition = p;
}
}
} }
if (dev) if (dev)

View file

@ -1,150 +0,0 @@
/* multiboot_loader.c - boot multiboot kernel image */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB 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 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/multiboot.h>
#include <grub/elf.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/command.h>
#include <grub/i18n.h>
grub_dl_t my_mod;
static int
find_multi_boot1_header (grub_file_t file)
{
struct multiboot_header *header;
char buffer[MULTIBOOT_SEARCH];
int found_status = 0;
grub_ssize_t len;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
return found_status;
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + 4))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
{
found_status = 1;
break;
}
}
return found_status;
}
static grub_err_t
grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
int header_multi_ver_found = 0;
grub_dl_ref (my_mod);
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
goto fail;
}
file = grub_gzfile_open (argv[0], 1);
if (! file)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
goto fail;
}
/* find which header is in the file */
if (find_multi_boot1_header (file))
header_multi_ver_found = 1;
else
{
grub_error (GRUB_ERR_BAD_OS, "multiboot header not found");
goto fail;
}
/* close file before calling functions */
if (file)
grub_file_close (file);
/* Launch multi boot with header */
grub_dprintf ("multiboot_loader",
"Launching multiboot 1 grub_multiboot() function\n");
grub_multiboot (argc, argv);
return grub_errno;
fail:
if (file)
grub_file_close (file);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_cmd_module_loader (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_dprintf("multiboot_loader",
"Launching multiboot 1 grub_module() function\n");
grub_module (argc, argv);
return grub_errno;
}
static grub_command_t cmd_multiboot, cmd_module;
GRUB_MOD_INIT(multiboot)
{
cmd_multiboot =
#ifdef GRUB_USE_MULTIBOOT2
grub_register_command ("multiboot2", grub_cmd_multiboot_loader,
0, N_("Load a multiboot 2 kernel."));
#else
grub_register_command ("multiboot", grub_cmd_multiboot_loader,
0, N_("Load a multiboot kernel."));
#endif
cmd_module =
grub_register_command ("module", grub_cmd_module_loader,
0, N_("Load a multiboot module."));
my_mod = mod;
}
GRUB_MOD_FINI(multiboot)
{
grub_unregister_command (cmd_multiboot);
grub_unregister_command (cmd_module);
}

View file

@ -19,32 +19,27 @@
#include <grub/symbol.h> #include <grub/symbol.h>
#define DS(x) ((x) - segstart) #define DS(x) ((x) - LOCAL (segstart))
segstart: LOCAL (segstart):
VARIABLE(grub_machine_mmaphook_start) VARIABLE(grub_machine_mmaphook_start)
.code16 .code16
VARIABLE(grub_machine_mmaphook_int12) VARIABLE(grub_machine_mmaphook_int12)
push %ds push %ds
push %cs push %cs
pop %ds pop %ds
#ifdef APPLE_CC movw DS (LOCAL (kblow)), %ax
grub_machine_mmaphook_kblow_rel = DS (EXT_C (grub_machine_mmaphook_kblow))
movw (grub_machine_mmaphook_kblow_rel), %ax
#else
movw DS (EXT_C (grub_machine_mmaphook_kblow)), %ax
#endif
pop %ds pop %ds
iret iret
VARIABLE(grub_machine_mmaphook_int15) VARIABLE(grub_machine_mmaphook_int15)
pushf pushf
cmpw $0xe801, %ax cmpw $0xe801, %ax
jz e801 jz LOCAL (e801)
cmpw $0xe820, %ax cmpw $0xe820, %ax
jz e820 jz LOCAL (e820)
cmpb $0x88, %ah cmpb $0x88, %ah
jz h88 jz LOCAL (h88)
popf popf
/* ljmp */ /* ljmp */
.byte 0xea .byte 0xea
@ -53,67 +48,44 @@ VARIABLE (grub_machine_mmaphook_int15offset)
VARIABLE (grub_machine_mmaphook_int15segment) VARIABLE (grub_machine_mmaphook_int15segment)
.word 0 .word 0
e801: LOCAL (e801):
popf popf
push %ds push %ds
push %cs push %cs
pop %ds pop %ds
#ifdef APPLE_CC movw DS (LOCAL (kbin16mb)), %ax
grub_machine_mmaphook_kbin16mb_rel = DS (EXT_C (grub_machine_mmaphook_kbin16mb)) movw DS (LOCAL (m64kbin4gb)), %bx
grub_machine_mmaphook_64kbin4gb_rel = DS (EXT_C (grub_machine_mmaphook_64kbin4gb))
movw (grub_machine_mmaphook_kbin16mb_rel), %ax
movw (grub_machine_mmaphook_64kbin4gb_rel), %bx
#else
movw DS (EXT_C (grub_machine_mmaphook_kbin16mb)), %ax
movw DS (EXT_C (grub_machine_mmaphook_64kbin4gb)), %bx
#endif
movw %ax, %cx movw %ax, %cx
movw %bx, %dx movw %bx, %dx
pop %ds pop %ds
clc clc
iret iret
h88: LOCAL (h88):
popf popf
push %ds push %ds
push %cs push %cs
pop %ds pop %ds
#ifdef APPLE_CC movw DS (LOCAL (kbin16mb)), %ax
movw (grub_machine_mmaphook_kbin16mb_rel), %ax
#else
movw DS (EXT_C (grub_machine_mmaphook_kbin16mb)), %ax
#endif
pop %ds pop %ds
clc clc
iret iret
e820: LOCAL (e820):
#ifdef APPLE_CC
mmaphook_mmap_rel = DS(mmaphook_mmap)
mmaphook_mmap_num_rel = DS(EXT_C(grub_machine_mmaphook_mmap_num))
#endif
popf popf
push %ds push %ds
push %cs push %cs
pop %ds pop %ds
cmpw $20, %cx cmpw $20, %cx
jb errexit jb LOCAL (errexit)
#ifdef APPLE_CC cmpw DS (LOCAL (mmap_num)), %bx
cmpw (mmaphook_mmap_num_rel), %bx jae LOCAL (errexit)
#else
cmpw DS (EXT_C (grub_machine_mmaphook_mmap_num)), %bx
#endif
jae errexit
cmp $0x534d4150, %edx cmp $0x534d4150, %edx
jne errexit jne LOCAL (errexit)
push %si push %si
push %di push %di
movw $20, %cx movw $20, %cx
#ifdef APPLE_CC movw $(DS(LOCAL (mmaphook_mmap))), %si
movl $(mmaphook_mmap_rel), %esi
#else
movw $(DS(mmaphook_mmap)), %si
#endif
mov %bx, %ax mov %bx, %ax
imul $20, %ax imul $20, %ax
add %ax, %si add %ax, %si
@ -122,19 +94,15 @@ e820:
pop %si pop %si
movl $20, %ecx movl $20, %ecx
inc %bx inc %bx
#ifdef APPLE_CC cmpw DS(LOCAL (mmap_num)), %bx
cmpw (mmaphook_mmap_num_rel), %bx jb LOCAL (noclean)
#else
cmpw DS(EXT_C(grub_machine_mmaphook_mmap_num)), %bx
#endif
jb noclean
xor %bx, %bx xor %bx, %bx
noclean: LOCAL (noclean):
mov $0x534d4150, %eax mov $0x534d4150, %eax
pop %ds pop %ds
clc clc
iret iret
errexit: LOCAL (errexit):
mov $0x534d4150, %eax mov $0x534d4150, %eax
pop %ds pop %ds
stc stc
@ -142,13 +110,18 @@ errexit:
iret iret
VARIABLE(grub_machine_mmaphook_mmap_num) VARIABLE(grub_machine_mmaphook_mmap_num)
LOCAL (mmap_num):
.word 0 .word 0
VARIABLE(grub_machine_mmaphook_kblow) VARIABLE(grub_machine_mmaphook_kblow)
LOCAL (kblow):
.word 0 .word 0
VARIABLE (grub_machine_mmaphook_kbin16mb) VARIABLE (grub_machine_mmaphook_kbin16mb)
LOCAL (kbin16mb):
.word 0 .word 0
VARIABLE (grub_machine_mmaphook_64kbin4gb) VARIABLE (grub_machine_mmaphook_64kbin4gb)
LOCAL (m64kbin4gb):
.word 0 .word 0
mmaphook_mmap: LOCAL (mmaphook_mmap):
/* Memory map is placed just after the interrupt handlers. */ /* Memory map is placed just after the interrupt handlers. */
VARIABLE(grub_machine_mmaphook_end) VARIABLE(grub_machine_mmaphook_end)
.byte 0

View file

@ -96,17 +96,12 @@ acorn_partition_map_iterate (grub_disk_t disk,
const grub_partition_t partition)) const grub_partition_t partition))
{ {
struct grub_partition part; struct grub_partition part;
struct grub_disk raw;
struct linux_part map[LINUX_MAP_ENTRIES]; struct linux_part map[LINUX_MAP_ENTRIES];
int i; int i;
grub_disk_addr_t sector; grub_disk_addr_t sector = 0;
grub_err_t err; grub_err_t err;
/* Enforce raw disk access. */ err = acorn_partition_map_find (disk, map, &sector);
raw = *disk;
raw.partition = 0;
err = acorn_partition_map_find (&raw, map, &sector);
if (err) if (err)
return err; return err;
@ -121,7 +116,7 @@ acorn_partition_map_iterate (grub_disk_t disk,
part.start = sector + map[i].start; part.start = sector + map[i].start;
part.len = map[i].size; part.len = map[i].size;
part.offset = 6; part.offset = 6;
part.index = i; part.number = part.index = i;
if (hook (disk, &part)) if (hook (disk, &part))
return grub_errno; return grub_errno;
@ -130,62 +125,13 @@ acorn_partition_map_iterate (grub_disk_t disk,
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
static grub_partition_t
acorn_partition_map_probe (grub_disk_t disk, const char *str)
{
struct linux_part map[LINUX_MAP_ENTRIES];
struct grub_disk raw = *disk;
unsigned long partnum = grub_strtoul (str, 0, 10) - 1;
grub_disk_addr_t sector;
grub_err_t err;
grub_partition_t p;
/* Enforce raw disk access. */
raw.partition = 0;
/* Get the partition number. */
if (partnum > LINUX_MAP_ENTRIES)
goto fail;
err = acorn_partition_map_find (&raw, map, &sector);
if (err)
return 0;
if (map[partnum].magic != LINUX_NATIVE_MAGIC
&& map[partnum].magic != LINUX_SWAP_MAGIC)
goto fail;
p = grub_malloc (sizeof (struct grub_partition));
if (! p)
return 0;
p->start = sector + map[partnum].start;
p->len = map[partnum].size;
p->offset = 6;
p->index = partnum;
return p;
fail:
grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
return 0;
}
static char *
acorn_partition_map_get_name (const grub_partition_t p)
{
return grub_xasprintf ("%d", p->index + 1);
}
/* Partition map type. */ /* Partition map type. */
static struct grub_partition_map grub_acorn_partition_map = static struct grub_partition_map grub_acorn_partition_map =
{ {
.name = "part_acorn", .name = "acorn",
.iterate = acorn_partition_map_iterate, .iterate = acorn_partition_map_iterate,
.probe = acorn_partition_map_probe,
.get_name = acorn_partition_map_get_name
}; };
GRUB_MOD_INIT(part_acorn) GRUB_MOD_INIT(part_acorn)

View file

@ -76,20 +76,15 @@ amiga_partition_map_iterate (grub_disk_t disk,
{ {
struct grub_partition part; struct grub_partition part;
struct grub_amiga_rdsk rdsk; struct grub_amiga_rdsk rdsk;
struct grub_disk raw;
int partno = 0; int partno = 0;
int next = -1; int next = -1;
unsigned pos; unsigned pos;
/* Enforce raw disk access. */
raw = *disk;
raw.partition = 0;
/* The RDSK block is one of the first 15 blocks. */ /* The RDSK block is one of the first 15 blocks. */
for (pos = 0; pos < 15; pos++) for (pos = 0; pos < 15; pos++)
{ {
/* Read the RDSK block which is a descriptor for the entire disk. */ /* Read the RDSK block which is a descriptor for the entire disk. */
if (grub_disk_read (&raw, pos, 0, sizeof (rdsk), &rdsk)) if (grub_disk_read (disk, pos, 0, sizeof (rdsk), &rdsk))
return grub_errno; return grub_errno;
if (grub_strcmp ((char *) rdsk.magic, "RDSK") == 0) if (grub_strcmp ((char *) rdsk.magic, "RDSK") == 0)
@ -110,7 +105,7 @@ amiga_partition_map_iterate (grub_disk_t disk,
struct grub_amiga_partition apart; struct grub_amiga_partition apart;
/* Read the RDSK block which is a descriptor for the entire disk. */ /* Read the RDSK block which is a descriptor for the entire disk. */
if (grub_disk_read (&raw, next, 0, sizeof (apart), &apart)) if (grub_disk_read (disk, next, 0, sizeof (apart), &apart))
return grub_errno; return grub_errno;
/* Calculate the first block and the size of the partition. */ /* Calculate the first block and the size of the partition. */
@ -123,7 +118,8 @@ amiga_partition_map_iterate (grub_disk_t disk,
* grub_be_to_cpu32 (apart.block_per_track)); * grub_be_to_cpu32 (apart.block_per_track));
part.offset = (grub_off_t) next * 512; part.offset = (grub_off_t) next * 512;
part.index = partno; part.number = partno;
part.index = 0;
part.partmap = &grub_amiga_partition_map; part.partmap = &grub_amiga_partition_map;
if (hook (disk, &part)) if (hook (disk, &part))
@ -136,65 +132,12 @@ amiga_partition_map_iterate (grub_disk_t disk,
return 0; return 0;
} }
static grub_partition_t
amiga_partition_map_probe (grub_disk_t disk, const char *str)
{
grub_partition_t p = 0;
int partnum = 0;
char *s = (char *) str;
auto int find_func (grub_disk_t d, const grub_partition_t partition);
int find_func (grub_disk_t d __attribute__ ((unused)),
const grub_partition_t partition)
{
if (partnum == partition->index)
{
p = (grub_partition_t) grub_malloc (sizeof (*p));
if (! p)
return 1;
grub_memcpy (p, partition, sizeof (*p));
return 1;
}
return 0;
}
/* Get the partition number. */
partnum = grub_strtoul (s, 0, 10) - 1;
if (grub_errno)
{
grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
return 0;
}
if (amiga_partition_map_iterate (disk, find_func))
goto fail;
return p;
fail:
grub_free (p);
return 0;
}
static char *
amiga_partition_map_get_name (const grub_partition_t p)
{
return grub_xasprintf ("%d", p->index + 1);
}
/* Partition map type. */ /* Partition map type. */
static struct grub_partition_map grub_amiga_partition_map = static struct grub_partition_map grub_amiga_partition_map =
{ {
.name = "part_amiga", .name = "amiga",
.iterate = amiga_partition_map_iterate, .iterate = amiga_partition_map_iterate,
.probe = amiga_partition_map_probe,
.get_name = amiga_partition_map_get_name
}; };
GRUB_MOD_INIT(part_amiga) GRUB_MOD_INIT(part_amiga)

View file

@ -105,17 +105,12 @@ apple_partition_map_iterate (grub_disk_t disk,
struct grub_partition part; struct grub_partition part;
struct grub_apple_header aheader; struct grub_apple_header aheader;
struct grub_apple_part apart; struct grub_apple_part apart;
struct grub_disk raw;
int partno = 0, partnum = 0; int partno = 0, partnum = 0;
unsigned pos; unsigned pos;
/* Enforce raw disk access. */
raw = *disk;
raw.partition = 0;
part.partmap = &grub_apple_partition_map; part.partmap = &grub_apple_partition_map;
if (grub_disk_read (&raw, 0, 0, sizeof (aheader), &aheader)) if (grub_disk_read (disk, 0, 0, sizeof (aheader), &aheader))
return grub_errno; return grub_errno;
if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC) if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC)
@ -131,8 +126,10 @@ apple_partition_map_iterate (grub_disk_t disk,
do do
{ {
if (grub_disk_read (&raw, pos / GRUB_DISK_SECTOR_SIZE, part.offset = pos / GRUB_DISK_SECTOR_SIZE;
pos % GRUB_DISK_SECTOR_SIZE, part.index = pos % GRUB_DISK_SECTOR_SIZE;
if (grub_disk_read (disk, part.offset, part.index,
sizeof (struct grub_apple_part), &apart)) sizeof (struct grub_apple_part), &apart))
return grub_errno; return grub_errno;
@ -156,6 +153,7 @@ apple_partition_map_iterate (grub_disk_t disk,
/ GRUB_DISK_SECTOR_SIZE; / GRUB_DISK_SECTOR_SIZE;
part.offset = pos; part.offset = pos;
part.index = partno; part.index = partno;
part.number = partno;
grub_dprintf ("partition", grub_dprintf ("partition",
"partition %d: name %s, type %s, start 0x%x, len 0x%x\n", "partition %d: name %s, type %s, start 0x%x, len 0x%x\n",
@ -179,65 +177,12 @@ apple_partition_map_iterate (grub_disk_t disk,
"Apple partition map not found"); "Apple partition map not found");
} }
static grub_partition_t
apple_partition_map_probe (grub_disk_t disk, const char *str)
{
grub_partition_t p = 0;
int partnum = 0;
char *s = (char *) str;
auto int find_func (grub_disk_t d, const grub_partition_t partition);
int find_func (grub_disk_t d __attribute__ ((unused)),
const grub_partition_t partition)
{
if (partnum == partition->index)
{
p = (grub_partition_t) grub_malloc (sizeof (*p));
if (! p)
return 1;
grub_memcpy (p, partition, sizeof (*p));
return 1;
}
return 0;
}
/* Get the partition number. */
partnum = grub_strtoul (s, 0, 10) - 1;
if (grub_errno)
{
grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
return 0;
}
if (apple_partition_map_iterate (disk, find_func))
goto fail;
return p;
fail:
grub_free (p);
return 0;
}
static char *
apple_partition_map_get_name (const grub_partition_t p)
{
return grub_xasprintf ("%d", p->index + 1);
}
/* Partition map type. */ /* Partition map type. */
static struct grub_partition_map grub_apple_partition_map = static struct grub_partition_map grub_apple_partition_map =
{ {
.name = "part_apple", .name = "apple",
.iterate = apple_partition_map_iterate, .iterate = apple_partition_map_iterate,
.probe = apple_partition_map_probe,
.get_name = apple_partition_map_get_name
}; };
GRUB_MOD_INIT(part_apple) GRUB_MOD_INIT(part_apple)

97
partmap/bsdlabel.c Normal file
View file

@ -0,0 +1,97 @@
/* bsdlabel.c - Read BSD style partition tables. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB 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 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/partition.h>
#include <grub/bsdlabel.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/dl.h>
static struct grub_partition_map grub_bsdlabel_partition_map;
static grub_err_t
bsdlabel_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
struct grub_partition_bsd_disk_label label;
struct grub_partition p;
grub_disk_addr_t delta = 0;
unsigned pos;
/* BSDLabel offsets are absolute even when it's embed inside partition. */
delta = grub_partition_get_start (disk->partition);
/* Read the BSD label. */
if (grub_disk_read (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR,
0, sizeof (label), &label))
return grub_errno;
/* Check if it is valid. */
if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
* GRUB_DISK_SECTOR_SIZE;
for (p.number = 0;
p.number < grub_cpu_to_le16 (label.num_partitions);
p.number++)
{
struct grub_partition_bsd_entry be;
p.offset = pos / GRUB_DISK_SECTOR_SIZE;
p.index = pos % GRUB_DISK_SECTOR_SIZE;
if (grub_disk_read (disk, p.offset, p.index, sizeof (be), &be))
return grub_errno;
p.start = grub_le_to_cpu32 (be.offset) - delta;
p.len = grub_le_to_cpu32 (be.size);
p.partmap = &grub_bsdlabel_partition_map;
if (be.fs_type != GRUB_PC_PARTITION_BSD_TYPE_UNUSED)
if (hook (disk, &p))
return grub_errno;
pos += sizeof (struct grub_partition_bsd_entry);
}
return GRUB_ERR_NONE;
}
/* Partition map type. */
static struct grub_partition_map grub_bsdlabel_partition_map =
{
.name = "bsd",
.iterate = bsdlabel_partition_map_iterate,
};
GRUB_MOD_INIT(part_bsd)
{
grub_partition_map_register (&grub_bsdlabel_partition_map);
}
GRUB_MOD_FINI(part_bsd)
{
grub_partition_map_unregister (&grub_bsdlabel_partition_map);
}

View file

@ -44,18 +44,13 @@ gpt_partition_map_iterate (grub_disk_t disk,
struct grub_partition part; struct grub_partition part;
struct grub_gpt_header gpt; struct grub_gpt_header gpt;
struct grub_gpt_partentry entry; struct grub_gpt_partentry entry;
struct grub_disk raw;
struct grub_msdos_partition_mbr mbr; struct grub_msdos_partition_mbr mbr;
grub_uint64_t entries; grub_uint64_t entries;
unsigned int i; unsigned int i;
int last_offset = 0; int last_offset = 0;
/* Enforce raw disk access. */
raw = *disk;
raw.partition = 0;
/* Read the protective MBR. */ /* Read the protective MBR. */
if (grub_disk_read (&raw, 0, 0, sizeof (mbr), &mbr)) if (grub_disk_read (disk, 0, 0, sizeof (mbr), &mbr))
return grub_errno; return grub_errno;
/* Check if it is valid. */ /* Check if it is valid. */
@ -67,7 +62,7 @@ gpt_partition_map_iterate (grub_disk_t disk,
return grub_error (GRUB_ERR_BAD_PART_TABLE, "no GPT partition map found"); return grub_error (GRUB_ERR_BAD_PART_TABLE, "no GPT partition map found");
/* Read the GPT header. */ /* Read the GPT header. */
if (grub_disk_read (&raw, 1, 0, sizeof (gpt), &gpt)) if (grub_disk_read (disk, 1, 0, sizeof (gpt), &gpt))
return grub_errno; return grub_errno;
if (grub_memcmp (gpt.magic, grub_gpt_magic, sizeof (grub_gpt_magic))) if (grub_memcmp (gpt.magic, grub_gpt_magic, sizeof (grub_gpt_magic)))
@ -78,7 +73,7 @@ gpt_partition_map_iterate (grub_disk_t disk,
entries = grub_le_to_cpu64 (gpt.partitions); entries = grub_le_to_cpu64 (gpt.partitions);
for (i = 0; i < grub_le_to_cpu32 (gpt.maxpart); i++) for (i = 0; i < grub_le_to_cpu32 (gpt.maxpart); i++)
{ {
if (grub_disk_read (&raw, entries, last_offset, if (grub_disk_read (disk, entries, last_offset,
sizeof (entry), &entry)) sizeof (entry), &entry))
return grub_errno; return grub_errno;
@ -90,16 +85,16 @@ gpt_partition_map_iterate (grub_disk_t disk,
part.len = (grub_le_to_cpu64 (entry.end) part.len = (grub_le_to_cpu64 (entry.end)
- grub_le_to_cpu64 (entry.start) + 1); - grub_le_to_cpu64 (entry.start) + 1);
part.offset = entries; part.offset = entries;
part.index = i; part.number = i;
part.index = last_offset;
part.partmap = &grub_gpt_partition_map; part.partmap = &grub_gpt_partition_map;
part.data = &entry;
grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", i, grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", i,
(unsigned long long) part.start, (unsigned long long) part.start,
(unsigned long long) part.len); (unsigned long long) part.len);
if (hook (disk, &part)) if (hook (disk, &part))
return 1; return grub_errno;
} }
last_offset += grub_le_to_cpu32 (gpt.partentry_size); last_offset += grub_le_to_cpu32 (gpt.partentry_size);
@ -110,69 +105,15 @@ gpt_partition_map_iterate (grub_disk_t disk,
} }
} }
return 0; return GRUB_ERR_NONE;
}
static grub_partition_t
gpt_partition_map_probe (grub_disk_t disk, const char *str)
{
grub_partition_t p = 0;
int partnum = 0;
char *s = (char *) str;
auto int find_func (grub_disk_t d, const grub_partition_t partition);
int find_func (grub_disk_t d __attribute__ ((unused)),
const grub_partition_t partition)
{
if (partnum == partition->index)
{
p = (grub_partition_t) grub_malloc (sizeof (*p));
if (! p)
return 1;
grub_memcpy (p, partition, sizeof (*p));
return 1;
}
return 0;
}
/* Get the partition number. */
partnum = grub_strtoul (s, 0, 10) - 1;
if (grub_errno)
{
grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
return 0;
}
gpt_partition_map_iterate (disk, find_func);
if (grub_errno)
goto fail;
return p;
fail:
grub_free (p);
return 0;
}
static char *
gpt_partition_map_get_name (const grub_partition_t p)
{
return grub_xasprintf ("%d", p->index + 1);
} }
/* Partition map type. */ /* Partition map type. */
static struct grub_partition_map grub_gpt_partition_map = static struct grub_partition_map grub_gpt_partition_map =
{ {
.name = "part_gpt", .name = "gpt",
.iterate = gpt_partition_map_iterate, .iterate = gpt_partition_map_iterate,
.probe = gpt_partition_map_probe,
.get_name = gpt_partition_map_get_name
}; };
GRUB_MOD_INIT(part_gpt) GRUB_MOD_INIT(part_gpt)

View file

@ -27,87 +27,20 @@
static struct grub_partition_map grub_msdos_partition_map; static struct grub_partition_map grub_msdos_partition_map;
/* Parse the partition representation in STR and return a partition. */
static grub_partition_t
grub_partition_parse (const char *str)
{
grub_partition_t p;
struct grub_msdos_partition *pcdata;
char *s = (char *) str;
p = (grub_partition_t) grub_malloc (sizeof (*p));
if (! p)
return 0;
pcdata = (struct grub_msdos_partition *) grub_malloc (sizeof (*pcdata));
if (! pcdata)
goto fail;
p->data = pcdata;
p->partmap = &grub_msdos_partition_map;
/* Initialize some of the fields with invalid values. */
pcdata->bsd_part = pcdata->dos_type = pcdata->bsd_type = p->index = -1;
/* Get the DOS partition number. The number is counted from one for
the user interface, and from zero internally. */
pcdata->dos_part = grub_strtoul (s, &s, 0) - 1;
if (grub_errno)
{
/* Not found. Maybe only a BSD label is specified. */
pcdata->dos_part = -1;
grub_errno = GRUB_ERR_NONE;
}
else if (*s == ',')
s++;
if (*s)
{
if (*s >= 'a' && *s <= 'h')
{
pcdata->bsd_part = *s - 'a';
s++;
}
if (*s)
goto fail;
}
if (pcdata->dos_part == -1 && pcdata->bsd_part == -1)
goto fail;
return p;
fail:
grub_free (p);
grub_free (pcdata);
grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
return 0;
}
static grub_err_t static grub_err_t
pc_partition_map_iterate (grub_disk_t disk, pc_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk, int (*hook) (grub_disk_t disk,
const grub_partition_t partition)) const grub_partition_t partition))
{ {
struct grub_partition p; struct grub_partition p;
struct grub_msdos_partition pcdata;
struct grub_msdos_partition_mbr mbr; struct grub_msdos_partition_mbr mbr;
struct grub_msdos_partition_disk_label label;
struct grub_disk raw;
int labeln = 0; int labeln = 0;
grub_disk_addr_t lastaddr; grub_disk_addr_t lastaddr;
grub_disk_addr_t ext_offset;
/* Enforce raw disk access. */
raw = *disk;
raw.partition = 0;
p.offset = 0; p.offset = 0;
pcdata.ext_offset = 0; ext_offset = 0;
pcdata.dos_part = -1; p.number = -1;
p.data = &pcdata;
p.partmap = &grub_msdos_partition_map; p.partmap = &grub_msdos_partition_map;
/* Any value different than `p.offset' will satisfy the check during /* Any value different than `p.offset' will satisfy the check during
@ -120,7 +53,7 @@ pc_partition_map_iterate (grub_disk_t disk,
struct grub_msdos_partition_entry *e; struct grub_msdos_partition_entry *e;
/* Read the MBR. */ /* Read the MBR. */
if (grub_disk_read (&raw, p.offset, 0, sizeof (mbr), &mbr)) if (grub_disk_read (disk, p.offset, 0, sizeof (mbr), &mbr))
goto finish; goto finish;
/* This is our loop-detection algorithm. It works the following way: /* This is our loop-detection algorithm. It works the following way:
@ -150,13 +83,10 @@ pc_partition_map_iterate (grub_disk_t disk,
p.start = p.offset + grub_le_to_cpu32 (e->start); p.start = p.offset + grub_le_to_cpu32 (e->start);
p.len = grub_le_to_cpu32 (e->length); p.len = grub_le_to_cpu32 (e->length);
pcdata.bsd_part = -1;
pcdata.dos_type = e->type;
pcdata.bsd_type = -1;
grub_dprintf ("partition", grub_dprintf ("partition",
"partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n", "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n",
p.index, e->flag, pcdata.dos_type, p.index, e->flag, e->type,
(unsigned long long) p.start, (unsigned long long) p.start,
(unsigned long long) p.len); (unsigned long long) p.len);
@ -168,59 +98,15 @@ pc_partition_map_iterate (grub_disk_t disk,
if (! grub_msdos_partition_is_empty (e->type) if (! grub_msdos_partition_is_empty (e->type)
&& ! grub_msdos_partition_is_extended (e->type)) && ! grub_msdos_partition_is_extended (e->type))
{ {
pcdata.dos_part++; p.number++;
if (hook (disk, &p)) if (hook (disk, &p))
return 1; return grub_errno;
/* Check if this is a BSD partition. */
if (grub_msdos_partition_is_bsd (e->type))
{
/* Check if the BSD label is within the DOS partition. */
if (p.len <= GRUB_PC_PARTITION_BSD_LABEL_SECTOR)
{
grub_dprintf ("partition", "no space for disk label\n");
continue;
}
/* Read the BSD label. */
if (grub_disk_read (&raw,
(p.start
+ GRUB_PC_PARTITION_BSD_LABEL_SECTOR),
0,
sizeof (label),
&label))
goto finish;
/* Check if it is valid. */
if (label.magic
!= grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
{
grub_dprintf ("partition",
"invalid disk label magic 0x%x on partition %d\n",
label.magic, p.index);
continue;
}
for (pcdata.bsd_part = 0;
pcdata.bsd_part < grub_cpu_to_le16 (label.num_partitions);
pcdata.bsd_part++)
{
struct grub_msdos_partition_bsd_entry *be
= label.entries + pcdata.bsd_part;
p.start = grub_le_to_cpu32 (be->offset);
p.len = grub_le_to_cpu32 (be->size);
pcdata.bsd_type = be->fs_type;
if (be->fs_type != GRUB_PC_PARTITION_BSD_TYPE_UNUSED)
if (hook (disk, &p))
return 1;
}
}
} }
else if (pcdata.dos_part < 4) else if (p.number < 4)
/* If this partition is a logical one, shouldn't increase the /* If this partition is a logical one, shouldn't increase the
partition number. */ partition number. */
pcdata.dos_part++; p.number++;
} }
/* Find an extended partition. */ /* Find an extended partition. */
@ -230,9 +116,9 @@ pc_partition_map_iterate (grub_disk_t disk,
if (grub_msdos_partition_is_extended (e->type)) if (grub_msdos_partition_is_extended (e->type))
{ {
p.offset = pcdata.ext_offset + grub_le_to_cpu32 (e->start); p.offset = ext_offset + grub_le_to_cpu32 (e->start);
if (! pcdata.ext_offset) if (! ext_offset)
pcdata.ext_offset = p.offset; ext_offset = p.offset;
break; break;
} }
@ -247,78 +133,12 @@ pc_partition_map_iterate (grub_disk_t disk,
return grub_errno; return grub_errno;
} }
static grub_partition_t
pc_partition_map_probe (grub_disk_t disk, const char *str)
{
grub_partition_t p;
struct grub_msdos_partition *pcdata;
auto int find_func (grub_disk_t d, const grub_partition_t partition);
int find_func (grub_disk_t d __attribute__ ((unused)),
const grub_partition_t partition)
{
struct grub_msdos_partition *partdata = partition->data;
if ((pcdata->dos_part == partdata->dos_part || pcdata->dos_part == -1)
&& pcdata->bsd_part == partdata->bsd_part)
{
grub_memcpy (p, partition, sizeof (*p));
p->data = pcdata;
grub_memcpy (pcdata, partdata, sizeof (*pcdata));
return 1;
}
return 0;
}
p = grub_partition_parse (str);
if (! p)
return 0;
pcdata = p->data;
pc_partition_map_iterate (disk, find_func);
if (grub_errno)
goto fail;
if (p->index < 0)
{
grub_error (GRUB_ERR_BAD_DEVICE, "no such partition");
goto fail;
}
return p;
fail:
grub_free (p);
grub_free (pcdata);
return 0;
}
static char *
pc_partition_map_get_name (const grub_partition_t p)
{
struct grub_msdos_partition *pcdata = p->data;
if (pcdata->bsd_part < 0)
return grub_xasprintf ("%d", pcdata->dos_part + 1);
else if (pcdata->dos_part < 0)
return grub_xasprintf ("%c", pcdata->bsd_part + 'a');
else
return grub_xasprintf ("%d,%c", pcdata->dos_part + 1,
pcdata->bsd_part + 'a');
}
/* Partition map type. */ /* Partition map type. */
static struct grub_partition_map grub_msdos_partition_map = static struct grub_partition_map grub_msdos_partition_map =
{ {
.name = "part_msdos", .name = "msdos",
.iterate = pc_partition_map_iterate, .iterate = pc_partition_map_iterate,
.probe = pc_partition_map_probe,
.get_name = pc_partition_map_get_name
}; };
GRUB_MOD_INIT(part_msdos) GRUB_MOD_INIT(part_msdos)

View file

@ -88,20 +88,16 @@ sun_partition_map_iterate (grub_disk_t disk,
const grub_partition_t partition)) const grub_partition_t partition))
{ {
grub_partition_t p; grub_partition_t p;
struct grub_disk raw;
struct grub_sun_block block; struct grub_sun_block block;
int partnum; int partnum;
grub_err_t err; grub_err_t err;
raw = *disk;
raw.partition = 0;
p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition)); p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition));
if (! p) if (! p)
return grub_errno; return grub_errno;
p->partmap = &grub_sun_partition_map; p->partmap = &grub_sun_partition_map;
err = grub_disk_read (&raw, 0, 0, sizeof (struct grub_sun_block), err = grub_disk_read (disk, 0, 0, sizeof (struct grub_sun_block),
&block); &block);
if (err) if (err)
{ {
@ -112,13 +108,12 @@ sun_partition_map_iterate (grub_disk_t disk,
if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic))
{ {
grub_free (p); grub_free (p);
return grub_error (GRUB_ERR_BAD_PART_TABLE, return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table");
"not a sun partition table");
} }
if (! grub_sun_is_valid (&block)) if (! grub_sun_is_valid (&block))
{ {
grub_free (p); grub_free (p);
return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum");
} }
@ -127,7 +122,7 @@ sun_partition_map_iterate (grub_disk_t disk,
for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++) for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++)
{ {
struct grub_sun_partition_descriptor *desc; struct grub_sun_partition_descriptor *desc;
if (block.infos[partnum].id == 0 if (block.infos[partnum].id == 0
|| block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID)
continue; continue;
@ -137,7 +132,7 @@ sun_partition_map_iterate (grub_disk_t disk,
* grub_be_to_cpu16 (block.ntrks) * grub_be_to_cpu16 (block.ntrks)
* grub_be_to_cpu16 (block.nsect)); * grub_be_to_cpu16 (block.nsect));
p->len = grub_be_to_cpu32 (desc->num_sectors); p->len = grub_be_to_cpu32 (desc->num_sectors);
p->index = partnum; p->number = p->index = partnum;
if (p->len) if (p->len)
{ {
if (hook (disk, p)) if (hook (disk, p))
@ -150,62 +145,11 @@ sun_partition_map_iterate (grub_disk_t disk,
return grub_errno; return grub_errno;
} }
static grub_partition_t
sun_partition_map_probe (grub_disk_t disk, const char *str)
{
grub_partition_t p = 0;
int partnum = 0;
char *s = (char *) str;
auto int find_func (grub_disk_t d, const grub_partition_t partition);
int find_func (grub_disk_t d __attribute__ ((unused)),
const grub_partition_t partition)
{
if (partnum == partition->index)
{
p = (grub_partition_t) grub_malloc (sizeof (*p));
if (p)
grub_memcpy (p, partition, sizeof (*p));
return 1;
}
return 0;
}
grub_errno = GRUB_ERR_NONE;
partnum = grub_strtoul (s, 0, 10) - 1;
if (grub_errno == GRUB_ERR_NONE)
{
if (sun_partition_map_iterate (disk, find_func))
{
grub_free (p);
p = 0;
}
}
else
{
grub_error (GRUB_ERR_BAD_FILENAME, "invalid partition");
p = 0;
}
return p;
}
static char *
sun_partition_map_get_name (const grub_partition_t p)
{
return grub_xasprintf ("%d", p->index + 1);
}
/* Partition map type. */ /* Partition map type. */
static struct grub_partition_map grub_sun_partition_map = static struct grub_partition_map grub_sun_partition_map =
{ {
.name = "part_sun", .name = "sun",
.iterate = sun_partition_map_iterate, .iterate = sun_partition_map_iterate,
.probe = sun_partition_map_probe,
.get_name = sun_partition_map_get_name
}; };
GRUB_MOD_INIT(part_sun) GRUB_MOD_INIT(part_sun)

144
partmap/sunpc.c Normal file
View file

@ -0,0 +1,144 @@
/* sunpc.c - Read SUN PC style partition tables. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2005,2006,2007,2009 Free Software Foundation, Inc.
*
* GRUB 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 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/partition.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/err.h>
#define GRUB_PARTMAP_SUN_PC_MAGIC 0xDABE
#define GRUB_PARTMAP_SUN_PC_MAX_PARTS 16
#define GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID 0x05
struct grub_sun_pc_partition_descriptor
{
grub_uint16_t id;
grub_uint16_t unused;
grub_uint32_t start_sector;
grub_uint32_t num_sectors;
} __attribute__ ((packed));
struct grub_sun_pc_block
{
grub_uint8_t unused[72];
struct grub_sun_pc_partition_descriptor partitions[GRUB_PARTMAP_SUN_PC_MAX_PARTS];
grub_uint8_t unused2[244];
grub_uint16_t magic; /* Magic number. */
grub_uint16_t csum; /* Label xor'd checksum. */
} __attribute__ ((packed));
static struct grub_partition_map grub_sun_pc_partition_map;
/* Verify checksum (true=ok). */
static int
grub_sun_is_valid (struct grub_sun_pc_block *label)
{
grub_uint16_t *pos;
grub_uint16_t sum = 0;
for (pos = (grub_uint16_t *) label;
pos < (grub_uint16_t *) (label + 1);
pos++)
sum ^= *pos;
return ! sum;
}
static grub_err_t
sun_pc_partition_map_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition))
{
grub_partition_t p;
struct grub_sun_pc_block block;
int partnum;
grub_err_t err;
p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition));
if (! p)
return grub_errno;
p->partmap = &grub_sun_pc_partition_map;
err = grub_disk_read (disk, 1, 0, sizeof (struct grub_sun_pc_block), &block);
if (err)
{
grub_free (p);
return err;
}
if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.magic))
{
grub_free (p);
return grub_error (GRUB_ERR_BAD_PART_TABLE,
"not a sun_pc partition table");
}
if (! grub_sun_is_valid (&block))
{
grub_free (p);
return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum");
}
/* Maybe another error value would be better, because partition
table _is_ recognized but invalid. */
for (partnum = 0; partnum < GRUB_PARTMAP_SUN_PC_MAX_PARTS; partnum++)
{
struct grub_sun_pc_partition_descriptor *desc;
if (block.partitions[partnum].id == 0
|| block.partitions[partnum].id == GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID)
continue;
desc = &block.partitions[partnum];
p->start = grub_le_to_cpu32 (desc->start_sector);
p->len = grub_le_to_cpu32 (desc->num_sectors);
p->number = partnum;
if (p->len)
{
if (hook (disk, p))
partnum = GRUB_PARTMAP_SUN_PC_MAX_PARTS;
}
}
grub_free (p);
return grub_errno;
}
/* Partition map type. */
static struct grub_partition_map grub_sun_pc_partition_map =
{
.name = "sunpc",
.iterate = sun_pc_partition_map_iterate,
};
GRUB_MOD_INIT(part_sunpc)
{
grub_partition_map_register (&grub_sun_pc_partition_map);
}
GRUB_MOD_FINI(part_sunpc)
{
grub_partition_map_unregister (&grub_sun_pc_partition_map);
}

View file

@ -49,7 +49,7 @@ static grub_err_t grub_pcpart_boot (const grub_device_t dev,
index = dev->disk->partition->index; index = dev->disk->partition->index;
part = dev->disk->partition; part = dev->disk->partition;
dev->disk->partition = 0; dev->disk->partition = part->parent;
/* Read the MBR. */ /* Read the MBR. */
if (grub_disk_read (dev->disk, 0, 0, sizeof (mbr), &mbr)) if (grub_disk_read (dev->disk, 0, 0, sizeof (mbr), &mbr))
@ -96,7 +96,7 @@ static grub_err_t grub_pcpart_type (const grub_device_t dev,
index = dev->disk->partition->index; index = dev->disk->partition->index;
part = dev->disk->partition; part = dev->disk->partition;
dev->disk->partition = 0; dev->disk->partition = part->parent;
/* Read the parttable. */ /* Read the parttable. */
if (grub_disk_read (dev->disk, part->offset, 0, if (grub_disk_read (dev->disk, part->offset, 0,
@ -140,10 +140,10 @@ static grub_err_t grub_pcpart_type (const grub_device_t dev,
GRUB_MOD_INIT (msdospart) GRUB_MOD_INIT (msdospart)
{ {
activate_table_handle = grub_parttool_register ("part_msdos", activate_table_handle = grub_parttool_register ("msdos",
grub_pcpart_boot, grub_pcpart_boot,
grub_pcpart_bootargs); grub_pcpart_bootargs);
type_table_handle = grub_parttool_register ("part_msdos", type_table_handle = grub_parttool_register ("msdos",
grub_pcpart_type, grub_pcpart_type,
grub_pcpart_typeargs); grub_pcpart_typeargs);

View file

@ -291,6 +291,32 @@ grub_script_execute_cmdif (struct grub_script_cmd *cmd)
return grub_script_execute_cmd (cmdif->exec_on_false); return grub_script_execute_cmd (cmdif->exec_on_false);
} }
/* Execute a for statement. */
grub_err_t
grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
{
int i;
int result;
char **args;
int argcount;
struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd;
args = grub_script_execute_arglist_to_argv (cmdfor->words, &argcount);
if (!args)
return grub_errno;
result = 0;
for (i = 0; i < argcount; i++)
{
grub_env_set (cmdfor->name->str, args[i]);
result = grub_script_execute_cmd (cmdfor->list);
grub_free (args[i]);
}
grub_free (args);
return result;
}
/* Execute the menu entry generate statement. */ /* Execute the menu entry generate statement. */
grub_err_t grub_err_t
grub_script_execute_menuentry (struct grub_script_cmd *cmd) grub_script_execute_menuentry (struct grub_script_cmd *cmd)

View file

@ -74,7 +74,7 @@
%token <arg> GRUB_PARSER_TOKEN_WORD "word" %token <arg> GRUB_PARSER_TOKEN_WORD "word"
%type <arglist> word argument arguments0 arguments1 %type <arglist> word argument arguments0 arguments1
%type <cmd> script_init script grubcmd ifcmd command %type <cmd> script_init script grubcmd ifcmd forcmd command
%type <cmd> commands1 menuentry statement %type <cmd> commands1 menuentry statement
%pure-parser %pure-parser
@ -92,7 +92,7 @@ script: newlines0
{ {
$$ = 0; $$ = 0;
} }
| script statement delimiter | script statement delimiter newlines0
{ {
struct grub_script_cmdblock *cmdblock; struct grub_script_cmdblock *cmdblock;
cmdblock = (struct grub_script_cmdblock *) $1; cmdblock = (struct grub_script_cmdblock *) $1;
@ -173,6 +173,7 @@ grubcmd: word arguments0
/* A single command. */ /* A single command. */
command: grubcmd { $$ = $1; } command: grubcmd { $$ = $1; }
| ifcmd { $$ = $1; } | ifcmd { $$ = $1; }
| forcmd { $$ = $1; }
; ;
/* A list of commands. */ /* A list of commands. */
@ -236,3 +237,14 @@ ifcmd: if commands1 delimiters1 "then" commands1 delimiters1 "fi"
grub_script_lexer_deref (state->lexerstate); grub_script_lexer_deref (state->lexerstate);
} }
; ;
forcmd: "for" "name"
{
grub_script_lexer_ref (state->lexerstate);
}
"in" arguments0 delimiters1 "do" commands1 delimiters1 "done"
{
$$ = grub_script_create_cmdfor (state, $2, $5, $8);
grub_script_lexer_deref (state->lexerstate);
}
;

View file

@ -221,6 +221,30 @@ grub_script_create_cmdif (struct grub_parser_param *state,
return (struct grub_script_cmd *) cmd; return (struct grub_script_cmd *) cmd;
} }
/* Create a command that functions as a for statement. */
struct grub_script_cmd *
grub_script_create_cmdfor (struct grub_parser_param *state,
struct grub_script_arg *name,
struct grub_script_arglist *words,
struct grub_script_cmd *list)
{
struct grub_script_cmdfor *cmd;
grub_dprintf ("scripting", "cmdfor\n");
cmd = grub_script_malloc (state, sizeof (*cmd));
if (! cmd)
return 0;
cmd->cmd.exec = grub_script_execute_cmdfor;
cmd->cmd.next = 0;
cmd->name = name;
cmd->words = words;
cmd->list = list;
return (struct grub_script_cmd *) cmd;
}
/* Create a command that adds a menu entry to the menu. Title is an /* Create a command that adds a menu entry to the menu. Title is an
argument that is parsed to generate a string that can be used as argument that is parsed to generate a string that can be used as
the title. The sourcecode for this entry is passed in SOURCECODE. the title. The sourcecode for this entry is passed in SOURCECODE.

View file

@ -0,0 +1,14 @@
#! /bin/sh -e
@builddir@/grub-script-check <<EOF
# comment 1
command1 arg1
command2 arg2
last command
# comment 2
EOF

View file

@ -0,0 +1,10 @@
#! /bin/sh -e
@builddir@/grub-script-check <<EOF
echo one;
echo one; echo two
echo one; echo two;
echo one ; echo two ;
echo one ; echo two ; echo three
echo one; echo two ; echo three;
EOF

27
tests/grub_script_for1.in Normal file
View file

@ -0,0 +1,27 @@
#! @builddir@/grub-shell-tester
for x in one two 'three 3' "four 4" five six-6; do echo $x; done
for x in one two 'three 3' "four 4" five six-6
do
echo $x
done
foo="1 2"
for x in ab${foo}cd; do echo $x; done
for x in "ab${foo}cd"; do echo $x; done
a="one two three"
y=foo
echo $y
for y in $a; do
echo $y
done
echo $y
b="one two three"
for z in $b; do
echo $z
done
echo $z

View file

@ -32,6 +32,7 @@ platform=@platform@
host_os=@host_os@ host_os=@host_os@
font=@datadir@/@PACKAGE_TARNAME@/ascii.pf2 font=@datadir@/@PACKAGE_TARNAME@/ascii.pf2
pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
localedir=@datadir@/locale
grub_setup=${sbindir}/`echo grub-setup | sed ${transform}` grub_setup=${sbindir}/`echo grub-setup | sed ${transform}`
if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] || [ "${target_cpu}-${platform}" = "mips-yeeloong" ] ; then if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] || [ "${target_cpu}-${platform}" = "mips-yeeloong" ] ; then
@ -263,9 +264,9 @@ fi
# Copy gettext files # Copy gettext files
mkdir -p ${grubdir}/locale/ mkdir -p ${grubdir}/locale/
for file in ${grubdir}/locale/*.mo ${pkglibdir}/locale/*.mo; do for dir in ${localedir}/*; do
if test -f "$file"; then if test -f "$dir/LC_MESSAGES/grub.mo"; then
cp -f "$file" ${grubdir}/locale/ cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo"
fi fi
done done
@ -287,7 +288,10 @@ fi
# Then the partition map module. In order to support partition-less media, # Then the partition map module. In order to support partition-less media,
# this command is allowed to fail (--target=fs already grants us that the # this command is allowed to fail (--target=fs already grants us that the
# filesystem will be accessible). # filesystem will be accessible).
partmap_module=`$grub_probe --target=partmap --device ${grub_device} 2> /dev/null` partmap_module=
for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do
partmap_module="$partmap_module part_$x";
done
# Device abstraction module, if any (lvm, raid). # Device abstraction module, if any (lvm, raid).
devabstraction_module=`$grub_probe --target=abstraction --device ${grub_device}` devabstraction_module=`$grub_probe --target=abstraction --device ${grub_device}`

View file

@ -84,13 +84,16 @@ grub_refresh (void)
static void static void
probe_partmap (grub_disk_t disk) probe_partmap (grub_disk_t disk)
{ {
grub_partition_t part;
if (disk->partition == NULL) if (disk->partition == NULL)
{ {
grub_util_info ("no partition map found for %s", disk->name); grub_util_info ("no partition map found for %s", disk->name);
return; return;
} }
printf ("%s\n", disk->partition->partmap->name); for (part = disk->partition; part; part = part->parent)
printf ("%s\n", part->partmap->name);
} }
static int static int

View file

@ -83,6 +83,12 @@ grub_script_execute_cmdif (struct grub_script_cmd *cmd __attribute__ ((unused)))
return 0; return 0;
} }
grub_err_t
grub_script_execute_cmdfor (struct grub_script_cmd *cmd __attribute__ ((unused)))
{
return 0;
}
grub_err_t grub_err_t
grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ ((unused))) grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ ((unused)))
{ {

View file

@ -379,11 +379,14 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
{ {
int is_partition = 0; int is_partition = 0;
char dev[PATH_MAX]; char dev[PATH_MAX];
grub_disk_addr_t part_start = 0;
part_start = grub_partition_get_start (disk->partition);
strcpy (dev, map[disk->id].device); strcpy (dev, map[disk->id].device);
if (disk->partition && sector >= disk->partition->start if (disk->partition && sector >= part_start
&& strncmp (map[disk->id].device, "/dev/", 5) == 0) && strncmp (map[disk->id].device, "/dev/", 5) == 0)
is_partition = linux_find_partition (dev, disk->partition->start); is_partition = linux_find_partition (dev, part_start);
if (data->dev && strcmp (data->dev, dev) == 0 && if (data->dev && strcmp (data->dev, dev) == 0 &&
data->access_mode == (flags & O_ACCMODE)) data->access_mode == (flags & O_ACCMODE))
@ -416,7 +419,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
} }
if (is_partition) if (is_partition)
sector -= disk->partition->start; sector -= part_start;
} }
#else /* ! __linux__ */ #else /* ! __linux__ */
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
@ -1077,39 +1080,25 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
int find_partition (grub_disk_t dsk __attribute__ ((unused)), int find_partition (grub_disk_t dsk __attribute__ ((unused)),
const grub_partition_t partition) const grub_partition_t partition)
{ {
struct grub_msdos_partition *pcdata = NULL; grub_disk_addr_t part_start = 0;
grub_util_info ("Partition %d starts from %lu",
partition->number, partition->start);
if (strcmp (partition->partmap->name, "part_msdos") == 0) part_start = grub_partition_get_start (partition);
pcdata = partition->data;
if (pcdata) if (hdg.start == part_start)
{ {
if (pcdata->bsd_part < 0) if (partition->parent)
grub_util_info ("DOS partition %d starts from %lu",
pcdata->dos_part, partition->start);
else
grub_util_info ("BSD partition %d,%c starts from %lu",
pcdata->dos_part, pcdata->bsd_part + 'a',
partition->start);
}
else
{
grub_util_info ("Partition %d starts from %lu",
partition->index, partition->start);
}
if (hdg.start == partition->start)
{
if (pcdata)
{ {
dos_part = pcdata->dos_part; dos_part = partition->parent->number;
bsd_part = pcdata->bsd_part; bsd_part = partition->number;
} }
else else
{ {
dos_part = partition->index; dos_part = partition->number;
bsd_part = -1; bsd_part = -1;
} }
return 1; return 1;
} }

View file

@ -31,6 +31,7 @@ target_cpu=@target_cpu@
platform=@platform@ platform=@platform@
host_os=@host_os@ host_os=@host_os@
pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
localedir=@datadir@/locale
grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
@ -182,9 +183,9 @@ done
# Copy gettext files # Copy gettext files
mkdir -p ${grubdir}/locale/ mkdir -p ${grubdir}/locale/
for file in ${grubdir}/locale/*.mo ${pkglibdir}/locale/*.mo; do for dir in ${localedir}/*; do
if test -f "$file"; then if test -f "$dir/LC_MESSAGES/grub.mo"; then
cp -f "$file" ${grubdir}/locale/ cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo"
fi fi
done done
@ -202,7 +203,10 @@ fi
# Then the partition map module. In order to support partition-less media, # Then the partition map module. In order to support partition-less media,
# this command is allowed to fail (--target=fs already grants us that the # this command is allowed to fail (--target=fs already grants us that the
# filesystem will be accessible). # filesystem will be accessible).
partmap_module=`$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null` partmap_module=
for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do
partmap_module="$partmap_module part_$x";
done
# Device abstraction module, if any (lvm, raid). # Device abstraction module, if any (lvm, raid).
devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}` devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}`

View file

@ -118,15 +118,10 @@ setup (const char *dir,
int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)), int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p) const grub_partition_t p)
{ {
struct grub_msdos_partition *pcdata = p->data;
/* There's always an embed region, and it starts right after the MBR. */ /* There's always an embed region, and it starts right after the MBR. */
embed_region.start = 1; embed_region.start = 1;
/* For its end offset, include as many dummy partitions as we can. */ if (embed_region.end > p->start)
if (! grub_msdos_partition_is_empty (pcdata->dos_type)
&& ! grub_msdos_partition_is_bsd (pcdata->dos_type)
&& embed_region.end > p->start)
embed_region.end = p->start; embed_region.end = p->start;
return 0; return 0;
@ -137,17 +132,21 @@ setup (const char *dir,
int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)), int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p) const grub_partition_t p)
{ {
struct grub_gpt_partentry *gptdata = p->data; struct grub_gpt_partentry gptdata;
disk->partition = p->parent;
if (grub_disk_read (disk, p->offset, p->index,
sizeof (gptdata), &gptdata))
return 0;
/* If there's an embed region, it is in a dedicated partition. */ /* If there's an embed region, it is in a dedicated partition. */
if (! memcmp (&gptdata->type, &grub_gpt_partition_type_bios_boot, 16)) if (! memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16))
{ {
embed_region.start = p->start; embed_region.start = p->start;
embed_region.end = p->start + p->len; embed_region.end = p->start + p->len;
return 1; return 1;
} }
return 0; return 0;
} }
@ -291,22 +290,19 @@ setup (const char *dir,
/* Embed information about the installed location. */ /* Embed information about the installed location. */
if (root_dev->disk->partition) if (root_dev->disk->partition)
{ {
if (strcmp (root_dev->disk->partition->partmap->name, if (root_dev->disk->partition->parent)
"part_msdos") == 0) {
{ if (root_dev->disk->partition->parent->parent)
struct grub_msdos_partition *pcdata = grub_util_error ("Installing on doubly nested partitions is "
root_dev->disk->partition->data; "not supported");
dos_part = pcdata->dos_part; dos_part = root_dev->disk->partition->parent->number;
bsd_part = pcdata->bsd_part; bsd_part = root_dev->disk->partition->number;
} }
else if (strcmp (root_dev->disk->partition->partmap->name,
"part_gpt") == 0)
{
dos_part = root_dev->disk->partition->index;
bsd_part = -1;
}
else else
grub_util_error (_("no DOS-style partitions found")); {
dos_part = root_dev->disk->partition->number;
bsd_part = -1;
}
} }
else else
dos_part = bsd_part = -1; dos_part = bsd_part = -1;
@ -339,6 +335,8 @@ setup (const char *dir,
int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t p) const grub_partition_t p)
{ {
if (p->parent)
return 0;
dest_partmap = p->partmap->name; dest_partmap = p->partmap->name;
return 1; return 1;
} }
@ -351,16 +349,16 @@ setup (const char *dir,
goto unable_to_embed; goto unable_to_embed;
} }
if (strcmp (dest_partmap, "part_msdos") == 0) if (strcmp (dest_partmap, "msdos") == 0)
grub_partition_iterate (dest_dev->disk, find_usable_region_msdos); grub_partition_iterate (dest_dev->disk, find_usable_region_msdos);
else if (strcmp (dest_partmap, "part_gpt") == 0) else if (strcmp (dest_partmap, "gpt") == 0)
grub_partition_iterate (dest_dev->disk, find_usable_region_gpt); grub_partition_iterate (dest_dev->disk, find_usable_region_gpt);
else else
grub_util_error (_("No DOS-style partitions found")); grub_util_error (_("No DOS-style partitions found"));
if (embed_region.end == embed_region.start) if (embed_region.end == embed_region.start)
{ {
if (! strcmp (dest_partmap, "part_msdos")) if (! strcmp (dest_partmap, "msdos"))
grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!")); grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!"));
else else
grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!")); grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!"));

View file

@ -179,7 +179,10 @@ fi
# Then the partition map module. In order to support partition-less media, # Then the partition map module. In order to support partition-less media,
# this command is allowed to fail (--target=fs already grants us that the # this command is allowed to fail (--target=fs already grants us that the
# filesystem will be accessible). # filesystem will be accessible).
partmap_module=`$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null` partmap_module=
for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do
partmap_module="$partmap_module part_$x";
done
# Device abstraction module, if any (lvm, raid). # Device abstraction module, if any (lvm, raid).
devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}` devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}`

View file

@ -604,10 +604,10 @@ make_system_path_relative_to_its_root (const char *path)
void void
grub_util_init_nls (void) grub_util_init_nls (void)
{ {
#if ENABLE_NLS #if (defined(ENABLE_NLS) && ENABLE_NLS)
setlocale (LC_ALL, ""); setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR); bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE); textdomain (PACKAGE);
#endif /* ENABLE_NLS */ #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
} }
#endif #endif

View file

@ -640,11 +640,11 @@ int FDECL2(main, int, argc, char **, argv){
char *log_file = 0; char *log_file = 0;
set_program_name (argv[0]); set_program_name (argv[0]);
#if ENABLE_NLS #if (defined(ENABLE_NLS) && ENABLE_NLS)
setlocale (LC_ALL, ""); setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR); bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE); textdomain (PACKAGE);
#endif /* ENABLE_NLS */ #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
if (argc < 2) if (argc < 2)
usage(); usage();

View file

@ -30,12 +30,12 @@
#include <prototyp.h> #include <prototyp.h>
#include <sys/stat.h> #include <sys/stat.h>
#if ENABLE_NLS #if (defined(ENABLE_NLS) && ENABLE_NLS)
# include <locale.h> # include <locale.h>
# include <libintl.h> # include <libintl.h>
#else /* ! ENABLE_NLS */ #else /* ! (defined(ENABLE_NLS) && ENABLE_NLS) */
/* Disabled NLS. /* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings The casts to 'const char *' serve the purpose of producing warnings
@ -43,7 +43,7 @@
On pre-ANSI systems without 'const', the config.h file is supposed to On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */ contain "#define const". */
# define gettext(Msgid) ((const char *) (Msgid)) # define gettext(Msgid) ((const char *) (Msgid))
#endif /* ENABLE_NLS */ #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
#define _(str) gettext(str) #define _(str) gettext(str)
#define N_(str) str #define N_(str) str