summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-04-06 15:19:21 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-04-06 15:19:21 -0700
commit2920515b1fe5dbf20cfa2f2890b154cd147831ec (patch)
treeb60d63da0dc91bfd3b134233319b4ee19fc0873a
parentc2636af9b7f4b170ffe791d5008fe6bdd822a59b (diff)
downloadsyslinux-2920515b1fe5dbf20cfa2f2890b154cd147831ec.tar.gz
Implement MENU SAVE; fix COM32 setadv functionsyslinux-3.74-pre18
Implement MENU SAVE, which allows the menu system to retain the previous selection from one boot to another. In the process, fix the syslinux_setadv() function. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--NEWS3
-rw-r--r--com32/include/syslinux/advconst.h2
-rw-r--r--com32/lib/syslinux/setadv.c16
-rw-r--r--com32/menu/menu.h1
-rw-r--r--com32/menu/menumain.c9
-rw-r--r--com32/menu/readconfig.c22
-rw-r--r--doc/menu.txt23
7 files changed, 70 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index 91845598..6ffd41b7 100644
--- a/NEWS
+++ b/NEWS
@@ -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]