From 2fbcbbc3895142f5ddc17518eacc7a5b7fbeb575 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 20 Dec 2009 02:52:39 +0100 Subject: [PATCH] Save 314 bytes on not handling contexts in core --- conf/any-emu.rmk | 2 +- conf/common.rmk | 2 +- conf/i386-coreboot.rmk | 3 +- conf/i386-efi.rmk | 3 +- conf/i386-ieee1275.rmk | 2 +- conf/i386-pc.rmk | 3 +- conf/powerpc-ieee1275.rmk | 2 +- conf/sparc64-ieee1275.rmk | 2 +- conf/x86_64-efi.rmk | 2 +- include/grub/env.h | 30 ++---- include/grub/env_private.h | 46 +++++++++ include/grub/normal.h | 2 + kern/corecmd.c | 14 --- kern/env.c | 203 ++----------------------------------- kern/main.c | 2 - normal/context.c | 172 +++++++++++++++++++++++++++++++ normal/main.c | 12 ++- 17 files changed, 259 insertions(+), 243 deletions(-) create mode 100644 include/grub/env_private.h create mode 100644 normal/context.c diff --git a/conf/any-emu.rmk b/conf/any-emu.rmk index fb97de0a0..066bb52ba 100644 --- a/conf/any-emu.rmk +++ b/conf/any-emu.rmk @@ -27,7 +27,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \ normal/handler.c normal/auth.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/menu_text.c normal/context.c \ script/main.c script/execute.c script/function.c \ script/lexer.c script/script.c grub_script.tab.c \ partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \ diff --git a/conf/common.rmk b/conf/common.rmk index 1ed30a404..74e2b5bc4 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -543,7 +543,7 @@ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \ normal/auth.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/misc.c normal/context.c normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index e597328e7..1efea8afb 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -35,7 +35,8 @@ 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 msdos_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 i18n.h + machine/memory.h machine/loader.h list.h handler.h command.h i18n.h \ + env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR),-Bstatic diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index 261fe4092..2de0e9304 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -51,7 +51,8 @@ kernel_img_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.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 msdos_partition.h reader.h symbol.h term.h time.h types.h \ - efi/efi.h efi/time.h efi/disk.h i386/pit.h list.h handler.h command.h i18n.h + efi/efi.h efi/time.h efi/disk.h i386/pit.h list.h handler.h command.h \ + i18n.h env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk index 8d9577844..08c6c8f37 100644 --- a/conf/i386-ieee1275.rmk +++ b/conf/i386-ieee1275.rmk @@ -33,7 +33,7 @@ kernel_img_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 msdos_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 i18n.h + list.h handler.h command.h i18n.h env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 046c71641..8cec19f19 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -64,7 +64,8 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ partition.h msdos_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 i386/pit.h list.h handler.h command.h i18n.h + machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h \ + i18n.h env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) $(TARGET_IMG_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KERNEL_MACHINE_LINK_ADDR) $(COMMON_CFLAGS) diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 85b1fa211..9c16299d1 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -17,7 +17,7 @@ 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 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 \ msdos_partition.h ieee1275/ieee1275.h machine/kernel.h handler.h list.h \ - command.h i18n.h + command.h i18n.h env_private.h symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h gensymlist.sh /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1) diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk index d19e927a5..d34adeb3c 100644 --- a/conf/sparc64-ieee1275.rmk +++ b/conf/sparc64-ieee1275.rmk @@ -31,7 +31,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \ list.h handler.h command.h i18n.h \ sparc64/libgcc.h ieee1275/ieee1275.h machine/kernel.h \ - sparc64/ieee1275/ieee1275.h + sparc64/ieee1275/ieee1275.h env_private.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 \ diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk index 0d1289c6f..f5f0db25e 100644 --- a/conf/x86_64-efi.rmk +++ b/conf/x86_64-efi.rmk @@ -51,7 +51,7 @@ 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 msdos_partition.h reader.h symbol.h term.h time.h types.h \ efi/efi.h efi/time.h efi/disk.h machine/loader.h i386/pit.h list.h \ - handler.h command.h i18n.h + handler.h command.h i18n.h env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/include/grub/env.h b/include/grub/env.h index 440185a59..ae4fd8745 100644 --- a/include/grub/env.h +++ b/include/grub/env.h @@ -22,6 +22,7 @@ #include #include #include +#include struct grub_env_var; @@ -30,18 +31,6 @@ typedef char *(*grub_env_read_hook_t) (struct grub_env_var *var, typedef char *(*grub_env_write_hook_t) (struct grub_env_var *var, const char *val); -enum grub_env_var_type - { - /* The default variable type which is local in current context. */ - GRUB_ENV_VAR_LOCAL, - - /* The exported type, which is passed to new contexts. */ - GRUB_ENV_VAR_GLOBAL, - - /* The data slot type, which is used to store arbitrary data. */ - GRUB_ENV_VAR_DATA - }; - struct grub_env_var { char *name; @@ -50,23 +39,24 @@ struct grub_env_var grub_env_write_hook_t write_hook; struct grub_env_var *next; struct grub_env_var **prevp; - enum grub_env_var_type type; + int global; }; grub_err_t EXPORT_FUNC(grub_env_set) (const char *name, const char *val); char *EXPORT_FUNC(grub_env_get) (const char *name); void EXPORT_FUNC(grub_env_unset) (const char *name); void EXPORT_FUNC(grub_env_iterate) (int (*func) (struct grub_env_var *var)); +struct grub_env_var *EXPORT_FUNC(grub_env_find) (const char *name); grub_err_t EXPORT_FUNC(grub_register_variable_hook) (const char *name, grub_env_read_hook_t read_hook, grub_env_write_hook_t write_hook); -grub_err_t EXPORT_FUNC(grub_env_context_open) (int export); -grub_err_t EXPORT_FUNC(grub_env_context_close) (void); -grub_err_t EXPORT_FUNC(grub_env_export) (const char *name); -grub_err_t EXPORT_FUNC(grub_env_set_data_slot) (const char *name, - const void *ptr); -void *EXPORT_FUNC(grub_env_get_data_slot) (const char *name); -void EXPORT_FUNC(grub_env_unset_data_slot) (const char *name); +grub_err_t grub_env_context_open (int export); +grub_err_t grub_env_context_close (void); +grub_err_t grub_env_export (const char *name); + +void grub_env_unset_menu (void); +grub_menu_t grub_env_get_menu (void); +void grub_env_set_menu (grub_menu_t nmenu); #endif /* ! GRUB_ENV_HEADER */ diff --git a/include/grub/env_private.h b/include/grub/env_private.h new file mode 100644 index 000000000..bb001533f --- /dev/null +++ b/include/grub/env_private.h @@ -0,0 +1,46 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,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 . + */ + +#ifndef GRUB_ENV_PRIVATE_HEADER +#define GRUB_ENV_PRIVATE_HEADER 1 + +#include + +/* The size of the hash table. */ +#define HASHSZ 13 + +/* A hashtable for quick lookup of variables. */ +struct grub_env_context +{ + /* A hash table for variables. */ + struct grub_env_var *vars[HASHSZ]; + + /* One level deeper on the stack. */ + struct grub_env_context *prev; +}; + +/* This is used for sorting only. */ +struct grub_env_sorted_var +{ + struct grub_env_var *var; + struct grub_env_sorted_var *next; +}; + +extern struct grub_env_context *EXPORT_VAR(grub_current_context); + +#endif /* ! GRUB_ENV_PRIVATE_HEADER */ diff --git a/include/grub/normal.h b/include/grub/normal.h index feebc85b1..15f4671d2 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -84,6 +84,8 @@ void read_command_list (void); /* Defined in `autofs.c'. */ void read_fs_list (void); +void grub_context_init (void); +void grub_context_fini (void); #ifdef GRUB_UTIL void grub_normal_init (void); diff --git a/kern/corecmd.c b/kern/corecmd.c index 03944f2df..7e8a3b4f6 100644 --- a/kern/corecmd.c +++ b/kern/corecmd.c @@ -73,18 +73,6 @@ grub_core_cmd_unset (struct grub_command *cmd __attribute__ ((unused)), return 0; } -static grub_err_t -grub_core_cmd_export (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) -{ - if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "no environment variable specified"); - - grub_env_export (args[0]); - return 0; -} - /* insmod MODULE */ static grub_err_t grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)), @@ -193,8 +181,6 @@ grub_register_core_commands (void) "set [ENVVAR=VALUE]", "set an environment variable"); grub_register_command ("unset", grub_core_cmd_unset, "unset ENVVAR", "remove an environment variable"); - grub_register_command ("export", grub_core_cmd_export, - "export ENVVAR", "Export a variable."); grub_register_command ("ls", grub_core_cmd_ls, "ls [ARG]", "list devices or files"); grub_register_command ("insmod", grub_core_cmd_insmod, diff --git a/kern/env.c b/kern/env.c index 750902af8..fdb3c9a34 100644 --- a/kern/env.c +++ b/kern/env.c @@ -18,34 +18,15 @@ */ #include +#include #include #include -/* The size of the hash table. */ -#define HASHSZ 13 - -/* A hashtable for quick lookup of variables. */ -struct grub_env_context -{ - /* A hash table for variables. */ - struct grub_env_var *vars[HASHSZ]; - - /* One level deeper on the stack. */ - struct grub_env_context *prev; -}; - -/* This is used for sorting only. */ -struct grub_env_sorted_var -{ - struct grub_env_var *var; - struct grub_env_sorted_var *next; -}; - /* The initial context. */ static struct grub_env_context initial_context; /* The current context. */ -static struct grub_env_context *current_context = &initial_context; +struct grub_env_context *grub_current_context = &initial_context; /* Return the hash representation of the string S. */ static unsigned int @@ -60,87 +41,20 @@ grub_env_hashval (const char *s) return i % HASHSZ; } -static struct grub_env_var * +struct grub_env_var * grub_env_find (const char *name) { struct grub_env_var *var; int idx = grub_env_hashval (name); /* Look for the variable in the current context. */ - for (var = current_context->vars[idx]; var; var = var->next) + for (var = grub_current_context->vars[idx]; var; var = var->next) if (grub_strcmp (var->name, name) == 0) return var; return 0; } -grub_err_t -grub_env_context_open (int export) -{ - struct grub_env_context *context; - int i; - - context = grub_zalloc (sizeof (*context)); - if (! context) - return grub_errno; - - context->prev = current_context; - current_context = context; - - /* Copy exported variables. */ - for (i = 0; i < HASHSZ; i++) - { - struct grub_env_var *var; - - for (var = context->prev->vars[i]; var; var = var->next) - { - if (export && var->type == GRUB_ENV_VAR_GLOBAL) - { - if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE) - { - grub_env_context_close (); - return grub_errno; - } - grub_register_variable_hook (var->name, var->read_hook, var->write_hook); - } - } - } - - return GRUB_ERR_NONE; -} - -grub_err_t -grub_env_context_close (void) -{ - struct grub_env_context *context; - int i; - - if (! current_context->prev) - grub_fatal ("cannot close the initial context"); - - /* Free the variables associated with this context. */ - for (i = 0; i < HASHSZ; i++) - { - struct grub_env_var *p, *q; - - for (p = current_context->vars[i]; p; p = q) - { - q = p->next; - grub_free (p->name); - if (p->type != GRUB_ENV_VAR_DATA) - grub_free (p->value); - grub_free (p); - } - } - - /* Restore the previous context. */ - context = current_context->prev; - grub_free (current_context); - current_context = context; - - return GRUB_ERR_NONE; -} - static void grub_env_insert (struct grub_env_context *context, struct grub_env_var *var) @@ -164,18 +78,6 @@ grub_env_remove (struct grub_env_var *var) var->next->prevp = var->prevp; } -grub_err_t -grub_env_export (const char *name) -{ - struct grub_env_var *var; - - var = grub_env_find (name); - if (var) - var->type = GRUB_ENV_VAR_GLOBAL; - - return GRUB_ERR_NONE; -} - grub_err_t grub_env_set (const char *name, const char *val) { @@ -207,9 +109,8 @@ grub_env_set (const char *name, const char *val) if (! var) return grub_errno; - /* This is not necessary, because GRUB_ENV_VAR_LOCAL == 0. But leave - this for readability. */ - var->type = GRUB_ENV_VAR_LOCAL; + /* This is not necessary. But leave this for readability. */ + var->global = 0; var->name = grub_strdup (name); if (! var->name) @@ -219,7 +120,7 @@ grub_env_set (const char *name, const char *val) if (! var->value) goto fail; - grub_env_insert (current_context, var); + grub_env_insert (grub_current_context, var); return GRUB_ERR_NONE; @@ -263,8 +164,7 @@ grub_env_unset (const char *name) grub_env_remove (var); grub_free (var->name); - if (var->type != GRUB_ENV_VAR_DATA) - grub_free (var->value); + grub_free (var->value); grub_free (var); } @@ -280,14 +180,10 @@ grub_env_iterate (int (*func) (struct grub_env_var *var)) { struct grub_env_var *var; - for (var = current_context->vars[i]; var; var = var->next) + for (var = grub_current_context->vars[i]; var; var = var->next) { struct grub_env_sorted_var *p, **q; - /* Ignore data slots. */ - if (var->type == GRUB_ENV_VAR_DATA) - continue; - sorted_var = grub_malloc (sizeof (*sorted_var)); if (! sorted_var) goto fail; @@ -343,84 +239,3 @@ grub_register_variable_hook (const char *name, return GRUB_ERR_NONE; } - -static char * -mangle_data_slot_name (const char *name) -{ - char *mangled_name; - - mangled_name = grub_malloc (grub_strlen (name) + 2); - if (! mangled_name) - return 0; - - grub_sprintf (mangled_name, "\e%s", name); - return mangled_name; -} - -grub_err_t -grub_env_set_data_slot (const char *name, const void *ptr) -{ - char *mangled_name; - struct grub_env_var *var; - - mangled_name = mangle_data_slot_name (name); - if (! mangled_name) - goto fail; - - /* If the variable does already exist, just update the variable. */ - var = grub_env_find (mangled_name); - if (var) - { - var->value = (char *) ptr; - return GRUB_ERR_NONE; - } - - /* The variable does not exist, so create a new one. */ - var = grub_zalloc (sizeof (*var)); - if (! var) - goto fail; - - var->type = GRUB_ENV_VAR_DATA; - var->name = mangled_name; - var->value = (char *) ptr; - - grub_env_insert (current_context, var); - - return GRUB_ERR_NONE; - - fail: - - grub_free (mangled_name); - return grub_errno; -} - -void * -grub_env_get_data_slot (const char *name) -{ - char *mangled_name; - void *ptr = 0; - - mangled_name = mangle_data_slot_name (name); - if (! mangled_name) - goto fail; - - ptr = grub_env_get (mangled_name); - grub_free (mangled_name); - - fail: - - return ptr; -} - -void -grub_env_unset_data_slot (const char *name) -{ - char *mangled_name; - - mangled_name = mangle_data_slot_name (name); - if (! mangled_name) - return; - - grub_env_unset (mangled_name); - grub_free (mangled_name); -} diff --git a/kern/main.c b/kern/main.c index 9215d55e7..b76d2d20e 100644 --- a/kern/main.c +++ b/kern/main.c @@ -114,7 +114,6 @@ grub_set_root_dev (void) const char *prefix; grub_register_variable_hook ("root", 0, grub_env_write_root); - grub_env_export ("root"); prefix = grub_env_get ("prefix"); @@ -164,7 +163,6 @@ grub_main (void) /* It is better to set the root device as soon as possible, for convenience. */ grub_machine_set_prefix (); - grub_env_export ("prefix"); grub_set_root_dev (); grub_register_core_commands (); diff --git a/normal/context.c b/normal/context.c new file mode 100644 index 000000000..d9ad3b61d --- /dev/null +++ b/normal/context.c @@ -0,0 +1,172 @@ +/* env.c - Environment variables */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,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 . + */ + +#include +#include +#include +#include +#include + +struct menu_pointer +{ + grub_menu_t menu; + struct menu_pointer *prev; +}; + +struct menu_pointer initial_menu; +struct menu_pointer *current_menu = &initial_menu; + +void +grub_env_unset_menu (void) +{ + current_menu->menu = NULL; +} + +grub_menu_t +grub_env_get_menu (void) +{ + return current_menu->menu; +} + +void +grub_env_set_menu (grub_menu_t nmenu) +{ + current_menu->menu = nmenu; +} + +grub_err_t +grub_env_context_open (int export) +{ + struct grub_env_context *context; + int i; + struct menu_pointer *menu; + + context = grub_zalloc (sizeof (*context)); + if (! context) + return grub_errno; + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + return grub_errno; + + context->prev = grub_current_context; + grub_current_context = context; + + menu->prev = current_menu; + current_menu = menu; + + /* Copy exported variables. */ + for (i = 0; i < HASHSZ; i++) + { + struct grub_env_var *var; + + for (var = context->prev->vars[i]; var; var = var->next) + { + if (export && var->global) + { + if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE) + { + grub_env_context_close (); + return grub_errno; + } + grub_register_variable_hook (var->name, var->read_hook, var->write_hook); + } + } + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_env_context_close (void) +{ + struct grub_env_context *context; + int i; + struct menu_pointer *menu; + + if (! grub_current_context->prev) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "cannot close the initial context"); + + /* Free the variables associated with this context. */ + for (i = 0; i < HASHSZ; i++) + { + struct grub_env_var *p, *q; + + for (p = grub_current_context->vars[i]; p; p = q) + { + q = p->next; + grub_free (p->name); + grub_free (p->value); + grub_free (p); + } + } + + /* Restore the previous context. */ + context = grub_current_context->prev; + grub_free (grub_current_context); + grub_current_context = context; + + menu = current_menu->prev; + grub_free (current_menu); + current_menu = menu; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_env_export (const char *name) +{ + struct grub_env_var *var; + + var = grub_env_find (name); + if (var) + var->global = 1; + + return GRUB_ERR_NONE; +} + +static grub_command_t export_cmd; + +static grub_err_t +grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "no environment variable specified"); + + grub_env_export (args[0]); + return 0; +} + +void +grub_context_init (void) +{ + grub_env_export ("root"); + grub_env_export ("prefix"); + + export_cmd = grub_register_command ("export", grub_cmd_export, + "export ENVVAR", "Export a variable."); +} + +void +grub_context_fini (void) +{ + grub_unregister_command (export_cmd); +} diff --git a/normal/main.c b/normal/main.c index f080a6971..52581613a 100644 --- a/normal/main.c +++ b/normal/main.c @@ -133,7 +133,7 @@ free_menu (grub_menu_t menu) } grub_free (menu); - grub_env_unset_data_slot ("menu"); + grub_env_unset_menu (); } static void @@ -174,7 +174,7 @@ grub_normal_add_menu_entry (int argc, const char **args, return grub_errno; classes_tail = classes_head; - menu = grub_env_get_data_slot ("menu"); + menu = grub_env_get_menu (); if (! menu) return grub_error (GRUB_ERR_MENU, "no menu context"); @@ -357,14 +357,14 @@ read_config_file (const char *config) grub_menu_t newmenu; - newmenu = grub_env_get_data_slot ("menu"); + newmenu = grub_env_get_menu (); if (! newmenu) { newmenu = grub_zalloc (sizeof (*newmenu)); if (! newmenu) return 0; - grub_env_set_data_slot ("menu", newmenu); + grub_env_set_menu (newmenu); } /* Try to open the config file. */ @@ -562,6 +562,8 @@ grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)), GRUB_MOD_INIT(normal) { + grub_context_init (); + /* Normal mode shouldn't be unloaded. */ if (mod) grub_dl_ref (mod); @@ -589,6 +591,8 @@ GRUB_MOD_INIT(normal) GRUB_MOD_FINI(normal) { + grub_context_fini (); + grub_set_history (0); grub_reader_unregister (&grub_normal_reader); grub_register_variable_hook ("pager", 0, 0);