aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2011-04-18 14:53:45 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2011-04-18 14:53:45 -0700
commit1be51e9991618732179da97750548a65371e9dff (patch)
tree5b1ed62a487d3947e025b0491157b21678764a84
parent6831030abcb28fa34f63ec8d1a6304d097addb90 (diff)
parent1370ad3a91803626d326abea253f9270bd6819c3 (diff)
downloadsyslinux-1be51e9991618732179da97750548a65371e9dff.tar.gz
syslinux-1be51e9991618732179da97750548a65371e9dff.tar.xz
syslinux-1be51e9991618732179da97750548a65371e9dff.zip
Merge commit 'syslinux-4.04' into dynamic-sector
-rw-r--r--NEWS5
-rw-r--r--com32/libutil/Makefile3
-rw-r--r--com32/libutil/include/getkey.h4
-rw-r--r--com32/libutil/keyname.c138
-rw-r--r--com32/menu/menu.h2
-rw-r--r--com32/menu/menumain.c9
-rw-r--r--com32/menu/readconfig.c48
-rw-r--r--com32/samples/keytest.c9
-rw-r--r--diag/geodsp/Makefile3
-rw-r--r--doc/menu.txt19
-rwxr-xr-xextlinux/main.c15
-rw-r--r--libinstaller/syslxcom.c13
-rw-r--r--libinstaller/syslxcom.h1
-rwxr-xr-xlinux/syslinux.c4
-rw-r--r--syslinux.spec.in3
15 files changed, 250 insertions, 26 deletions
diff --git a/NEWS b/NEWS
index 5d9b5206..94c47ab9 100644
--- a/NEWS
+++ b/NEWS
@@ -48,7 +48,10 @@ Changes in 4.04:
* Include a set of diagnostics by Gene Cumm.
* Fixes for gcc 4.6 and binutils 2.21.51.
* chain.c32: Allow "uuid" as a synonym to "guid".
- * Handle directory names starting with .. for vfat and iso9660.
+ * Handle directory names starting with .. for vfat and
+ iso9660.
+ * New MENU HIDDENKEY command to provide a one-keystroke way to
+ activate a boot option from a hidden menu intro screen.
Changes in 4.03:
* Don't hang if no configuration file is found.
diff --git a/com32/libutil/Makefile b/com32/libutil/Makefile
index 02789ca6..7a6b5272 100644
--- a/com32/libutil/Makefile
+++ b/com32/libutil/Makefile
@@ -32,7 +32,8 @@
topdir = ../..
include ../MCONFIG
-LIBOBJS = ansiline.o ansiraw.o get_key.o sha1hash.o unbase64.o \
+LIBOBJS = ansiline.o ansiraw.o get_key.o keyname.o \
+ sha1hash.o unbase64.o \
md5.o crypt-md5.o sha256crypt.o sha512crypt.o base64.o
LNXLIBOBJS = $(patsubst %.o,%.lo,$(LIBOBJS))
diff --git a/com32/libutil/include/getkey.h b/com32/libutil/include/getkey.h
index 52312a25..a46de812 100644
--- a/com32/libutil/include/getkey.h
+++ b/com32/libutil/include/getkey.h
@@ -75,6 +75,10 @@
#define KEY_INSERT 0x0128
#define KEY_DELETE 0x0129
+#define KEY_MAX 0x012a
+
int get_key(FILE *, clock_t);
+int key_name_to_code(const char *);
+const char *key_code_to_name(int);
#endif /* LIBUTIL_GETKEY_H */
diff --git a/com32/libutil/keyname.c b/com32/libutil/keyname.c
new file mode 100644
index 00000000..3b9e6581
--- /dev/null
+++ b/com32/libutil/keyname.c
@@ -0,0 +1,138 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2011 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
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * keyname.c
+ *
+ * Conversion between strings and get_key() key numbers.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/times.h>
+#include <getkey.h>
+#include <libutil.h>
+
+struct keyname {
+ const char *string;
+ int key;
+};
+
+static const struct keyname key_names[] = {
+ { "Backspace", KEY_BACKSPACE },
+ { "Tab", KEY_TAB },
+ { "Enter", KEY_ENTER },
+ { "Esc", KEY_ESC },
+ { "Escape", KEY_ESC },
+ { "Space", ' ' },
+ { "^?", KEY_DEL },
+ { "F1", KEY_F1 },
+ { "F2", KEY_F2},
+ { "F3", KEY_F3 },
+ { "F4", KEY_F4 },
+ { "F5", KEY_F5 },
+ { "F6", KEY_F6 },
+ { "F7", KEY_F7 },
+ { "F8", KEY_F8 },
+ { "F9", KEY_F9 },
+ { "F10", KEY_F10 },
+ { "F11", KEY_F11 },
+ { "F12", KEY_F12 },
+ { "Up", KEY_UP },
+ { "Down", KEY_DOWN },
+ { "Left", KEY_LEFT },
+ { "Right", KEY_RIGHT },
+ { "PgUp", KEY_PGUP },
+ { "PgDn", KEY_PGDN },
+ { "Home", KEY_HOME },
+ { "End", KEY_END },
+ { "Insert", KEY_INSERT },
+ { "Delete", KEY_DELETE },
+ { NULL, KEY_NONE }
+};
+
+int key_name_to_code(const char *code)
+{
+ const struct keyname *name;
+
+ if (code[0] && !code[1]) {
+ /* Single character */
+ return (unsigned char)code[0];
+ } else if (code[0] == '^' && code[1] && !code[2]) {
+ /* Control character */
+ if (code[1] == '?')
+ return 0x7f;
+ else
+ return (unsigned char)code[1] & 0x9f;
+ }
+
+
+ for (name = key_names; name->string; name++) {
+ if (!strcasecmp(name->string, code))
+ break;
+ }
+ return name->key; /* KEY_NONE at end of array */
+}
+
+const char *key_code_to_name(int key)
+{
+ static char buf[4];
+ const struct keyname *name;
+
+ if (key < 0)
+ return NULL;
+
+ if (key > ' ' && key < 0x100) {
+ if (key & 0x60) {
+ buf[0] = key;
+ buf[1] = '\0';
+ } else {
+ buf[0] = '^';
+ buf[1] = key | 0x40;
+ buf[2] = '\0';
+ }
+ return buf;
+ }
+
+ for (name = key_names; name->string; name++) {
+ if (key == name->key)
+ return name->string;
+ }
+
+ if (key < ' ') {
+ buf[0] = '^';
+ buf[1] = key | 0x40;
+ buf[2] = '\0';
+ return buf;
+ }
+
+ return NULL;
+}
diff --git a/com32/menu/menu.h b/com32/menu/menu.h
index 36c5669c..1db4d7c9 100644
--- a/com32/menu/menu.h
+++ b/com32/menu/menu.h
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <colortbl.h>
#include <stdbool.h>
+#include <getkey.h>
#include "refstr.h"
/* #define DEBUG 1 */
@@ -186,6 +187,7 @@ extern int shiftkey;
extern int hiddenmenu;
extern int clearmenu;
extern long long totaltimeout;
+extern const char *hide_key[KEY_MAX];
void parse_configs(char **argv);
int draw_background(const char *filename);
diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c
index 06725f37..5b3f6bd1 100644
--- a/com32/menu/menumain.c
+++ b/com32/menu/menumain.c
@@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
- * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2009-2011 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
@@ -726,8 +726,11 @@ static const char *do_hidden_menu(void)
this_timeout = min(timeout_left, CLK_TCK);
key = mygetkey(this_timeout);
- if (key != KEY_NONE)
- return NULL; /* Key pressed */
+ if (key != KEY_NONE) {
+ /* Clear the message from the screen */
+ print_timeout_message(0, HIDDEN_ROW, "");
+ return hide_key[key]; /* NULL if no MENU HIDEKEY in effect */
+ }
timeout_left -= this_timeout;
}
diff --git a/com32/menu/readconfig.c b/com32/menu/readconfig.c
index f3b0f96d..0ac2564a 100644
--- a/com32/menu/readconfig.c
+++ b/com32/menu/readconfig.c
@@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 2004-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2009-2011 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
@@ -37,6 +37,7 @@ int shiftkey = 0; /* Only display menu if shift key pressed */
int hiddenmenu = 0;
int clearmenu = 0;
long long totaltimeout = 0;
+const char *hide_key[KEY_MAX];
/* Keep track of global default */
static int has_ui = 0; /* DEFAULT only counts if UI is found */
@@ -141,6 +142,22 @@ static char *looking_at(char *line, const char *kwd)
return my_isspace(*p) ? p : NULL; /* Must be EOL or whitespace */
}
+/* Get a single word into a new refstr; advances the input pointer */
+static char *get_word(char *str, char **word)
+{
+ char *p = str;
+ char *q;
+
+ while (*p && !my_isspace(*p))
+ p++;
+
+ *word = q = refstr_alloc(p - str);
+ memcpy(q, str, p - str);
+ /* refstr_alloc() already inserted a terminating NUL */
+
+ return p;
+}
+
static struct menu *new_menu(struct menu *parent,
struct menu_entry *parent_entry, const char *label)
{
@@ -703,6 +720,28 @@ static void parse_config_file(FILE * f)
m->menu_background = refdup_word(&p);
} else if ((ep = looking_at(p, "hidden"))) {
hiddenmenu = 1;
+ } else if (looking_at(p, "hiddenkey")) {
+ char *key_name, *k, *ek;
+ const char *command;
+ int key;
+ p = get_word(skipspace(p + 9), &key_name);
+ command = refstrdup(skipspace(p));
+ k = key_name;
+ for (;;) {
+ ek = strchr(k+1, ',');
+ if (ek)
+ *ek = '\0';
+ key = key_name_to_code(k);
+ if (key >= 0) {
+ refstr_put(hide_key[key]);
+ hide_key[key] = refstr_get(command);
+ }
+ if (!ek)
+ break;
+ k = ek+1;
+ }
+ refstr_put(key_name);
+ refstr_put(command);
} else if ((ep = looking_at(p, "clear"))) {
clearmenu = 1;
} else if ((ep = is_message_name(p, &msgnr))) {
@@ -1036,6 +1075,7 @@ void parse_configs(char **argv)
const char *filename;
struct menu *m;
struct menu_entry *me;
+ int k;
empty_string = refstrdup("");
@@ -1097,4 +1137,10 @@ void parse_configs(char **argv)
if (m->onerror)
m->onerror = unlabel(m->onerror);
}
+
+ /* Final global initialization, with all labels known */
+ for (k = 0; k < KEY_MAX; k++) {
+ if (hide_key[k])
+ hide_key[k] = unlabel(hide_key[k]);
+ }
}
diff --git a/com32/samples/keytest.c b/com32/samples/keytest.c
index b4f8f5b0..09c041a1 100644
--- a/com32/samples/keytest.c
+++ b/com32/samples/keytest.c
@@ -37,13 +37,13 @@ static void cooked_keys(void)
if (key == 0x03) {
printf("[done]\n");
exit(0);
- } else if (key == '?')
+ } else if (key == '!')
return;
if (key >= 0x20 && key < 0x100) {
putchar(key);
} else {
- printf("[%04x]", key);
+ printf("[%s,%04x]", key_code_to_name(key), key);
}
}
}
@@ -63,7 +63,8 @@ static void raw_keys(void)
} else if (key == '!')
return;
- printf("<%02x>", key);
+ if (key != EOF)
+ printf("<%02x>", key);
}
}
@@ -72,7 +73,7 @@ int main(void)
console_ansi_raw();
printf("CLK_TCK = %d\n", (int)CLK_TCK);
- printf("Press keys, end with Ctrl-C...\n");
+ printf("Press keys, end with Ctrl-C, ! changes from cooked to raw\n");
for (;;) {
cooked_keys();
diff --git a/diag/geodsp/Makefile b/diag/geodsp/Makefile
index 4c8eff6f..6af0d2db 100644
--- a/diag/geodsp/Makefile
+++ b/diag/geodsp/Makefile
@@ -58,6 +58,7 @@ tidy dist:
rm -Rf *.img
clean: tidy
- rm -f $(BTARGET) *.lst *.bin *_bin.c
+ rm -f *.lst *.bin *_bin.c
spotless: clean
+ rm -f $(BTARGET)
diff --git a/doc/menu.txt b/doc/menu.txt
index e2dd1e1c..620527e6 100644
--- a/doc/menu.txt
+++ b/doc/menu.txt
@@ -48,6 +48,25 @@ MENU HIDDEN
All that is displayed is a timeout message.
+MENU HIDDENKEY key[,key...] command...
+
+ If they key used to interrupt MENU HIDDEN is <key>, then
+ execute the specified command instead of displaying the menu.
+
+ Currently, the following key names are recognized:
+
+ Backspace, Tab, Enter, Esc, Space, F1..F12, Up, Down, Left,
+ Right, PgUp, PgDn, Home, End, Insert, Delete
+
+ ... in addition to all single characters plus the syntax ^X
+ for Ctrl-X. Note that single characters are treated as case
+ sensitive, so a different command can be bound to "A" than
+ "a". One can bind the same command to multiple keys by giving
+ a comma-separated list of keys:
+
+ menu hiddenkey A,a key_a_command
+
+
MENU CLEAR
Clear the screen when exiting the menu, instead of leaving the
diff --git a/extlinux/main.c b/extlinux/main.c
index 21369e46..e5212a95 100755
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -503,19 +503,6 @@ int install_file(const char *path, int devfd, struct stat *rst)
return 1;
}
-/*
- * SYSLINUX installs the string 'SYSLINUX' at offset 3 in the boot
- * sector; this is consistent with FAT filesystems. Earlier versions
- * would install the string "EXTLINUX" instead, handle both.
- */
-int already_installed(int devfd)
-{
- char buffer[8];
-
- xpread(devfd, buffer, 8, 3);
- return !memcmp(buffer, "SYSLINUX", 8) || !memcmp(buffer, "EXTLINUX", 8);
-}
-
#ifdef __KLIBC__
static char devname_buf[64];
@@ -766,7 +753,7 @@ int install_loader(const char *path, int update_only)
if (devfd < 0)
return 1;
- if (update_only && !already_installed(devfd)) {
+ if (update_only && !syslinux_already_installed(devfd)) {
fprintf(stderr, "%s: no previous syslinux boot sector found\n",
program);
close(devfd);
diff --git a/libinstaller/syslxcom.c b/libinstaller/syslxcom.c
index b176f6d7..1de85aa5 100644
--- a/libinstaller/syslxcom.c
+++ b/libinstaller/syslxcom.c
@@ -284,3 +284,16 @@ int sectmap(int fd, sector_t *sectors, int nsectors)
return sectmap_fib(fd, sectors, nsectors);
}
+
+/*
+ * SYSLINUX installs the string 'SYSLINUX' at offset 3 in the boot
+ * sector; this is consistent with FAT filesystems. Earlier versions
+ * would install the string "EXTLINUX" instead, handle both.
+ */
+int syslinux_already_installed(int dev_fd)
+{
+ char buffer[8];
+
+ xpread(dev_fd, buffer, 8, 3);
+ return !memcmp(buffer, "SYSLINUX", 8) || !memcmp(buffer, "EXTLINUX", 8);
+}
diff --git a/libinstaller/syslxcom.h b/libinstaller/syslxcom.h
index 39ca09d3..bf186ca6 100644
--- a/libinstaller/syslxcom.h
+++ b/libinstaller/syslxcom.h
@@ -18,5 +18,6 @@ ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset);
void clear_attributes(int fd);
void set_attributes(int fd);
int sectmap(int fd, sector_t *sectors, int nsectors);
+int syslinux_already_installed(int dev_fd);
#endif
diff --git a/linux/syslinux.c b/linux/syslinux.c
index 97b6a306..c7a9ecc4 100755
--- a/linux/syslinux.c
+++ b/linux/syslinux.c
@@ -382,6 +382,10 @@ int main(int argc, char *argv[])
sync();
rmdir(mntpath);
exit(0);
+ } else if (opt.update_only && !syslinux_already_installed(dev_fd)) {
+ fprintf(stderr, "%s: no previous syslinux boot sector found\n",
+ argv[0]);
+ exit(1);
} else {
fprintf(stderr, "%s: please specify --install or --update for the future\n", argv[0]);
opt.update_only = 0;
diff --git a/syslinux.spec.in b/syslinux.spec.in
index c4b466b5..b82d9a14 100644
--- a/syslinux.spec.in
+++ b/syslinux.spec.in
@@ -11,7 +11,7 @@ Source0: ftp://ftp.kernel.org/pub/linux/utils/boot/syslinux/%{name}-%{VERSION}.t
ExclusiveArch: i386 i486 i586 i686 athlon pentium4 x86_64
Packager: H. Peter Anvin <hpa@zytor.com>
Buildroot: %{_tmppath}/%{name}-%{VERSION}-root
-BuildPrereq: nasm >= 2.03, perl
+BuildRequires: nasm >= 2.03, perl
Autoreq: 0
%ifarch x86_64
Requires: mtools, libc.so.6()(64bit)
@@ -94,6 +94,7 @@ rm -rf %{buildroot}
%{_datadir}/syslinux/*.0
%{_datadir}/syslinux/memdisk
%{_datadir}/syslinux/dosutil/*
+%{_datadir}/syslinux/diag/*
%files devel
%{_datadir}/syslinux/com32