diff --git a/ChangeLog b/ChangeLog index c6adb363e..81f7f55f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,140 @@ +2009-05-02 Bean + + * conf/common.rmk (grub_script.tab.c): Change normal/parser.y to + script/sh/parser.y. + (pkglib_MODULES): Add normal.mod and sh.mod. + (normal_SOURCES): New variable. + (normal_mod_CFLAGS): Likewise. + (normal_mod_LDFLAGS): Likewise. + (sh_mod_SOURCES): Likewise. + (sh_mod_CFLAGS): Likewise. + (sh_mod_LDFLAGS): Likewise. + + * conf/i386-pc.rmk (normal/lexer.c_DEPENDENCIES): Changed to + script/sh/lexer.c_DEPENDENCIES. + (kernel_img_SOURCES): Remove kern/rescue.c, and kern/reader.c, + kern/rescue_reader.c and kern/rescue_parser.c. + (kernel_img_HEADERS): Remove rescue.h, add reader.h. + (grub_emu_SOURCES): Change source files. + (pkglib_MODULES): Remove normal.mod. + (normal_SOURCES): Removed. + (normal_mod_CFLAGS): Likewise. + (normal_mod_LDFLAGS): Likewise. + * conf/i386-coreboot.rmk: Likewise. + * conf/i386-efi.rmk: Likewise. + * conf/i386-ieee1276.rmk: Likewise. + * conf/powerpc-ieee1275.rmk: Likewise. + * conf/sparc64-ieee1275.rmk: Likewise. + * conf/x86_64-efi.rmk: Likewise. + + * include/grub/command.h (grub_command_execute): New inline function. + + * include/grub/menu.h (grub_menu_entry): Removed commands field. + + * include/grub/normal.h: Remove . + (grub_fs_module_list): Moved to normal/autofs.c. + (grub_exit_env): Removed. + (grub_command_execute): Likewise. + (grub_normal_menu_addentry): Renamed to grub_menu_addentry, removed + parameter script. + (read_command_list): New function declaration. + (read_fs_list): Likewise. + + * include/parser.h: Include . + (grub_parser_split_cmdline): Change type of getline parameter. + (grub_parser): New structure. + (grub_parser_class): New variable. + (grub_parser_execute): New function declaration. + (grub_register_rescue_parser): Likewise. + (grub_parser_register): New inline function. + (grub_parser_unregister): Likewise. + (grub_parser_get_current): Likewise. + (grub_parser_set_current): Likewise. + + * include/grub/reader.h: New file. + * kern/reader.c: Likewise. + * kern/rescue_parser.c: Likewise. + * kern/rescue_reader.c: Likewise. + * normal/autofs.c: Likewise. + * normal/dyncmd.c: Likewise. + + * include/grub/rescue.h: Removed. + * normal/command.h: Likewise. + + * include/grub/script.h: Moved to ... + * include/grub/script_sh.h: ... Moved here. + * normal/execute.c: Moved to ... + * script/sh/execute.c: ... Moved here. + * normal/function.c: Moved to ... + * script/sh/function.c: ... Moved here. + * normal/lexer.c: Moved to ... + * script/sh/lexer.c: ... Moved here. + * normal/parser.y: Moved to ... + * script/sh/parser.y: ... Moved here. + * normal/script.c: Moved to ... + * script/sh/script.c: ... Moved here. + + * normal/main.c: Remove and , include + . + (grub_exit_env): Removed. + (fs_module_list): Moved to normal/autofs.c. + (grub_file_getline): Don't handle comment here. + (free_menu): Skip removed field entry->commands. + (grub_normal_menu_addentry): Removed as grub_menu_entry, removed + script parameter. + (read_config_file): Removed nested parameter, change getline function. + (grub_enter_normal_mode): Removed. + (grub_dyncmd_dispatcher): Moved to normal/dyncmd.c. + (read_command_list): Likewise. + (autoload_fs_module): Moved to normal/autofs.c. + (read_fs_list): Likewise. + (reader_nested): New variable. + (grub_normal_execute): Run parser.sh to switch to sh parser. + (grub_cmd_rescue): Removed. + (cmd_normal): Removed. + (grub_cmd_normal): Unregister itself at the beginning. Don't register + rescue command. + (grub_cmdline_run): New function. + (grub_normal_reader_init): Likewise. + (grub_normal_read_line): Likewise. + (grub_env_write_pager): Likewise. + (cmdline): New variable. + (grub_normal_reader): Likewise. + (GRUB_MOD_INIT): Register normal reader and set as current, register + pager hook, register normal command with grub_register_command_prio, + so that it won't show up in command.lst. + (GRUB_MOD_FINI): Unregister normal reader, unhook pager, clear + grub_fs_autoload_hook. + + * normal/menu.c: Remove , add . + (grub_menu_execute_entry): Replace grub_script_execute with + grub_parser_execute, change parameter to grub_command_execute. + + * normal/menu_text.c: Remove . + + * normal/menu_entry.c: Remove , add + and . + (run): Change editor_getline to use new parser interface. Change + parameter to grub_command_execute. + + * kern/main.c: Remove , include , + and . + (grub_load_normal_mode): Execute normal command. + (grub_main): Call grub_register_core_commands, + grub_register_rescue_parser and grub_register_rescue_reader, use + grub_reader_loop to enter input loop. + + * kern/parser.c (grub_parser_spli_cmdline): Change type of getline + parameter. + (grub_parser_class): New variable. + (grub_parser_execute): New function. + + * loader/i386/multiboot.c: Remove . + * loader/multiboot2.c: Likewise. + * loader/sparc64/ieee1275/linux.c: Likewise. + + * util/grub-emu.c (read_command_list): New dummy function. + 2009-05-02 Robert Millan * util/deviceiter.c (grub_util_iterate_devices): Increase max drive diff --git a/conf/common.rmk b/conf/common.rmk index 0e63da6d5..2335d8f8e 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -56,8 +56,8 @@ grub_mkfont_LDFLAGS = $(freetype_libs) endif # For the parser. -grub_script.tab.c grub_script.tab.h: normal/parser.y - $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y +grub_script.tab.c grub_script.tab.h: script/sh/parser.y + $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/script/sh/parser.y DISTCLEANFILES += grub_script.tab.c grub_script.tab.h # For grub-emu. @@ -343,7 +343,7 @@ pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod \ loopback.mod fs_uuid.mod configfile.mod echo.mod \ terminfo.mod test.mod blocklist.mod hexdump.mod \ read.mod sleep.mod loadenv.mod crc.mod parttool.mod \ - pcpart.mod memrw.mod boot.mod + pcpart.mod memrw.mod boot.mod normal.mod sh.mod # For boot.mod. boot_mod_SOURCES = commands/boot.c @@ -470,6 +470,21 @@ memrw_mod_SOURCES = commands/memrw.c memrw_mod_CFLAGS = $(COMMON_CFLAGS) memrw_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For normal.mod. +normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \ + normal/autofs.c normal/handler.c \ + normal/color.c normal/completion.c normal/datetime.c normal/menu.c \ + normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \ + normal/misc.c +normal_mod_CFLAGS = $(COMMON_CFLAGS) +normal_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For sh.mod. +sh_mod_SOURCES = script/sh/main.c script/sh/script.c script/sh/execute.c \ + script/sh/function.c script/sh/lexer.c grub_script.tab.c +sh_mod_CFLAGS = $(COMMON_CFLAGS) +sh_mod_LDFLAGS = $(COMMON_LDFLAGS) + # Common Video Subsystem specific modules. pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod \ png.mod font.mod gfxterm.mod diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index 1284fe4ca..dbacc11ba 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -5,7 +5,7 @@ COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32 COMMON_LDFLAGS = -m32 -nostdlib # Used by various components. These rules need to precede them. -normal/lexer.c_DEPENDENCIES = grub_script.tab.h +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_PROGRAMS = kernel.elf @@ -16,7 +16,8 @@ kernel_elf_SOURCES = kern/i386/coreboot/startup.S \ kern/i386/multiboot_mmap.c \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/rescue.c kern/term.c \ + kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/rescue_parser.c kern/rescue_reader.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/i386/dl.c kern/parser.c kern/partition.c \ kern/i386/tsc.c kern/i386/pit.c \ @@ -28,7 +29,7 @@ kernel_elf_SOURCES = kern/i386/coreboot/startup.S \ symlist.c kernel_elf_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ - partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \ + partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \ machine/boot.h machine/console.h machine/init.h \ machine/memory.h machine/loader.h list.h handler.h command.h kernel_elf_CFLAGS = $(COMMON_CFLAGS) @@ -100,7 +101,7 @@ sbin_SCRIPTS += grub-install grub_install_SOURCES = util/i386/pc/grub-install.in # Modules. -pkglib_MODULES = linux.mod normal.mod multiboot.mod \ +pkglib_MODULES = linux.mod multiboot.mod \ aout.mod play.mod serial.mod ata.mod \ memdisk.mod pci.mod lspci.mod reboot.mod \ halt.mod datetime.mod date.mod datehook.mod \ @@ -111,27 +112,6 @@ linux_mod_SOURCES = loader/i386/linux.c linux_mod_CFLAGS = $(COMMON_CFLAGS) linux_mod_LDFLAGS = $(COMMON_LDFLAGS) -# -# Only arch dependant part of normal.mod will be here. Common part for -# all architecures of normal.mod is at start and should be kept at sync -# with other makefiles. -# -# Please put arch dependant part of normal.mod at the end of list to -# keep it simpler to update to different architectures. -# -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/handler.c \ - normal/completion.c normal/datetime.c normal/execute.c \ - normal/function.c normal/lexer.c normal/main.c normal/menu.c \ - normal/menu_text.c \ - normal/color.c \ - normal/menu_viewer.c normal/menu_entry.c \ - normal/misc.c grub_script.tab.c \ - normal/script.c \ - normal/i386/setjmp.S -normal_mod_CFLAGS = $(COMMON_CFLAGS) -normal_mod_ASFLAGS = $(COMMON_ASFLAGS) -normal_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For reboot.mod. reboot_mod_SOURCES = commands/reboot.c kern/i386/reboot.c reboot_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index 717683b3a..fd8957944 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -5,7 +5,7 @@ COMMON_CFLAGS = -fno-builtin -m32 COMMON_LDFLAGS = -melf_i386 -nostdlib # Used by various components. These rules need to precede them. -normal/lexer.c_DEPENDENCIES = grub_script.tab.h +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Utilities. bin_UTILITIES = grub-mkimage @@ -80,7 +80,7 @@ sbin_SCRIPTS = grub-install grub_install_SOURCES = util/i386/efi/grub-install.in # Modules. -pkglib_MODULES = kernel.mod normal.mod chain.mod appleldr.mod \ +pkglib_MODULES = kernel.mod chain.mod appleldr.mod \ linux.mod halt.mod reboot.mod pci.mod lspci.mod \ datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod @@ -88,7 +88,8 @@ pkglib_MODULES = kernel.mod normal.mod chain.mod appleldr.mod \ kernel_mod_EXPORTS = no kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/rescue.c kern/term.c \ + kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/rescue_parser.c kern/rescue_reader.c \ kern/i386/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ term/efi/console.c disk/efi/efidisk.c \ @@ -98,7 +99,7 @@ kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \ kern/generic/millisleep.c kernel_mod_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ - partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \ + partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \ efi/efi.h efi/time.h efi/disk.h list.h handler.h command.h kernel_mod_CFLAGS = $(COMMON_CFLAGS) kernel_mod_ASFLAGS = $(COMMON_ASFLAGS) @@ -114,27 +115,6 @@ symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist. kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1) -# -# Only arch dependant part of normal.mod will be here. Common part for -# all architecures of normal.mod is at start and should be kept at sync -# with other makefiles. -# -# Please put arch dependant part of normal.mod at the end of list to -# keep it simpler to update to different architectures. -# -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/handler.c \ - normal/completion.c normal/datetime.c normal/execute.c \ - normal/function.c normal/lexer.c normal/main.c normal/menu.c \ - normal/menu_text.c \ - normal/color.c \ - normal/menu_viewer.c normal/menu_entry.c \ - normal/misc.c grub_script.tab.c \ - normal/script.c \ - normal/i386/setjmp.S -normal_mod_CFLAGS = $(COMMON_CFLAGS) -normal_mod_ASFLAGS = $(COMMON_ASFLAGS) -normal_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For chain.mod. chain_mod_SOURCES = loader/efi/chainloader.c chain_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk index cb32c73c5..35d6ec675 100644 --- a/conf/i386-ieee1275.rmk +++ b/conf/i386-ieee1275.rmk @@ -5,7 +5,7 @@ COMMON_CFLAGS = -ffreestanding -mrtd -mregparm=3 COMMON_LDFLAGS = -nostdlib -static -lgcc # Used by various components. These rules need to precede them. -normal/lexer.c_DEPENDENCIES = grub_script.tab.h +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_PROGRAMS = kernel.elf @@ -17,7 +17,8 @@ kernel_elf_SOURCES = kern/i386/ieee1275/startup.S kern/i386/ieee1275/init.c \ kern/ieee1275/cmain.c kern/ieee1275/openfw.c \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/rescue.c kern/term.c \ + kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/rescue_parser.c kern/rescue_reader.c \ kern/i386/dl.c kern/parser.c kern/partition.c \ kern/env.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ @@ -28,7 +29,7 @@ kernel_elf_SOURCES = kern/i386/ieee1275/startup.S kern/i386/ieee1275/init.c \ symlist.c kernel_elf_HEADERS = cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ - partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \ + partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \ ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h \ list.h handler.h command.h kernel_elf_CFLAGS = $(COMMON_CFLAGS) @@ -101,32 +102,11 @@ sbin_SCRIPTS = grub-install grub_install_SOURCES = util/ieee1275/grub-install.in # Modules. -pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod \ - multiboot.mod aout.mod serial.mod linux.mod \ +pkglib_MODULES = halt.mod reboot.mod suspend.mod \ + multiboot.mod aout.mod serial.mod linux.mod \ nand.mod memdisk.mod pci.mod lspci.mod datetime.mod \ date.mod datehook.mod lsmmap.mod -# -# Only arch dependant part of normal.mod will be here. Common part for -# all architecures of normal.mod is at start and should be kept at sync -# with other makefiles. -# -# Please put arch dependant part of normal.mod at the end of list to -# keep it simpler to update to different architectures. -# -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/handler.c \ - normal/completion.c normal/datetime.c normal/execute.c \ - normal/function.c normal/lexer.c normal/main.c normal/menu.c \ - normal/menu_text.c \ - normal/color.c \ - normal/menu_viewer.c normal/menu_entry.c \ - normal/misc.c grub_script.tab.c \ - normal/script.c \ - normal/i386/setjmp.S -normal_mod_CFLAGS = $(COMMON_CFLAGS) -normal_mod_ASFLAGS = $(COMMON_ASFLAGS) -normal_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For multiboot.mod. multiboot_mod_SOURCES = loader/ieee1275/multiboot2.c \ loader/i386/multiboot_helper.S \ diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index d74a5fabf..c4b53fc63 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -7,7 +7,7 @@ COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32 COMMON_LDFLAGS = -m32 -nostdlib # Used by various components. These rules need to precede them. -normal/lexer.c_DEPENDENCIES = grub_script.tab.h +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_IMAGES = boot.img diskboot.img kernel.img pxeboot.img lnxboot.img \ @@ -46,7 +46,8 @@ cdboot_img_FORMAT = binary # For kernel.img. kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/rescue.c kern/term.c \ + kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/rescue_parser.c kern/rescue_reader.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \ kern/parser.c kern/partition.c \ @@ -58,7 +59,7 @@ kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \ symlist.c kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ - partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \ + partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \ machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \ machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \ machine/kernel.h machine/pxe.h list.h handler.h command.h @@ -131,16 +132,17 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c kern/list.c kern/handler.c \ - kern/command.c kern/corecmd.c commands/extcmd.c \ - normal/execute.c kern/file.c kern/fs.c normal/lexer.c \ - commands/boot.c kern/main.c kern/misc.c kern/parser.c \ - grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c \ - lib/arg.c normal/cmdline.c normal/command.c normal/datetime.c \ - normal/function.c normal/handler.c \ + kern/command.c kern/corecmd.c commands/extcmd.c kern/file.c \ + kern/fs.c commands/boot.c kern/main.c kern/misc.c kern/parser.c \ + kern/partition.c kern/reader.c kern/term.c \ + kern/rescue_reader.c kern/rescue_parser.c \ + lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c \ + normal/handler.c normal/autofs.c \ normal/completion.c normal/main.c normal/color.c \ normal/menu.c normal/menu_entry.c normal/menu_viewer.c \ normal/menu_text.c \ - normal/misc.c normal/script.c \ + script/sh/main.c script/sh/execute.c script/sh/function.c \ + script/sh/lexer.c script/sh/script.c grub_script.tab.c \ partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \ partmap/acorn.c partmap/gpt.c \ \ @@ -176,7 +178,7 @@ grub_install_SOURCES = util/i386/pc/grub-install.in # For grub-mkrescue. grub_mkrescue_SOURCES = util/i386/pc/grub-mkrescue.in -pkglib_MODULES = biosdisk.mod chain.mod normal.mod \ +pkglib_MODULES = biosdisk.mod chain.mod \ multiboot.mod reboot.mod halt.mod \ vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod \ ata.mod vga.mod memdisk.mod pci.mod lspci.mod \ @@ -204,27 +206,6 @@ linux_mod_SOURCES = loader/i386/linux.c linux_mod_CFLAGS = $(COMMON_CFLAGS) linux_mod_LDFLAGS = $(COMMON_LDFLAGS) -# -# Only arch dependant part of normal.mod will be here. Common part for -# all architecures of normal.mod is at start and should be kept at sync -# with other makefiles. -# -# Please put arch dependant part of normal.mod at the end of list to -# keep it simpler to update to different architectures. -# -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/datetime.c \ - normal/completion.c normal/execute.c normal/handler.c \ - normal/function.c normal/lexer.c normal/main.c normal/menu.c \ - normal/menu_text.c \ - normal/color.c \ - normal/menu_viewer.c normal/menu_entry.c \ - normal/misc.c grub_script.tab.c \ - normal/script.c \ - normal/i386/setjmp.S -normal_mod_CFLAGS = $(COMMON_CFLAGS) -normal_mod_ASFLAGS = $(COMMON_ASFLAGS) -normal_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For reboot.mod. reboot_mod_SOURCES = commands/reboot.c reboot_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 84f91d897..911adc6fb 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -6,7 +6,7 @@ COMMON_CFLAGS = -ffreestanding COMMON_LDFLAGS += -nostdlib # Used by various components. These rules need to precede them. -normal/lexer.c_DEPENDENCIES = grub_script.tab.h +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. @@ -14,7 +14,7 @@ MOSTLYCLEANFILES += symlist.c kernel_syms.lst DEFSYMFILES += kernel_syms.lst kernel_elf_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ - env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h rescue.h \ + env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h reader.h \ symbol.h term.h time.h types.h powerpc/libgcc.h loader.h partition.h \ pc_partition.h ieee1275/ieee1275.h machine/kernel.h handler.h list.h \ command.h @@ -82,7 +82,8 @@ grub_emu_LDFLAGS = $(LIBCURSES) kernel_elf_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/ieee1275/ieee1275.c kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ - kern/misc.c kern/mm.c kern/rescue.c kern/term.c \ + kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/rescue_parser.c kern/rescue_reader.c \ kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/ieee1275/init.c \ kern/ieee1275/mmap.c \ @@ -109,7 +110,6 @@ grub_mkrescue_SOURCES = util/powerpc/ieee1275/grub-mkrescue.in # Modules. pkglib_MODULES = halt.mod \ linux.mod \ - normal.mod \ reboot.mod \ suspend.mod \ multiboot.mod \ @@ -121,27 +121,6 @@ linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c linux_mod_CFLAGS = $(COMMON_CFLAGS) linux_mod_LDFLAGS = $(COMMON_LDFLAGS) -# -# Only arch dependant part of normal.mod will be here. Common part for -# all architecures of normal.mod is at start and should be kept at sync -# with other makefiles. -# -# Please put arch dependant part of normal.mod at the end of list to -# keep it simpler to update to different architectures. -# -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/datetime.c \ - normal/completion.c normal/execute.c normal/handler.c \ - normal/function.c normal/lexer.c normal/main.c normal/menu.c \ - normal/menu_text.c \ - normal/color.c \ - normal/menu_viewer.c normal/menu_entry.c \ - normal/misc.c grub_script.tab.c \ - normal/script.c \ - normal/powerpc/setjmp.S -normal_mod_CFLAGS = $(COMMON_CFLAGS) -normal_mod_ASFLAGS = $(COMMON_ASFLAGS) -normal_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For suspend.mod suspend_mod_SOURCES = commands/ieee1275/suspend.c suspend_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk index e1929d1e3..c11442abc 100644 --- a/conf/sparc64-ieee1275.rmk +++ b/conf/sparc64-ieee1275.rmk @@ -6,7 +6,7 @@ COMMON_CFLAGS = -ffreestanding -m64 -mno-app-regs COMMON_LDFLAGS = -melf64_sparc -nostdlib -mno-relax # Used by various components. These rules need to precede them. -normal/lexer.c_DEPENDENCIES = grub_script.tab.h +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_IMAGES = boot.img diskboot.img kernel.img @@ -28,14 +28,15 @@ DEFSYMFILES += kernel_syms.lst kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ - partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \ + partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \ list.h handler.h command.h \ sparc64/libgcc.h ieee1275/ieee1275.h machine/kernel.h \ sparc64/ieee1275/ieee1275.h kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c \ kern/ieee1275/ieee1275.c kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ - kern/misc.c kern/mm.c kern/rescue.c kern/term.c \ + kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/rescue_parser.c kern/rescue_reader.c \ kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/sparc64/ieee1275/ieee1275.c \ kern/sparc64/ieee1275/init.c \ @@ -142,7 +143,6 @@ grub_install_SOURCES = util/sparc64/ieee1275/grub-install.in # Modules. pkglib_MODULES = halt.mod \ linux.mod \ - normal.mod \ reboot.mod \ memdisk.mod \ lsmmap.mod @@ -152,27 +152,6 @@ linux_mod_SOURCES = loader/sparc64/ieee1275/linux.c linux_mod_CFLAGS = $(COMMON_CFLAGS) linux_mod_LDFLAGS = $(COMMON_LDFLAGS) -# -# Only arch dependant part of normal.mod will be here. Common part for -# all architecures of normal.mod is at start and should be kept at sync -# with other makefiles. -# -# Please put arch dependant part of normal.mod at the end of list to -# keep it simpler to update to different architectures. -# -normal_mod_SOURCES = lib/arg.c normal/cmdline.c normal/command.c \ - normal/datetime.c normal/completion.c normal/execute.c \ - normal/function.c normal/lexer.c normal/main.c normal/menu.c \ - normal/handler.c normal/menu_text.c \ - normal/color.c \ - normal/menu_viewer.c normal/menu_entry.c \ - normal/misc.c grub_script.tab.c \ - normal/script.c \ - normal/sparc64/setjmp.S -normal_mod_CFLAGS = $(COMMON_CFLAGS) -normal_mod_ASFLAGS = $(COMMON_ASFLAGS) -normal_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For reboot.mod. reboot_mod_SOURCES = commands/reboot.c reboot_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk index d7ad9a4c8..6cf9d7d79 100644 --- a/conf/x86_64-efi.rmk +++ b/conf/x86_64-efi.rmk @@ -5,10 +5,7 @@ COMMON_CFLAGS = -fno-builtin -m64 COMMON_LDFLAGS = -melf_x86_64 -nostdlib # Used by various components. These rules need to precede them. -normal/execute.c_DEPENDENCIES = grub_script.tab.h -normal/command.c_DEPENDENCIES = grub_script.tab.h -normal/function.c_DEPENDENCIES = grub_script.tab.h -normal/lexer.c_DEPENDENCIES = grub_script.tab.h +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Utilities. bin_UTILITIES = grub-mkimage @@ -81,7 +78,7 @@ sbin_SCRIPTS = grub-install grub_install_SOURCES = util/i386/efi/grub-install.in # Modules. -pkglib_MODULES = kernel.mod normal.mod chain.mod appleldr.mod \ +pkglib_MODULES = kernel.mod chain.mod appleldr.mod \ halt.mod reboot.mod linux.mod pci.mod lspci.mod \ datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod @@ -90,7 +87,8 @@ kernel_mod_EXPORTS = no kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/rescue.c kern/term.c \ + kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/rescue_parser.c kern/rescue_reader.c \ kern/x86_64/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ @@ -99,7 +97,7 @@ kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \ term/efi/console.c disk/efi/efidisk.c kernel_mod_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ - partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \ + partition.h pc_partition.h reader.h symbol.h term.h time.h types.h \ efi/efi.h efi/time.h efi/disk.h machine/loader.h list.h handler.h \ command.h kernel_mod_CFLAGS = $(COMMON_CFLAGS) @@ -116,27 +114,6 @@ symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist. kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1) -# -# Only arch dependant part of normal.mod will be here. Common part for -# all architecures of normal.mod is at start and should be kept at sync -# with other makefiles. -# -# Please put arch dependant part of normal.mod at the end of list to -# keep it simpler to update to different architectures. -# -normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/handler.c \ - normal/completion.c normal/datetime.c normal/execute.c \ - normal/function.c normal/lexer.c normal/main.c normal/menu.c \ - normal/menu_text.c \ - normal/color.c \ - normal/menu_viewer.c normal/menu_entry.c \ - normal/misc.c grub_script.tab.c \ - normal/script.c \ - normal/x86_64/setjmp.S -normal_mod_CFLAGS = $(COMMON_CFLAGS) -normal_mod_ASFLAGS = $(COMMON_ASFLAGS) -normal_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For chain.mod. chain_mod_SOURCES = loader/efi/chainloader.c chain_mod_CFLAGS = $(COMMON_CFLAGS) @@ -197,5 +174,4 @@ fixvideo_mod_SOURCES = commands/efi/fixvideo.c fixvideo_mod_CFLAGS = $(COMMON_CFLAGS) fixvideo_mod_LDFLAGS = $(COMMON_LDFLAGS) -include $(srcdir)/conf/i386.mk include $(srcdir)/conf/common.mk diff --git a/include/grub/command.h b/include/grub/command.h index 18f2934fa..a391cf2a9 100644 --- a/include/grub/command.h +++ b/include/grub/command.h @@ -106,6 +106,15 @@ grub_command_find (const char *name) return grub_named_list_find (GRUB_AS_NAMED_LIST (grub_command_list), name); } +static inline grub_err_t +grub_command_execute (const char *name, int argc, char **argv) +{ + grub_command_t cmd; + + cmd = grub_command_find (name); + return (cmd) ? cmd->func (cmd, argc, argv) : GRUB_ERR_FILE_NOT_FOUND; +} + static inline int grub_command_iterate (int (*func) (grub_command_t)) { diff --git a/include/grub/menu.h b/include/grub/menu.h index 6850846b4..f11e00516 100644 --- a/include/grub/menu.h +++ b/include/grub/menu.h @@ -38,9 +38,6 @@ struct grub_menu_entry E.classes->next is the first class if it is not NULL. */ struct grub_menu_entry_class *classes; - /* The commands associated with this menu entry. */ - struct grub_script *commands; - /* The sourcecode of the menu entry, used by the editor. */ const char *sourcecode; diff --git a/include/grub/normal.h b/include/grub/normal.h index e62e43379..948289aa6 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -20,7 +20,6 @@ #ifndef GRUB_NORMAL_HEADER #define GRUB_NORMAL_HEADER 1 -#include #include #include #include @@ -42,17 +41,6 @@ enum grub_completion_type }; typedef enum grub_completion_type grub_completion_type_t; -/* This is used to store the names of filesystem modules for auto-loading. */ -struct grub_fs_module_list -{ - char *name; - struct grub_fs_module_list *next; -}; -typedef struct grub_fs_module_list *grub_fs_module_list_t; - -/* To exit from the normal mode. */ -extern grub_jmp_buf grub_exit_env; - extern struct grub_menu_viewer grub_normal_text_menu_viewer; /* Callback structure menu viewers can use to provide user feedback when @@ -86,19 +74,14 @@ void grub_menu_execute_entry(grub_menu_entry_t entry); grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no); int grub_menu_get_timeout (void); void grub_menu_set_timeout (int timeout); -void grub_cmdline_run (int nested); int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, int echo_char, int readline); grub_err_t grub_set_history (int newsize); -int grub_command_execute (char *cmdline, int interactive); void grub_normal_init_page (void); void grub_menu_init_page (int nested, int edit); char *grub_normal_do_completion (char *buf, int *restore, void (*hook) (const char *item, grub_completion_type_t type, int count)); grub_err_t grub_normal_print_device_info (const char *name); -grub_err_t grub_normal_menu_addentry (int argc, const char **args, - struct grub_script *script, - const char *sourcecode); char *grub_env_write_color_normal (struct grub_env_var *var, const char *val); char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val); void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name); @@ -107,6 +90,11 @@ void grub_wait_after_message (void); char *grub_file_getline (grub_file_t file); void read_handler_list (void); void free_handler_list (void); +void read_command_list (void); +void read_fs_list (void); +void grub_cmdline_run (int nested); +grub_err_t grub_menu_addentry (int argc, const char **args, + const char *sourcecode); #ifdef GRUB_UTIL void grub_normal_init (void); diff --git a/include/grub/parser.h b/include/grub/parser.h index 1a7f0a361..4ee0e8389 100644 --- a/include/grub/parser.h +++ b/include/grub/parser.h @@ -1,7 +1,7 @@ /* parser.h - prototypes for the command line parser. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007 Free Software Foundation, Inc. + * Copyright (C) 2005,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 @@ -22,6 +22,7 @@ #include #include +#include /* All the states for the command line. */ typedef enum @@ -61,7 +62,56 @@ EXPORT_FUNC (grub_parser_cmdline_state) (grub_parser_state_t state, grub_err_t EXPORT_FUNC (grub_parser_split_cmdline) (const char *cmdline, - grub_err_t (*getline) (char **), + grub_reader_getline_t getline, int *argc, char ***argv); +struct grub_parser +{ + /* The next parser. */ + struct grub_parser *next; + + /* The parser name. */ + const char *name; + + /* Initialize the parser. */ + grub_err_t (*init) (void); + + /* Clean up the parser. */ + grub_err_t (*fini) (void); + + grub_err_t (*parse_line) (char *line, grub_reader_getline_t getline); +}; +typedef struct grub_parser *grub_parser_t; + +extern struct grub_handler_class EXPORT_VAR(grub_parser_class); +grub_err_t EXPORT_FUNC(grub_parser_execute) (char *source); + +static inline void +grub_parser_register (const char *name __attribute__ ((unused)), + grub_parser_t parser) +{ + grub_handler_register (&grub_parser_class, GRUB_AS_HANDLER (parser)); +} + +static inline void +grub_parser_unregister (grub_parser_t parser) +{ + grub_handler_unregister (&grub_parser_class, GRUB_AS_HANDLER (parser)); +} + +static inline grub_parser_t +grub_parser_get_current (void) +{ + return (grub_parser_t) grub_parser_class.cur_handler; +} + +static inline grub_err_t +grub_parser_set_current (grub_parser_t parser) +{ + return grub_handler_set_current (&grub_parser_class, + GRUB_AS_HANDLER (parser)); +} + +void grub_register_rescue_parser (void); + #endif /* ! GRUB_PARSER_HEADER */ diff --git a/include/grub/reader.h b/include/grub/reader.h new file mode 100644 index 000000000..c7e67bf5e --- /dev/null +++ b/include/grub/reader.h @@ -0,0 +1,79 @@ +/* reader.h - prototypes for command line reader. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#ifndef GRUB_READER_HEADER +#define GRUB_READER_HEADER 1 + +#include +#include +#include + +typedef grub_err_t (*grub_reader_getline_t) (char **, int); + +struct grub_reader +{ + /* The next reader. */ + struct grub_parser *next; + + /* The reader name. */ + const char *name; + + /* Initialize the reader. */ + grub_err_t (*init) (void); + + /* Clean up the reader. */ + grub_err_t (*fini) (void); + + grub_reader_getline_t read_line; +}; +typedef struct grub_reader *grub_reader_t; + +extern struct grub_handler_class EXPORT_VAR(grub_reader_class); + +grub_err_t EXPORT_FUNC(grub_reader_loop) (grub_reader_getline_t getline); + +static inline void +grub_reader_register (const char *name __attribute__ ((unused)), + grub_reader_t reader) +{ + grub_handler_register (&grub_reader_class, GRUB_AS_HANDLER (reader)); +} + +static inline void +grub_reader_unregister (grub_reader_t reader) +{ + grub_handler_unregister (&grub_reader_class, GRUB_AS_HANDLER (reader)); +} + +static inline grub_reader_t +grub_reader_get_current (void) +{ + return (grub_reader_t) grub_reader_class.cur_handler; +} + +static inline grub_err_t +grub_reader_set_current (grub_reader_t reader) +{ + return grub_handler_set_current (&grub_reader_class, + GRUB_AS_HANDLER (reader)); +} + +void grub_register_rescue_reader (void); + +#endif /* ! GRUB_READER_HEADER */ diff --git a/include/grub/rescue.h b/include/grub/rescue.h deleted file mode 100644 index d02c83ece..000000000 --- a/include/grub/rescue.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,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 . - */ - -#ifndef GRUB_RESCUE_HEADER -#define GRUB_RESCUE_HEADER 1 - -#include - -/* Enter rescue mode. */ -void grub_enter_rescue_mode (void); - -#endif /* ! GRUB_RESCUE_HEADER */ diff --git a/include/grub/script.h b/include/grub/script_sh.h similarity index 96% rename from include/grub/script.h rename to include/grub/script_sh.h index 4d18b9266..188068141 100644 --- a/include/grub/script.h +++ b/include/grub/script_sh.h @@ -1,4 +1,4 @@ -/* script.h */ +/* normal_parser.h */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2005,2007,2009 Free Software Foundation, Inc. @@ -17,8 +17,8 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_SCRIPT_HEADER -#define GRUB_SCRIPT_HEADER 1 +#ifndef GRUB_NORMAL_PARSER_HEADER +#define GRUB_NORMAL_PARSER_HEADER 1 #include #include @@ -134,7 +134,7 @@ struct grub_lexer_param /* Function used by the lexer to get a new line when more input is expected, but not available. */ - grub_err_t (*getline) (char **); + grub_reader_getline_t getline; /* A reference counter. If this is >0 it means that the parser expects more tokens and `getline' should be called to fetch more. @@ -156,7 +156,7 @@ struct grub_lexer_param /* Points to the recording. */ char *recording; - /* index in the RECORDING. */ + /* index in the RECORDING. */ int recordpos; /* Size of RECORDING. */ @@ -218,13 +218,13 @@ grub_script_arg_add (struct grub_parser_param *state, grub_script_arg_type_t type, char *str); struct grub_script *grub_script_parse (char *script, - grub_err_t (*getline) (char **)); + grub_reader_getline_t getline); void grub_script_free (struct grub_script *script); struct grub_script *grub_script_create (struct grub_script_cmd *cmd, struct grub_script_mem *mem); struct grub_lexer_param *grub_script_lexer_init (char *s, - grub_err_t (*getline) (char **)); + grub_reader_getline_t getline); void grub_script_lexer_ref (struct grub_lexer_param *); void grub_script_lexer_deref (struct grub_lexer_param *); void grub_script_lexer_record_start (struct grub_lexer_param *); @@ -232,7 +232,7 @@ char *grub_script_lexer_record_stop (struct grub_lexer_param *); /* Functions to track allocated memory. */ struct grub_script_mem *grub_script_mem_record (struct grub_parser_param *state); -struct grub_script_mem *grub_script_mem_record_stop (struct grub_parser_param *state, +struct grub_script_mem *grub_script_mem_record_stop (struct grub_parser_param *state, struct grub_script_mem *restore); void *grub_script_malloc (struct grub_parser_param *state, grub_size_t size); @@ -284,4 +284,4 @@ int grub_script_function_iterate (int (*iterate) (grub_script_function_t)); int grub_script_function_call (grub_script_function_t func, int argc, char **args); -#endif /* ! GRUB_SCRIPT_HEADER */ +#endif /* ! GRUB_NORMAL_PARSER_HEADER */ diff --git a/kern/main.c b/kern/main.c index 40300b24d..1d88b60f6 100644 --- a/kern/main.c +++ b/kern/main.c @@ -22,11 +22,13 @@ #include #include #include -#include #include #include #include #include +#include +#include +#include void grub_module_iterate (int (*hook) (struct grub_module_header *header)) @@ -120,6 +122,9 @@ grub_load_normal_mode (void) /* Something went wrong. Print errors here to let user know why we're entering rescue mode. */ grub_print_error (); + grub_errno = 0; + + grub_command_execute ("normal", 0, 0); } /* The main routine. */ @@ -144,9 +149,10 @@ grub_main (void) grub_env_export ("prefix"); grub_set_root_dev (); - /* Load the normal mode module. */ - grub_load_normal_mode (); + grub_register_core_commands (); + grub_register_rescue_parser (); + grub_register_rescue_reader (); - /* Enter the rescue mode. */ - grub_enter_rescue_mode (); + grub_load_normal_mode (); + grub_reader_loop (0); } diff --git a/kern/parser.c b/kern/parser.c index e93185334..685ab2250 100644 --- a/kern/parser.c +++ b/kern/parser.c @@ -1,7 +1,7 @@ /* parser.c - the part of the parser that can return partial tokens */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007 Free Software Foundation, Inc. + * Copyright (C) 2005,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 @@ -100,7 +100,7 @@ grub_parser_cmdline_state (grub_parser_state_t state, char c, char *result) grub_err_t -grub_parser_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **), +grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, int *argc, char ***argv) { grub_parser_state_t state = GRUB_PARSER_STATE_TEXT; @@ -152,7 +152,7 @@ grub_parser_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **), if (! *rd) { if (getline) - getline (&rd); + getline (&rd, 1); else break; } @@ -227,3 +227,45 @@ grub_parser_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **), return 0; } + +struct grub_handler_class grub_parser_class = + { + .name = "parser" + }; + +grub_err_t +grub_parser_execute (char *source) +{ + auto grub_err_t getline (char **line, int cont); + grub_err_t getline (char **line, int cont __attribute__ ((unused))) + { + char *p; + + if (! source) + { + *line = 0; + return 0; + } + + p = grub_strchr (source, '\n'); + if (p) + *(p++) = 0; + + *line = grub_strdup (source); + source = p; + return 0; + } + + while (source) + { + char *line; + grub_parser_t parser; + + getline (&line, 0); + parser = grub_parser_get_current (); + parser->parse_line (line, getline); + grub_free (line); + } + + return grub_errno; +} diff --git a/kern/reader.c b/kern/reader.c new file mode 100644 index 000000000..271a90f5a --- /dev/null +++ b/kern/reader.c @@ -0,0 +1,49 @@ +/* reader.c - reader support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#include +#include +#include +#include + +struct grub_handler_class grub_reader_class = + { + .name = "reader" + }; + +grub_err_t +grub_reader_loop (grub_reader_getline_t getline) +{ + while (1) + { + char *line; + grub_reader_getline_t func; + + /* Print an error, if any. */ + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + + func = (getline) ? : grub_reader_get_current ()->read_line; + if ((func (&line, 0)) || (! line)) + return grub_errno; + + grub_parser_get_current ()->parse_line (line, func); + grub_free (line); + } +} diff --git a/kern/rescue.c b/kern/rescue.c deleted file mode 100644 index 69a5db90e..000000000 --- a/kern/rescue.c +++ /dev/null @@ -1,163 +0,0 @@ -/* rescue.c - rescue mode */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2005,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 . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GRUB_RESCUE_BUF_SIZE 256 -#define GRUB_RESCUE_MAX_ARGS 20 - -static char linebuf[GRUB_RESCUE_BUF_SIZE]; - -/* Prompt to input a command and read the line. */ -static void -grub_rescue_get_command_line (const char *prompt) -{ - int c; - int pos = 0; - - grub_printf (prompt); - grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE); - - while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r') - { - if (grub_isprint (c)) - { - if (pos < GRUB_RESCUE_BUF_SIZE - 1) - { - linebuf[pos++] = c; - grub_putchar (c); - } - } - else if (c == '\b') - { - if (pos > 0) - { - linebuf[--pos] = 0; - grub_putchar (c); - grub_putchar (' '); - grub_putchar (c); - } - } - grub_refresh (); - } - - grub_putchar ('\n'); - grub_refresh (); -} - -static void -attempt_normal_mode (void) -{ - grub_command_t cmd; - - cmd = grub_command_find ("normal"); - if (cmd) - (cmd->func) (cmd, 0, 0); -} - -/* Enter the rescue mode. */ -void -grub_enter_rescue_mode (void) -{ - auto grub_err_t getline (char **line); - - grub_err_t getline (char **line) - { - grub_rescue_get_command_line ("> "); - *line = linebuf; - return 0; - } - - grub_register_core_commands (); - - /* First of all, attempt to execute the normal mode. */ - attempt_normal_mode (); - - grub_printf ("Entering rescue mode...\n"); - - while (1) - { - char *line = linebuf; - char *name; - int n; - grub_command_t cmd; - char **args; - - /* Print an error, if any. */ - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - - /* Get a command line. */ - grub_rescue_get_command_line ("grub rescue> "); - if (line[0] == 0) - continue; - - if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0) - continue; - - /* In case of an assignment set the environment accordingly - instead of calling a function. */ - if (n == 0 && grub_strchr (line, '=')) - { - char *val = grub_strchr (args[0], '='); - val[0] = 0; - grub_env_set (args[0], val + 1); - val[0] = '='; - grub_free (args[0]); - continue; - } - - /* Get the command name. */ - name = args[0]; - - /* If nothing is specified, restart. */ - if (*name == '\0') - { - grub_free (args[0]); - continue; - } - - cmd = grub_command_find (name); - if (cmd) - { - (cmd->func) (cmd, n, &args[1]); - } - else - { - grub_printf ("Unknown command `%s'\n", name); - grub_printf ("Try `help' for usage\n"); - } - - grub_free (args[0]); - } -} diff --git a/kern/rescue_parser.c b/kern/rescue_parser.c new file mode 100644 index 000000000..79f32b8fd --- /dev/null +++ b/kern/rescue_parser.c @@ -0,0 +1,84 @@ +/* rescue_parser.c - rescue mode parser */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#include +#include +#include +#include +#include +#include + +static grub_err_t +grub_rescue_parse_line (char *line, grub_reader_getline_t getline) +{ + char *name; + int n; + grub_command_t cmd; + char **args; + + if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0) + return grub_errno; + + /* In case of an assignment set the environment accordingly + instead of calling a function. */ + if (n == 0 && grub_strchr (line, '=')) + { + char *val = grub_strchr (args[0], '='); + val[0] = 0; + grub_env_set (args[0], val + 1); + val[0] = '='; + goto quit; + } + + /* Get the command name. */ + name = args[0]; + + /* If nothing is specified, restart. */ + if (*name == '\0') + goto quit; + + cmd = grub_command_find (name); + if (cmd) + { + (cmd->func) (cmd, n, &args[1]); + } + else + { + grub_printf ("Unknown command `%s'\n", name); + grub_printf ("Try `help' for usage\n"); + } + + quit: + grub_free (args[0]); + grub_free (args); + + return grub_errno; +} + +static struct grub_parser grub_rescue_parser = + { + .name = "rescue", + .parse_line = grub_rescue_parse_line + }; + +void +grub_register_rescue_parser (void) +{ + grub_parser_register ("rescue", &grub_rescue_parser); +} diff --git a/kern/rescue_reader.c b/kern/rescue_reader.c new file mode 100644 index 000000000..2a06f3fc2 --- /dev/null +++ b/kern/rescue_reader.c @@ -0,0 +1,88 @@ +/* rescue_reader.c - rescue mode reader */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#include +#include +#include +#include + +#define GRUB_RESCUE_BUF_SIZE 256 + +static char linebuf[GRUB_RESCUE_BUF_SIZE]; + +static grub_err_t +grub_rescue_init (void) +{ + grub_printf ("Entering rescue mode...\n"); + return 0; +} + +/* Prompt to input a command and read the line. */ +static grub_err_t +grub_rescue_read_line (char **line, int cont) +{ + int c; + int pos = 0; + + grub_printf ((cont) ? "> " : "grub rescue> "); + grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE); + + while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r') + { + if (grub_isprint (c)) + { + if (pos < GRUB_RESCUE_BUF_SIZE - 1) + { + linebuf[pos++] = c; + grub_putchar (c); + } + } + else if (c == '\b') + { + if (pos > 0) + { + linebuf[--pos] = 0; + grub_putchar (c); + grub_putchar (' '); + grub_putchar (c); + } + } + grub_refresh (); + } + + grub_putchar ('\n'); + grub_refresh (); + + *line = grub_strdup (linebuf); + + return 0; +} + +static struct grub_reader grub_rescue_reader = + { + .name = "rescue", + .init = grub_rescue_init, + .read_line = grub_rescue_read_line + }; + +void +grub_register_rescue_reader (void) +{ + grub_reader_register ("rescue", &grub_rescue_reader); +} diff --git a/loader/i386/multiboot.c b/loader/i386/multiboot.c index 27042a50d..2f7e1e403 100644 --- a/loader/i386/multiboot.c +++ b/loader/i386/multiboot.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/loader/multiboot2.c b/loader/multiboot2.c index 2fb56bfdf..fd8282849 100644 --- a/loader/multiboot2.c +++ b/loader/multiboot2.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/loader/sparc64/ieee1275/linux.c b/loader/sparc64/ieee1275/linux.c index 4f5b3cee8..86e532f7f 100644 --- a/loader/sparc64/ieee1275/linux.c +++ b/loader/sparc64/ieee1275/linux.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/normal/autofs.c b/normal/autofs.c new file mode 100644 index 000000000..39f2f9ddc --- /dev/null +++ b/normal/autofs.c @@ -0,0 +1,134 @@ +/* autofs.c - support auto-loading from fs.lst */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#include +#include +#include +#include +#include +#include + +/* This is used to store the names of filesystem modules for auto-loading. */ +struct grub_fs_module_list +{ + char *name; + struct grub_fs_module_list *next; +}; +typedef struct grub_fs_module_list *grub_fs_module_list_t; + +static grub_fs_module_list_t fs_module_list = 0; + +/* The auto-loading hook for filesystems. */ +static int +autoload_fs_module (void) +{ + grub_fs_module_list_t p; + + while ((p = fs_module_list) != 0) + { + if (! grub_dl_get (p->name) && grub_dl_load (p->name)) + return 1; + + fs_module_list = p->next; + grub_free (p->name); + grub_free (p); + } + + return 0; +} + +/* Read the file fs.lst for auto-loading. */ +void +read_fs_list (void) +{ + const char *prefix; + static int first_time = 1; + + /* Make sure that this function does not get executed twice. */ + if (! first_time) + return; + first_time = 0; + + prefix = grub_env_get ("prefix"); + if (prefix) + { + char *filename; + + filename = grub_malloc (grub_strlen (prefix) + sizeof ("/fs.lst")); + if (filename) + { + grub_file_t file; + + grub_sprintf (filename, "%s/fs.lst", prefix); + file = grub_file_open (filename); + if (file) + { + while (1) + { + char *buf; + char *p; + char *q; + grub_fs_module_list_t fs_mod; + + buf = grub_file_getline (file); + if (! buf) + break; + + p = buf; + q = buf + grub_strlen (buf) - 1; + + /* Ignore space. */ + while (grub_isspace (*p)) + p++; + + while (p < q && grub_isspace (*q)) + *q-- = '\0'; + + /* If the line is empty, skip it. */ + if (p >= q) + continue; + + fs_mod = grub_malloc (sizeof (*fs_mod)); + if (! fs_mod) + continue; + + fs_mod->name = grub_strdup (p); + if (! fs_mod->name) + { + grub_free (fs_mod); + continue; + } + + fs_mod->next = fs_module_list; + fs_module_list = fs_mod; + } + + grub_file_close (file); + } + + grub_free (filename); + } + } + + /* Ignore errors. */ + grub_errno = GRUB_ERR_NONE; + + /* Set the hook. */ + grub_fs_autoload_hook = autoload_fs_module; +} diff --git a/normal/cmdline.c b/normal/cmdline.c index 8ca83f6bb..4ef8890fb 100644 --- a/normal/cmdline.c +++ b/normal/cmdline.c @@ -132,37 +132,6 @@ grub_history_replace (int pos, char *s) hist_lines[pos] = grub_strdup (s); } -void -grub_cmdline_run (int nested) -{ - grub_normal_init_page (); - grub_setcursor (1); - - grub_printf ("\ - [ Minimal BASH-like line editing is supported. For the first word, TAB\n\ - lists possible command completions. Anywhere else TAB lists possible\n\ - device/file completions.%s ]\n\n", - nested ? " ESC at any time exits." : ""); - - while (1) - { - static char cmdline[GRUB_MAX_CMDLINE]; - - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - cmdline[0] = '\0'; - - if (! grub_cmdline_get ("grub> ", cmdline, sizeof (cmdline), 0, 1) - && nested) - return; - - if (! *cmdline) - continue; - - grub_command_execute (cmdline, 1); - } -} - /* A completion hook to print items. */ static void print_completion (const char *item, grub_completion_type_t type, int count) diff --git a/normal/dyncmd.c b/normal/dyncmd.c new file mode 100644 index 000000000..154da6114 --- /dev/null +++ b/normal/dyncmd.c @@ -0,0 +1,158 @@ +/* dyncmd.c - support dynamic command */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#include +#include +#include +#include +#include +#include + +static grub_err_t +grub_dyncmd_dispatcher (struct grub_command *cmd, + int argc, char **args) +{ + char *modname = cmd->data; + grub_dl_t mod; + grub_err_t ret; + + mod = grub_dl_load (modname); + if (mod) + { + char *name; + + grub_free (modname); + grub_dl_ref (mod); + + name = (char *) cmd->name; + grub_unregister_command (cmd); + + cmd = grub_command_find (name); + if (cmd) + ret = (cmd->func) (cmd, argc, args); + else + ret = grub_errno; + + grub_free (name); + } + else + ret = grub_errno; + + return ret; +} + +/* Read the file command.lst for auto-loading. */ +void +read_command_list (void) +{ + const char *prefix; + static int first_time = 1; + + /* Make sure that this function does not get executed twice. */ + if (! first_time) + return; + first_time = 0; + + prefix = grub_env_get ("prefix"); + if (prefix) + { + char *filename; + + filename = grub_malloc (grub_strlen (prefix) + sizeof ("/command.lst")); + if (filename) + { + grub_file_t file; + + grub_sprintf (filename, "%s/command.lst", prefix); + file = grub_file_open (filename); + if (file) + { + char *buf = 0; + for (;; grub_free(buf)) + { + char *p, *name, *modname; + grub_command_t cmd; + int prio = 0; + + buf = grub_file_getline (file); + + if (! buf) + break; + + name = buf; + if (*name == '*') + { + name++; + prio++; + } + + if (! grub_isgraph (name[0])) + continue; + + p = grub_strchr (name, ':'); + if (! p) + continue; + + *p = '\0'; + while (*++p == ' ') + ; + + if (! grub_isgraph (*p)) + continue; + + if (grub_dl_get (p)) + continue; + + name = grub_strdup (name); + if (! name) + continue; + + modname = grub_strdup (p); + if (! modname) + { + grub_free (name); + continue; + } + + cmd = grub_register_command_prio (name, + grub_dyncmd_dispatcher, + 0, "not loaded", prio); + if (! cmd) + { + grub_free (name); + grub_free (modname); + continue; + } + cmd->flags |= GRUB_COMMAND_FLAG_DYNCMD; + cmd->data = modname; + + /* Update the active flag. */ + grub_command_find (name); + } + + grub_file_close (file); + } + + grub_free (filename); + } + } + + /* Ignore errors. */ + grub_errno = GRUB_ERR_NONE; +} diff --git a/normal/main.c b/normal/main.c index 1a50d9553..1c2eff4df 100644 --- a/normal/main.c +++ b/normal/main.c @@ -20,20 +20,15 @@ #include #include #include -#include #include #include #include #include #include #include -#include +#include #include -grub_jmp_buf grub_exit_env; - -static grub_fs_module_list_t fs_module_list = 0; - #define GRUB_DEFAULT_HISTORY_SIZE 50 /* Read a line from the file FILE. */ @@ -43,7 +38,6 @@ grub_file_getline (grub_file_t file) char c; int pos = 0; int literal = 0; - int comment = 0; char *cmdline; int max_len = 64; @@ -84,16 +78,9 @@ grub_file_getline (grub_file_t file) if (c == '\\') literal = 1; - if (comment) + if (pos == 0) { - if (c == '\n') - comment = 0; - } - else if (pos == 0) - { - if (c == '#') - comment = 1; - else if (! grub_isspace (c)) + if (! grub_isspace (c)) cmdline[pos++] = c; } else @@ -138,7 +125,6 @@ free_menu (grub_menu_t menu) { grub_menu_entry_t next_entry = entry->next; - grub_script_free (entry->commands); grub_free ((void *) entry->title); grub_free ((void *) entry->sourcecode); entry = next_entry; @@ -164,8 +150,8 @@ free_menu_entry_classes (struct grub_menu_entry_class *head) } grub_err_t -grub_normal_menu_addentry (int argc, const char **args, - struct grub_script *script, const char *sourcecode) +grub_menu_addentry (int argc, const char **args, + const char *sourcecode) { const char *menutitle = 0; const char *menusourcecode; @@ -237,7 +223,7 @@ grub_normal_menu_addentry (int argc, const char **args, /* Handle invalid argument. */ failed = 1; grub_error (GRUB_ERR_MENU, - "invalid argument for menuentry: %s", args[i]); + "invalid argument for menuentry: %s", args[i]); break; } } @@ -251,7 +237,7 @@ grub_normal_menu_addentry (int argc, const char **args, { failed = 1; grub_error (GRUB_ERR_MENU, - "too many titles for menuentry: %s", args[i]); + "too many titles for menuentry: %s", args[i]); break; } } @@ -287,7 +273,6 @@ grub_normal_menu_addentry (int argc, const char **args, return grub_errno; } - (*last)->commands = script; (*last)->title = menutitle; (*last)->classes = classes_head; (*last)->next = 0; @@ -299,20 +284,56 @@ grub_normal_menu_addentry (int argc, const char **args, } static grub_menu_t -read_config_file (const char *config, int nested) +read_config_file (const char *config) { grub_file_t file; - auto grub_err_t getline (char **line); - int currline = 0; - int errors = 0; + grub_parser_t old_parser = 0; - grub_err_t getline (char **line) + auto grub_err_t getline (char **line, int cont); + grub_err_t getline (char **line, int cont __attribute__ ((unused))) { - currline++; + while (1) + { + char *buf; - *line = grub_file_getline (file); - if (! *line) - return grub_errno; + *line = buf = grub_file_getline (file); + if (! buf) + return grub_errno; + + if (buf[0] == '#') + { + if (buf[1] == '!') + { + grub_parser_t parser; + grub_named_list_t list; + + buf += 2; + while (grub_isspace (*buf)) + buf++; + + if (! old_parser) + old_parser = grub_parser_get_current (); + + list = GRUB_AS_NAMED_LIST (grub_parser_class.handler_list); + parser = grub_named_list_find (list, buf); + if (parser) + grub_parser_set_current (parser); + else + { + char cmd_name[8 + grub_strlen (buf)]; + + /* Perhaps it's not loaded yet, try the autoload + command. */ + grub_strcpy (cmd_name, "parser."); + grub_strcat (cmd_name, buf); + grub_command_execute (cmd_name, 0, 0); + } + } + grub_free (*line); + } + else + break; + } return GRUB_ERR_NONE; } @@ -320,14 +341,15 @@ read_config_file (const char *config, int nested) grub_menu_t newmenu; newmenu = grub_env_get_data_slot ("menu"); - - if (nested || ! newmenu) + if (! newmenu) { newmenu = grub_malloc (sizeof (*newmenu)); if (! newmenu) return 0; newmenu->size = 0; newmenu->entry_list = 0; + + grub_env_set_data_slot ("menu", newmenu); } /* Try to open the config file. */ @@ -335,58 +357,15 @@ read_config_file (const char *config, int nested) if (! file) return 0; - grub_env_set_data_slot ("menu", newmenu); - - while (1) - { - struct grub_script *parsed_script; - int startline; - char *cmdline; - - cmdline = grub_file_getline (file); - if (!cmdline) - break; - - startline = ++currline; - - /* Execute the script, line for line. */ - parsed_script = grub_script_parse (cmdline, getline); - - grub_free (cmdline); - - if (! parsed_script) - { - grub_printf ("(line %d-%d)\n", startline, currline); - errors++; - continue; - } - - /* Execute the command(s). */ - grub_script_execute (parsed_script); - - /* Ignore errors. */ - grub_errno = GRUB_ERR_NONE; - - /* The parsed script was executed, throw it away. */ - grub_script_free (parsed_script); - } - + grub_reader_loop (getline); grub_file_close (file); - if (errors > 0) - grub_wait_after_message (); + if (old_parser) + grub_parser_set_current (old_parser); return newmenu; } -/* This starts the normal mode. */ -void -grub_enter_normal_mode (const char *config) -{ - if (grub_setjmp (grub_exit_env) == 0) - grub_normal_execute (config, 0, 0); -} - /* Initialize the screen. */ void grub_normal_init_page (void) @@ -409,237 +388,7 @@ grub_normal_init_page (void) #undef TITLE } -static grub_err_t -grub_dyncmd_dispatcher (struct grub_command *cmd, - int argc, char **args) -{ - char *modname = cmd->data; - grub_dl_t mod; - grub_err_t ret; - - mod = grub_dl_load (modname); - if (mod) - { - char *name; - - grub_free (modname); - grub_dl_ref (mod); - - name = (char *) cmd->name; - grub_unregister_command (cmd); - - cmd = grub_command_find (name); - if (cmd) - ret = (cmd->func) (cmd, argc, args); - else - ret = grub_errno; - - grub_free (name); - } - else - ret = grub_errno; - - return ret; -} - -/* Read the file command.lst for auto-loading. */ -static void -read_command_list (void) -{ - const char *prefix; - static int first_time = 1; - - /* Make sure that this function does not get executed twice. */ - if (! first_time) - return; - first_time = 0; - - prefix = grub_env_get ("prefix"); - if (prefix) - { - char *filename; - - filename = grub_malloc (grub_strlen (prefix) + sizeof ("/command.lst")); - if (filename) - { - grub_file_t file; - - grub_sprintf (filename, "%s/command.lst", prefix); - file = grub_file_open (filename); - if (file) - { - char *buf = 0; - for (;; grub_free(buf)) - { - char *p, *name, *modname; - grub_command_t cmd; - int prio = 0; - - buf = grub_file_getline (file); - - if (! buf) - break; - - name = buf; - if (*name == '*') - { - name++; - prio++; - } - - if (! grub_isgraph (name[0])) - continue; - - p = grub_strchr (name, ':'); - if (! p) - continue; - - *p = '\0'; - while (*++p == ' ') - ; - - if (! grub_isgraph (*p)) - continue; - - if (grub_dl_get (p)) - continue; - - name = grub_strdup (name); - if (! name) - continue; - - modname = grub_strdup (p); - if (! modname) - { - grub_free (name); - continue; - } - - cmd = grub_register_command_prio (name, - grub_dyncmd_dispatcher, - 0, "not loaded", prio); - if (! cmd) - { - grub_free (name); - grub_free (modname); - continue; - } - cmd->flags |= GRUB_COMMAND_FLAG_DYNCMD; - cmd->data = modname; - - /* Update the active flag. */ - grub_command_find (name); - } - - grub_file_close (file); - } - - grub_free (filename); - } - } - - /* Ignore errors. */ - grub_errno = GRUB_ERR_NONE; -} - -/* The auto-loading hook for filesystems. */ -static int -autoload_fs_module (void) -{ - grub_fs_module_list_t p; - - while ((p = fs_module_list) != 0) - { - if (! grub_dl_get (p->name) && grub_dl_load (p->name)) - return 1; - - fs_module_list = p->next; - grub_free (p->name); - grub_free (p); - } - - return 0; -} - -/* Read the file fs.lst for auto-loading. */ -static void -read_fs_list (void) -{ - const char *prefix; - static int first_time = 1; - - /* Make sure that this function does not get executed twice. */ - if (! first_time) - return; - first_time = 0; - - prefix = grub_env_get ("prefix"); - if (prefix) - { - char *filename; - - filename = grub_malloc (grub_strlen (prefix) + sizeof ("/fs.lst")); - if (filename) - { - grub_file_t file; - - grub_sprintf (filename, "%s/fs.lst", prefix); - file = grub_file_open (filename); - if (file) - { - while (1) - { - char *buf; - char *p; - char *q; - grub_fs_module_list_t fs_mod; - - buf = grub_file_getline (file); - if (! buf) - break; - - p = buf; - q = buf + grub_strlen (buf) - 1; - - /* Ignore space. */ - while (grub_isspace (*p)) - p++; - - while (p < q && grub_isspace (*q)) - *q-- = '\0'; - - /* If the line is empty, skip it. */ - if (p >= q) - continue; - - fs_mod = grub_malloc (sizeof (*fs_mod)); - if (! fs_mod) - continue; - - fs_mod->name = grub_strdup (p); - if (! fs_mod->name) - { - grub_free (fs_mod); - continue; - } - - fs_mod->next = fs_module_list; - fs_module_list = fs_mod; - } - - grub_file_close (file); - } - - grub_free (filename); - } - } - - /* Ignore errors. */ - grub_errno = GRUB_ERR_NONE; - - /* Set the hook. */ - grub_fs_autoload_hook = autoload_fs_module; -} +static int reader_nested; /* Read the config file COFIG, and execute the menu interface or the command-line interface if BATCH is false. */ @@ -651,10 +400,13 @@ grub_normal_execute (const char *config, int nested, int batch) read_command_list (); read_fs_list (); read_handler_list (); + grub_command_execute ("parser.sh", 0, 0); + + reader_nested = nested; if (config) { - menu = read_config_file (config, nested); + menu = read_config_file (config); /* Ignore any error. */ grub_errno = GRUB_ERR_NONE; @@ -663,39 +415,27 @@ grub_normal_execute (const char *config, int nested, int batch) if (! batch) { if (menu && menu->size) - { - grub_menu_viewer_show_menu (menu, nested); - if (nested) - free_menu (menu); - } - else - grub_cmdline_run (nested); + { + grub_menu_viewer_show_menu (menu, nested); + if (nested) + free_menu (menu); + } } } -static grub_err_t -grub_cmd_rescue (struct grub_command *cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) +/* This starts the normal mode. */ +void +grub_enter_normal_mode (const char *config) { - grub_longjmp (grub_exit_env, 0); - - /* Never reach here. */ - return 0; + grub_normal_execute (config, 0, 0); } -static grub_command_t cmd_normal; - /* Enter normal mode from rescue mode. */ static grub_err_t -grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), +grub_cmd_normal (struct grub_command *cmd, int argc, char *argv[]) { - grub_command_t cmd_rescue; - - grub_unregister_command (cmd_normal); - cmd_rescue = grub_register_command ("rescue", grub_cmd_rescue, - 0, "enter rescue mode"); + grub_unregister_command (cmd); if (argc == 0) { @@ -722,12 +462,77 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), grub_enter_normal_mode (argv[0]); quit: - grub_unregister_command (cmd_rescue); - cmd_normal = grub_register_command_prio ("normal", grub_cmd_normal, - 0, "enter normal mode", 0); return 0; } +void +grub_cmdline_run (int nested) +{ + grub_reader_t reader = grub_reader_get_current (); + + reader_nested = nested; + if (reader->init) + reader->init (); + grub_reader_loop (0); +} + +static grub_err_t +grub_normal_reader_init (void) +{ + grub_normal_init_page (); + grub_setcursor (1); + + grub_printf ("\ + [ Minimal BASH-like line editing is supported. For the first word, TAB\n\ + lists possible command completions. Anywhere else TAB lists possible\n\ + device/file completions.%s ]\n\n", + reader_nested ? " ESC at any time exits." : ""); + + return 0; +} + +static char cmdline[GRUB_MAX_CMDLINE]; + +static grub_err_t +grub_normal_read_line (char **line, int cont) +{ + grub_parser_t parser = grub_parser_get_current (); + char prompt[8 + grub_strlen (parser->name)]; + + grub_sprintf (prompt, "%s:%s> ", parser->name, (cont) ? "" : "grub"); + + while (1) + { + cmdline[0] = 0; + if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1)) + break; + + if ((reader_nested) || (cont)) + { + *line = 0; + return grub_errno; + } + } + + *line = grub_strdup (cmdline); + return 0; +} + +static struct grub_reader grub_normal_reader = + { + .name = "normal", + .init = grub_normal_reader_init, + .read_line = grub_normal_read_line + }; + +static char * +grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)), + const char *val) +{ + grub_set_more ((*val == '1')); + return grub_strdup (val); +} + GRUB_MOD_INIT(normal) { /* Normal mode shouldn't be unloaded. */ @@ -738,9 +543,13 @@ GRUB_MOD_INIT(normal) grub_set_history (GRUB_DEFAULT_HISTORY_SIZE); + grub_reader_register ("normal", &grub_normal_reader); + grub_reader_set_current (&grub_normal_reader); + grub_register_variable_hook ("pager", 0, grub_env_write_pager); + /* Register a command "normal" for the rescue mode. */ - cmd_normal = grub_register_command ("normal", grub_cmd_normal, - 0, "enter normal mode"); + grub_register_command_prio ("normal", grub_cmd_normal, + 0, "Enter normal mode", 0); /* Reload terminal colors when these variables are written to. */ grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal); @@ -754,6 +563,8 @@ GRUB_MOD_INIT(normal) GRUB_MOD_FINI(normal) { grub_set_history (0); - grub_unregister_command (cmd_normal); + grub_reader_unregister (&grub_normal_reader); + grub_register_variable_hook ("pager", 0, 0); + grub_fs_autoload_hook = 0; free_handler_list (); } diff --git a/normal/menu.c b/normal/menu.c index df262096c..abf1b0f6d 100644 --- a/normal/menu.c +++ b/normal/menu.c @@ -23,8 +23,8 @@ #include #include #include -#include #include +#include /* Get a menu entry by its index in the entry list. */ grub_menu_entry_t @@ -123,11 +123,11 @@ get_and_remove_first_entry_number (const char *name) void grub_menu_execute_entry(grub_menu_entry_t entry) { - grub_script_execute (entry->commands); + grub_parser_execute ((char *) entry->sourcecode); if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) /* Implicit execution of boot, only if something is loaded. */ - grub_command_execute ("boot", 0); + grub_command_execute ("boot", 0, 0); } /* Execute ENTRY from the menu MENU, falling back to entries specified diff --git a/normal/menu_entry.c b/normal/menu_entry.c index a9c17886f..6ec0d632a 100644 --- a/normal/menu_entry.c +++ b/normal/menu_entry.c @@ -21,7 +21,8 @@ #include #include #include -#include +#include +#include enum update_mode { @@ -970,12 +971,11 @@ clear_completions (void) static int run (struct screen *screen) { - struct grub_script *parsed_script = 0; int currline = 0; char *nextline; - auto grub_err_t editor_getline (char **line); - grub_err_t editor_getline (char **line) + auto grub_err_t editor_getline (char **line, int cont); + grub_err_t editor_getline (char **line, int cont __attribute__ ((unused))) { struct line *linep = screen->lines + currline; char *p; @@ -1008,23 +1008,14 @@ run (struct screen *screen) /* Execute the script, line for line. */ while (currline < screen->num_lines) { - editor_getline (&nextline); - parsed_script = grub_script_parse (nextline, editor_getline); - if (parsed_script) - { - /* Execute the command(s). */ - grub_script_execute (parsed_script); - - /* The parsed script was executed, throw it away. */ - grub_script_free (parsed_script); - } - else + editor_getline (&nextline, 0); + if (grub_parser_get_current ()->parse_line (nextline, editor_getline)) break; } if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) /* Implicit execution of boot, only if something is loaded. */ - grub_command_execute ("boot", 0); + grub_command_execute ("boot", 0, 0); if (grub_errno != GRUB_ERR_NONE) { diff --git a/normal/menu_text.c b/normal/menu_text.c index 9e97c32e9..e0d96c47f 100644 --- a/normal/menu_text.c +++ b/normal/menu_text.c @@ -24,7 +24,6 @@ #include #include #include -#include #include /* Time to delay after displaying an error message about a default/fallback diff --git a/normal/execute.c b/script/sh/execute.c similarity index 94% rename from normal/execute.c rename to script/sh/execute.c index 8bf6d1745..3856dd95c 100644 --- a/normal/execute.c +++ b/script/sh/execute.c @@ -19,10 +19,12 @@ #include #include -#include #include -#include +#include +#include +#include #include +#include static grub_err_t grub_script_execute_cmd (struct grub_script_cmd *cmd) @@ -192,7 +194,6 @@ grub_script_execute_menuentry (struct grub_script_cmd *cmd) { struct grub_script_cmd_menuentry *cmd_menuentry; struct grub_script_arglist *arglist; - struct grub_script *script; char **args = 0; int argcount = 0; int i = 0; @@ -219,15 +220,8 @@ grub_script_execute_menuentry (struct grub_script_cmd *cmd) } } - /* Parse the menu entry *again*. */ - script = grub_script_parse ((char *) cmd_menuentry->sourcecode, 0); - - /* Add new menu entry. */ - if (script) - { - grub_normal_menu_addentry (argcount, (const char **)args, - script, cmd_menuentry->sourcecode); - } + grub_menu_addentry (argcount, (const char **) args, + cmd_menuentry->sourcecode); /* Free arguments. */ for (i = 0; i < argcount; i++) diff --git a/normal/function.c b/script/sh/function.c similarity index 96% rename from normal/function.c rename to script/sh/function.c index 4c08d1581..db6b903cd 100644 --- a/normal/function.c +++ b/script/sh/function.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007 Free Software Foundation, Inc. + * Copyright (C) 2005,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 @@ -17,7 +17,7 @@ */ #include -#include +#include #include #include @@ -28,7 +28,7 @@ grub_script_function_create (char *functionname, struct grub_script *cmd) { grub_script_function_t func; grub_script_function_t *p; - + func = (grub_script_function_t) grub_malloc (sizeof (*func)); if (! func) return 0; @@ -39,7 +39,7 @@ grub_script_function_create (char *functionname, struct grub_script *cmd) grub_free (func); return 0; } - + func->func = cmd; /* Keep the list sorted for simplicity. */ @@ -107,11 +107,11 @@ int grub_script_function_iterate (int (*iterate) (grub_script_function_t)) { grub_script_function_t func; - + for (func = grub_script_function_list; func; func = func->next) if (iterate (func)) return 1; - + return 0; } diff --git a/normal/lexer.c b/script/sh/lexer.c similarity index 97% rename from normal/lexer.c rename to script/sh/lexer.c index f500374d5..8bae4871b 100644 --- a/normal/lexer.c +++ b/script/sh/lexer.c @@ -1,7 +1,7 @@ /* lexer.c - The scripting lexer. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2006,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 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 @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "grub_script.tab.h" @@ -44,7 +44,7 @@ check_textstate (grub_parser_state_t state) } struct grub_lexer_param * -grub_script_lexer_init (char *script, grub_err_t (*getline) (char **)) +grub_script_lexer_init (char *script, grub_reader_getline_t getline) { struct grub_lexer_param *param; @@ -176,7 +176,7 @@ grub_script_yylex2 (union YYSTYPE *yylval, struct grub_parser_param *parsestate) { grub_free (state->newscript); state->newscript = 0; - state->getline (&state->newscript); + state->getline (&state->newscript, 1); state->script = state->newscript; if (! state->script) return 0; diff --git a/normal/command.c b/script/sh/main.c similarity index 51% rename from normal/command.c rename to script/sh/main.c index 3296515c3..d4e342c71 100644 --- a/normal/command.c +++ b/script/sh/main.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003,2005,2006,2007 Free Software Foundation, Inc. + * Copyright (C) 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 @@ -16,43 +16,17 @@ * along with GRUB. If not, see . */ -#include -#include -#include -#include -#include -#include #include #include -#include -#include -#include +#include -int -grub_command_execute (char *cmdline, int interactive) +static grub_err_t +grub_normal_parse_line (char *line, grub_reader_getline_t getline) { - auto grub_err_t cmdline_get (char **s); - grub_err_t cmdline_get (char **s) - { - *s = grub_malloc (GRUB_MAX_CMDLINE); - *s[0] = '\0'; - return grub_cmdline_get (">", *s, GRUB_MAX_CMDLINE, 0, 1); - } - - grub_err_t ret = 0; - char *pager; struct grub_script *parsed_script; - - /* Enable the pager if the environment pager is set to 1. */ - if (interactive) - pager = grub_env_get ("pager"); - else - pager = NULL; - if (pager && (! grub_strcmp (pager, "1"))) - grub_set_more (1); /* Parse the script. */ - parsed_script = grub_script_parse (cmdline, cmdline_get); + parsed_script = grub_script_parse (line, getline); if (parsed_script) { @@ -63,8 +37,22 @@ grub_command_execute (char *cmdline, int interactive) grub_script_free (parsed_script); } - if (pager && (! grub_strcmp (pager, "1"))) - grub_set_more (0); - - return ret; + return grub_errno; +} + +static struct grub_parser grub_sh_parser = + { + .name = "sh", + .parse_line = grub_normal_parse_line + }; + +GRUB_MOD_INIT(sh) +{ + (void) mod; + grub_parser_register ("sh", &grub_sh_parser); +} + +GRUB_MOD_FINI(sh) +{ + grub_parser_unregister (&grub_sh_parser); } diff --git a/normal/parser.y b/script/sh/parser.y similarity index 99% rename from normal/parser.y rename to script/sh/parser.y index eaf400b45..366f6b064 100644 --- a/normal/parser.y +++ b/script/sh/parser.y @@ -18,7 +18,7 @@ */ %{ -#include +#include #include #define YYFREE grub_free @@ -167,10 +167,10 @@ commands: command recognized after executing the `grub_script_mem_record; and before `grub_script_mem_record_stop'. */ function: "function" GRUB_PARSER_TOKEN_NAME - { + { grub_script_lexer_ref (state->lexerstate); } newlines '{' - { + { /* The first part of the function was recognized. Now start recording the memory usage to store this function. */ diff --git a/normal/script.c b/script/sh/script.c similarity index 98% rename from normal/script.c rename to script/sh/script.c index 0d5d5a8b7..3e80b8383 100644 --- a/normal/script.c +++ b/script/sh/script.c @@ -18,7 +18,7 @@ */ #include -#include +#include #include #include @@ -110,7 +110,7 @@ grub_script_arg_add (struct grub_parser_param *state, struct grub_script_arg *ar { struct grub_script_arg *argpart; struct grub_script_arg *ll; - + argpart = (struct grub_script_arg *) grub_script_malloc (state, sizeof (*arg)); argpart->type = type; argpart->str = str; @@ -121,7 +121,7 @@ grub_script_arg_add (struct grub_parser_param *state, struct grub_script_arg *ar for (ll = arg; ll->next; ll = ll->next); ll->next = argpart; - + return arg; } @@ -294,7 +294,7 @@ grub_script_create (struct grub_script_cmd *cmd, struct grub_script_mem *mem) /* Parse the script passed in SCRIPT and return the parsed datastructure that is ready to be interpreted. */ struct grub_script * -grub_script_parse (char *script, grub_err_t (*getline) (char **)) +grub_script_parse (char *script, grub_reader_getline_t getline) { struct grub_script *parsed; struct grub_script_mem *membackup; diff --git a/util/grub-emu.c b/util/grub-emu.c index 59392fe35..addbc085f 100644 --- a/util/grub-emu.c +++ b/util/grub-emu.c @@ -86,6 +86,11 @@ grub_machine_fini (void) { grub_console_fini (); } + +void +read_command_list (void) +{ +} static struct option options[] =