diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | com32/include/syslinux/advconst.h | 2 | ||||
-rw-r--r-- | com32/lib/syslinux/setadv.c | 16 | ||||
-rw-r--r-- | com32/menu/menu.h | 1 | ||||
-rw-r--r-- | com32/menu/menumain.c | 9 | ||||
-rw-r--r-- | com32/menu/readconfig.c | 22 | ||||
-rw-r--r-- | doc/menu.txt | 23 |
7 files changed, 70 insertions, 6 deletions
@@ -37,6 +37,9 @@ Changes in 3.74: byte at offset 439 decimal. * Add IPAPPEND strings to com32 modules, especially needed for linux.c32. + * New MENU SAVE directive which saves the latest menu + selection until the next boot. Currently only implemented for + EXTLINUX. Changes in 3.73: * Upgrade gPXE to release version 0.9.5. diff --git a/com32/include/syslinux/advconst.h b/com32/include/syslinux/advconst.h index 1e1ec73e..b7c775fd 100644 --- a/com32/include/syslinux/advconst.h +++ b/com32/include/syslinux/advconst.h @@ -1,6 +1,7 @@ /* ----------------------------------------------------------------------- * * * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -39,5 +40,6 @@ #define ADV_END 0 #define ADV_BOOTONCE 1 +#define ADV_MENUSAVE 2 #endif /* _SYSLINUX_ADVCONST_H */ diff --git a/com32/lib/syslinux/setadv.c b/com32/lib/syslinux/setadv.c index 4af8d6e1..5993df6d 100644 --- a/com32/lib/syslinux/setadv.c +++ b/com32/lib/syslinux/setadv.c @@ -1,6 +1,7 @@ /* ----------------------------------------------------------------------- * * * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -47,7 +48,7 @@ int syslinux_setadv(int tag, size_t size, const void *data) { uint8_t *p, *advtmp; - size_t left; + size_t rleft, left; if ((unsigned)tag-1 > 254) { errno = EINVAL; @@ -59,11 +60,11 @@ int syslinux_setadv(int tag, size_t size, const void *data) return -1; } - left = syslinux_adv_size(); + rleft = left = syslinux_adv_size(); p = advtmp = alloca(left); memcpy(p, syslinux_adv_ptr(), left); /* Make working copy */ - while (left >= 2) { + while (rleft >= 2) { uint8_t ptag = p[0]; size_t plen = p[1]+2; @@ -73,17 +74,19 @@ int syslinux_setadv(int tag, size_t size, const void *data) if (ptag == tag) { /* Found our tag. Delete it. */ - if (plen >= left) { + if (plen >= rleft) { /* Entire remainder is our tag */ break; } - memmove(p, p+plen, left-plen); + memmove(p, p+plen, rleft-plen); + rleft -= plen; /* Fewer bytes to read, but not to write */ } else { /* Not our tag */ - if (plen > left) + if (plen > rleft) break; /* Corrupt tag (overrun) - overwrite it */ left -= plen; + rleft -= plen; p += plen; } } @@ -100,6 +103,7 @@ int syslinux_setadv(int tag, size_t size, const void *data) *p++ = tag; *p++ = size; memcpy(p, data, size); + p += size; left -= size+2; } diff --git a/com32/menu/menu.h b/com32/menu/menu.h index e2ffc1bc..43f65947 100644 --- a/com32/menu/menu.h +++ b/com32/menu/menu.h @@ -174,6 +174,7 @@ extern struct menu *root_menu, *start_menu, *hide_menu, *menu_list; /* These are global parameters regardless of which menu we're displaying */ extern int shiftkey; extern int hiddenmenu; +extern bool menusave; extern long long totaltimeout; void parse_configs(char **argv); diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c index f7af90aa..c3da97e4 100644 --- a/com32/menu/menumain.c +++ b/com32/menu/menumain.c @@ -1,6 +1,7 @@ /* ----------------------------------------------------------------------- * * * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +28,7 @@ #include <setjmp.h> #include <limits.h> #include <com32.h> +#include <syslinux/adv.h> #include "menu.h" @@ -875,6 +877,13 @@ run_menu(void) break; } } + if (done && !me->passwd) { + /* Only save a new default if we don't have a password... */ + if (menusave && me->label) { + syslinux_setadv(ADV_MENUSAVE, strlen(me->label), me->label); + syslinux_adv_write(); + } + } break; case KEY_UP: diff --git a/com32/menu/readconfig.c b/com32/menu/readconfig.c index c276c0bf..768591d9 100644 --- a/com32/menu/readconfig.c +++ b/com32/menu/readconfig.c @@ -12,6 +12,7 @@ * ----------------------------------------------------------------------- */ #include <stdio.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <minmax.h> @@ -19,6 +20,7 @@ #include <inttypes.h> #include <colortbl.h> #include <com32.h> +#include <syslinux/adv.h> #include <syslinux/config.h> #include "menu.h" @@ -33,6 +35,7 @@ struct menu *root_menu, *start_menu, *hide_menu, *menu_list; int shiftkey = 0; /* Only display menu if shift key pressed */ int hiddenmenu = 0; long long totaltimeout = 0; +bool menusave = false; /* Keep track of global default */ static int has_ui = 0; /* DEFAULT only counts if UI is found */ @@ -668,6 +671,8 @@ static void parse_config_file(FILE *f) } } else if ( looking_at(p, "shiftkey") ) { shiftkey = 1; + } else if ( looking_at(p, "save") ) { + menusave = true; } else if ( looking_at(p, "onerror") ) { refstr_put(m->onerror); m->onerror = refstrdup(skipspace(p+7)); @@ -1026,6 +1031,23 @@ void parse_configs(char **argv) } } + /* If "menu save" is active, let the ADV override the global default */ + if (menusave) { + size_t len; + const char *lbl = syslinux_getadv(ADV_MENUSAVE, &len); + char *lstr; + if (lbl && len) { + lstr = refstr_alloc(len); + memcpy(lstr, lbl, len); /* refstr_alloc() adds the final null */ + me = find_label(lstr); + if (me && me->menu != hide_menu) { + me->menu->defentry = me->entry; + start_menu = me->menu; + } + refstr_put(lstr); + } + } + /* Final per-menu initialization, with all labels known */ for (m = menu_list; m; m = m->next) { m->curentry = m->defentry; /* All menus start at their defaults */ diff --git a/doc/menu.txt b/doc/menu.txt index 379df321..72bc9dca 100644 --- a/doc/menu.txt +++ b/doc/menu.txt @@ -48,6 +48,12 @@ MENU HIDDEN All that is displayed is a timeout message. +MENU SHIFTKEY + + Exit the menu system immediately unless either the Shift or Alt + key is pressed, or Caps Lock or Scroll Lock is set. + + MENU SEPARATOR Insert an empty line in the menu. @@ -269,6 +275,23 @@ DEFAULT label non-label. The menu system does not support that. +MENU SAVE + + Remember the last entry selected and make that the default for + the next boot. A password-protected menu entry is *not* + saved. This requires the ADV data storage mechanism, which is + currently only implemented for EXTLINUX, although the other + Syslinux derivatives will accept the command (and ignore it.) + + NOTE: MENU SAVE stores the LABEL tag of the selected entry; + this mechanism therefore relies on LABEL tags being unique. + On the other hand, it handles changes in the configuration + file gracefully. + + The MENU SAVE information can be cleared with + "extlinux --reset-adv". + + INCLUDE filename [tagname] MENU INCLUDE filename [tagname] |