[syslinux] Path simple menu integrated progress indicator
Ayvaz, James
James.Ayvaz at hp.com
Fri Apr 23 08:41:55 PDT 2010
This patch modifies the simple menu com32 program to include integrated load progress. It also adds new options to the simple menu configuration
MENU LOADMSG -- allows the user to specify the text to display when loading
MENU LOADMSGROW -- controls where the text is written
Example configuration:
MENU LOADMSG Booting
MENU LOADMSGROW 25
It works with my setup, please let me know if you find any bugs or spot any problems. Thank you.
diff -uprN syslinux-3.86-vanilla//com32/include/syslinux/loadfile.h syslinux-3.86/com32/include/syslinux/loadfile.h
--- syslinux-3.86-vanilla//com32/include/syslinux/loadfile.h 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/include/syslinux/loadfile.h 2010-04-15 10:14:24.000000000 -0500
@@ -9,7 +9,9 @@
#define LOADFILE_ZERO_PAD 64
int loadfile(const char *, void **, size_t *);
+int loadfile_w_callback(const char *filename, void **ptr, size_t *len, void (*callback)(const char* file, size_t cur, size_t total));
int zloadfile(const char *, void **, size_t *);
int floadfile(FILE *, void **, size_t *, const void *, size_t);
-
+int floadfile_w_callback(FILE *f, void **ptr, size_t *len, const void *prefix,
+ size_t prefix_len, const char *filename, void (*callback)(const char* file, size_t cur, size_t total));
#endif
diff -uprN syslinux-3.86-vanilla//com32/include/syslinux/vesacon.h syslinux-3.86/com32/include/syslinux/vesacon.h
--- syslinux-3.86-vanilla//com32/include/syslinux/vesacon.h 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/include/syslinux/vesacon.h 2010-04-15 08:21:00.000000000 -0500
@@ -32,6 +32,7 @@
int vesacon_default_background(void);
void vesacon_set_resolution(int, int);
+void vesacon_get_resolution(int *, int *);
int vesacon_load_background(const char *);
int vesacon_set_background(unsigned int);
void vesacon_cursor_enable(bool);
diff -uprN syslinux-3.86-vanilla//com32/lib/sys/vesacon_write.c syslinux-3.86/com32/lib/sys/vesacon_write.c
--- syslinux-3.86-vanilla//com32/lib/sys/vesacon_write.c 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/lib/sys/vesacon_write.c 2010-04-15 08:20:46.000000000 -0500
@@ -85,6 +85,15 @@ void vesacon_set_resolution(int x, int y
vesacon_resolution.y = y;
}
+/* Get current resolution */
+void vesacon_get_resolution(int *x, int *y)
+{
+ x = vesacon_resolution.x;
+ y = vesacon_resolution.y;
+}
+
+
+
/* Common setup */
int __vesacon_open(struct file_info *fp)
{
diff -uprN syslinux-3.86-vanilla//com32/lib/syslinux/floadfile.c syslinux-3.86/com32/lib/syslinux/floadfile.c
--- syslinux-3.86-vanilla//com32/lib/syslinux/floadfile.c 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/lib/syslinux/floadfile.c 2010-04-15 10:15:10.000000000 -0500
@@ -106,3 +106,64 @@ err:
free(data);
return -1;
}
+
+int floadfile_w_callback(FILE *f, void **ptr, size_t *len, const void *prefix,
+ size_t prefix_len, const char *filename, void (*callback)(const char *name, size_t cur, size_t total))
+{
+ struct stat st;
+ void *data, *dp;
+ size_t alen, clen, rlen, xlen, flen;
+
+ clen = alen = 0;
+ data = NULL;
+
+ if ( fstat(fileno(f), &st) )
+ goto err;
+
+
+ if (!S_ISREG(st.st_mode)) {
+ /* Not a regular file, we can't assume we know the file size */
+ flen = -1;
+ }
+ else {
+ flen = st.st_size + prefix_len - ftell(f);
+ }
+
+ if (prefix_len) {
+ clen = alen = prefix_len;
+ data = malloc(prefix_len);
+ if (!data)
+ goto err;
+
+ memcpy(data, prefix, prefix_len);
+ }
+
+ do {
+ alen += INCREMENTAL_CHUNK;
+ dp = realloc(data, alen);
+ if (!dp)
+ goto err;
+ data = dp;
+
+ rlen = fread((char *)data+clen, 1, alen-clen, f);
+ clen += rlen;
+ callback(filename, clen, flen);
+ } while (clen == alen);
+
+ *len = clen;
+ xlen = (clen + LOADFILE_ZERO_PAD-1) & ~(LOADFILE_ZERO_PAD-1);
+ dp = realloc(data, xlen);
+ if (dp)
+ data = dp;
+ *ptr = data;
+
+ memset((char *)data + clen, 0, xlen-clen);
+ return 0;
+
+ err:
+ if (data)
+ free(data);
+ return -1;
+}
+
+
diff -uprN syslinux-3.86-vanilla//com32/lib/syslinux/loadfile.c syslinux-3.86/com32/lib/syslinux/loadfile.c
--- syslinux-3.86-vanilla//com32/lib/syslinux/loadfile.c 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/lib/syslinux/loadfile.c 2010-04-15 10:12:32.000000000 -0500
@@ -61,3 +61,24 @@ int loadfile(const char *filename, void
errno = e;
return rv;
}
+
+int loadfile_w_callback(const char *filename, void **ptr, size_t *len, void (*callback)(const char* name, size_t cur, size_t total))
+{
+ FILE *f;
+ int rv, e;
+
+ f = fopen(filename, "r");
+ if ( !f )
+ return -1;
+
+ rv = floadfile_w_callback(f, ptr, len, NULL, 0, filename, callback);
+ e = errno;
+
+ fclose(f);
+
+ if (rv)
+ errno = e;
+ return rv;
+}
+
+
diff -uprN syslinux-3.86-vanilla//com32/menu/execute.c syslinux-3.86/com32/menu/execute.c
--- syslinux-3.86-vanilla//com32/menu/execute.c 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/menu/execute.c 2010-04-15 10:10:29.000000000 -0500
@@ -10,20 +10,123 @@
*
* ----------------------------------------------------------------------- */
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <syslinux/linux.h>
+
#include <com32.h>
#include "menu.h"
+bool opt_quiet = false;
+
+static const char *refdup_word(char **p)
+{
+ char *sp = *p;
+ char *ep = sp;
+
+ while (*ep && !my_isspace(*ep))
+ ep++;
+
+ *p = ep;
+ return refstrndup(sp, ep - sp);
+}
+
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+char *skip_spaces(char *s)
+{
+ while(*s && (*s == ' ' || *s == '\t')) s++;
+
+ return s;
+}
+
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+char *skip_nonspaces(char *s)
+{
+ while(*s && *s != ' ' && *s != '\t') s++;
+
+ return s;
+}
+
+/* Search for a boolean argument; return its position, or 0 if not present */
+static int find_boolean(char **argv, const char *argument)
+{
+ char **arg;
+
+ for (arg = argv; *arg; arg++) {
+ if (!strcmp(*arg, argument))
+ return (arg - argv) + 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Find the last instance of a particular command line argument
+ * (which should include the final =; do not use for boolean arguments)
+ * Note: the resulting string is typically not null-terminated.
+ */
+const char *find_argument(const char *cmdline, const char *argument)
+{
+ const char *found = NULL;
+ const char *p = cmdline;
+ bool was_space = true;
+ size_t la = strlen(argument);
+
+ while (*p) {
+ if (my_isspace(*p)) {
+ was_space = true;
+ } else if (was_space) {
+ if (!memcmp(p, argument, la))
+ found = p + la;
+ was_space = false;
+ }
+ p++;
+ }
+
+ return found;
+}
+
+void console_prepare(void)
+{
+ fputs("\033[0m\033[25l", stdout);
+}
+
+void console_cleanup(void)
+{
+ /* For the serial console, be nice and clean up */
+ fputs("\033[0m", stdout);
+}
+
+void
+clear_screen(void)
+{
+ fputs("\033e\033%@\033)0\033(B\1#0\033[?25l\033[2J", stdout);
+}
+
+int initramfs_load_archive_w_callback(struct initramfs *ihead, const char *filename, void (*callback)(const char* name, size_t cur, size_t total))
+{
+ void *data;
+ size_t len;
+
+ if (loadfile_w_callback(filename, &data, &len, callback))
+ return -1;
+
+ return initramfs_add_data(ihead, data, len, len, 4);
+}
+
+
void execute(const char *cmdline, enum kernel_type type)
{
com32sys_t ireg;
- const char *p, *const *pp;
+ char *p, *const *pp;
char *q = __com32.cs_bounce;
const char *kernel, *args;
- memset(&ireg, 0, sizeof ireg);
-
kernel = q;
p = cmdline;
while (*p && !my_isspace(*p)) {
@@ -48,22 +151,60 @@ void execute(const char *cmdline, enum k
}
if (type == KT_LOCALBOOT) {
- ireg.eax.w[0] = 0x0014; /* Local boot */
- ireg.edx.w[0] = strtoul(kernel, NULL, 0);
+ syslinux_local_boot(strtoul(kernel,NULL,0));
} else {
- if (type < KT_KERNEL)
- type = KT_KERNEL;
- ireg.eax.w[0] = 0x0016; /* Run kernel image */
- ireg.esi.w[0] = OFFS(kernel);
- ireg.ds = SEG(kernel);
- ireg.ebx.w[0] = OFFS(args);
- ireg.es = SEG(args);
- ireg.edx.l = type - KT_KERNEL;
- /* ireg.ecx.l = 0; *//* We do ipappend "manually" */
+ size_t kernel_size = 0, initrd_size = 0;
+ char* kernel_name;
+ void* kernel_data, *initrd_buf;
+ char *s, *s0, *t, *initrd_arg;
+ struct initramfs *initramfs = NULL;
+
+ char *arg;
+ opt_quiet = false;
+
+ kernel_name = refdup_word(&cmdline);
+ loadfile(kernel_name, &kernel_data, &kernel_size);
+ if(!kernel_data) {
+ fprintf(stdout, "%s: read error\n", kernel_name);
+ return; /* Error! */
+ }
+
+ char *cmdline2 = malloc(strlen(cmdline) + strlen(kernel_name) + 12);
+ memset(cmdline2, 0, (strlen(cmdline) + strlen(kernel_name) + 12));
+ strcat(cmdline2, kernel_name);
+ strcat(cmdline2, " ");
+ strcat(cmdline2, cmdline);
+
+ /* Initialize the initramfs chain */
+ initramfs = initramfs_init();
+ if (!initramfs)
+ return;
+
+
+ if ((arg = find_argument(cmdline2, "initrd="))) {
+ do {
+ char* initrdarg = refdup_word(&arg);
+ p = strchr(initrdarg, ',');
+ if (p)
+ *p = '\0';
+
+ if (initramfs_load_archive_w_callback(initramfs, initrdarg, draw_progress)) {
+ printf("failed!\n");
+ return 1;
+ }
+
+ if (p)
+ *p++ = ',';
+ } while ((arg = p));
+ }
+
+ console_cleanup();
+ console_prepare();
+
+ syslinux_boot_linux(kernel_data, kernel_size, initramfs, cmdline2);
}
- __intcall(0x22, &ireg, NULL);
/* If this returns, something went bad; return to menu */
}
diff -uprN syslinux-3.86-vanilla//com32/menu/menu.c syslinux-3.86/com32/menu/menu.c
--- syslinux-3.86-vanilla//com32/menu/menu.c 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/menu/menu.c 2010-04-15 10:07:34.000000000 -0500
@@ -42,3 +42,25 @@ void start_console(void)
{
console_ansi_raw();
}
+
+void draw_progress(const char *file, size_t cur, size_t total)
+{
+ static bool once = true;
+ float percent;
+ percent = ((float)cur / (float)total) * 100.0;
+
+ if (opt_quiet)
+ return;
+
+ if (once) {
+ printf("Loading %s", file);
+ once = false;
+ }
+
+ printf(".");
+
+ if (percent>=100)
+ printf("ok\n");
+}
+
+
diff -uprN syslinux-3.86-vanilla//com32/menu/menu.h syslinux-3.86/com32/menu/menu.h
--- syslinux-3.86-vanilla//com32/menu/menu.h 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/menu/menu.h 2010-04-15 10:08:01.000000000 -0500
@@ -97,6 +97,7 @@ enum parameter_number {
P_PASSWD_MARGIN,
P_MENU_ROWS,
P_TABMSG_ROW,
+ P_LOADMSG_ROW,
P_CMDLINE_ROW,
P_END_ROW,
P_PASSWD_ROW,
@@ -115,6 +116,7 @@ enum message_number {
MSG_TITLE,
MSG_AUTOBOOT,
MSG_TAB,
+ MSG_LOAD,
MSG_NOTAB,
MSG_PASSPROMPT,
@@ -188,6 +190,7 @@ int draw_background(const char *filename
void set_resolution(int x, int y);
void start_console(void);
void local_cursor_enable(bool);
+void draw_progress(const char *file, size_t cur, size_t total);
static inline int my_isspace(char c)
{
@@ -227,4 +230,27 @@ void execute(const char *cmdline, enum k
/* drain.c */
void drain_keyboard(void);
+extern bool opt_quiet;
+
+/* The symbol "cm" always refers to the current menu across this file... */
+extern struct menu *cm;
+
+/* These macros assume "cm" is a pointer to the current menu */
+#define WIDTH (cm->mparm[P_WIDTH])
+#define MARGIN (cm->mparm[P_MARGIN])
+#define PASSWD_MARGIN (cm->mparm[P_PASSWD_MARGIN])
+#define MENU_ROWS (cm->mparm[P_MENU_ROWS])
+#define TABMSG_ROW (cm->mparm[P_TABMSG_ROW]+VSHIFT)
+#define LOADMSG_ROW (cm->mparm[P_LOADMSG_ROW]+VSHIFT)
+#define CMDLINE_ROW (cm->mparm[P_CMDLINE_ROW]+VSHIFT)
+#define END_ROW (cm->mparm[P_END_ROW])
+#define PASSWD_ROW (cm->mparm[P_PASSWD_ROW]+VSHIFT)
+#define TIMEOUT_ROW (cm->mparm[P_TIMEOUT_ROW]+VSHIFT)
+#define HELPMSG_ROW (cm->mparm[P_HELPMSG_ROW]+VSHIFT)
+#define HELPMSGEND_ROW (cm->mparm[P_HELPMSGEND_ROW])
+#define HSHIFT (cm->mparm[P_HSHIFT])
+#define VSHIFT (cm->mparm[P_VSHIFT])
+#define HIDDEN_ROW (cm->mparm[P_HIDDEN_ROW])
+
+
#endif /* MENU_H */
diff -uprN syslinux-3.86-vanilla//com32/menu/menumain.c syslinux-3.86/com32/menu/menumain.c
--- syslinux-3.86-vanilla//com32/menu/menumain.c 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/menu/menumain.c 2010-04-15 13:08:03.000000000 -0500
@@ -29,11 +29,13 @@
#include <limits.h>
#include <com32.h>
#include <syslinux/adv.h>
+#include <console.h>
#include "menu.h"
/* The symbol "cm" always refers to the current menu across this file... */
-static struct menu *cm;
+//static struct menu *cm;
+struct menu *cm;
const struct menu_parameter mparm[NPARAMS] = {
[P_WIDTH] = {"width", 0},
@@ -41,6 +43,7 @@ const struct menu_parameter mparm[NPARAM
[P_PASSWD_MARGIN] = {"passwordmargin", 3},
[P_MENU_ROWS] = {"rows", 12},
[P_TABMSG_ROW] = {"tabmsgrow", 18},
+ [P_LOADMSG_ROW] = {"loadmsgrow", 18},
[P_CMDLINE_ROW] = {"cmdlinerow", 18},
[P_END_ROW] = {"endrow", -1},
[P_PASSWD_ROW] = {"passwordrow", 11},
@@ -52,22 +55,6 @@ const struct menu_parameter mparm[NPARAM
[P_HIDDEN_ROW] = {"hiddenrow", -2},
};
-/* These macros assume "cm" is a pointer to the current menu */
-#define WIDTH (cm->mparm[P_WIDTH])
-#define MARGIN (cm->mparm[P_MARGIN])
-#define PASSWD_MARGIN (cm->mparm[P_PASSWD_MARGIN])
-#define MENU_ROWS (cm->mparm[P_MENU_ROWS])
-#define TABMSG_ROW (cm->mparm[P_TABMSG_ROW]+VSHIFT)
-#define CMDLINE_ROW (cm->mparm[P_CMDLINE_ROW]+VSHIFT)
-#define END_ROW (cm->mparm[P_END_ROW])
-#define PASSWD_ROW (cm->mparm[P_PASSWD_ROW]+VSHIFT)
-#define TIMEOUT_ROW (cm->mparm[P_TIMEOUT_ROW]+VSHIFT)
-#define HELPMSG_ROW (cm->mparm[P_HELPMSG_ROW]+VSHIFT)
-#define HELPMSGEND_ROW (cm->mparm[P_HELPMSGEND_ROW])
-#define HSHIFT (cm->mparm[P_HSHIFT])
-#define VSHIFT (cm->mparm[P_VSHIFT])
-#define HIDDEN_ROW (cm->mparm[P_HIDDEN_ROW])
-
static char *pad_line(const char *text, int align, int width)
{
static char buffer[MAX_CMDLINE_LEN];
diff -uprN syslinux-3.86-vanilla//com32/menu/readconfig.c syslinux-3.86/com32/menu/readconfig.c
--- syslinux-3.86-vanilla//com32/menu/readconfig.c 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/menu/readconfig.c 2010-04-15 09:36:23.000000000 -0500
@@ -49,6 +49,7 @@ static struct menu_entry **all_entries_e
static const struct messages messages[MSG_COUNT] = {
[MSG_AUTOBOOT] = {"autoboot", "Automatic boot in # second{,s}..."},
[MSG_TAB] = {"tabmsg", "Press [Tab] to edit options"},
+ [MSG_LOAD] = {"loadmsg", "Loading"},
[MSG_NOTAB] = {"notabmsg", ""},
[MSG_PASSPROMPT] = {"passprompt", "Password required"},
};
diff -uprN syslinux-3.86-vanilla//com32/menu/vesamenu.c syslinux-3.86/com32/menu/vesamenu.c
--- syslinux-3.86-vanilla//com32/menu/vesamenu.c 2010-03-31 11:24:25.000000000 -0500
+++ syslinux-3.86/com32/menu/vesamenu.c 2010-04-15 13:05:52.000000000 -0500
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <console.h>
+#include <syslinux/video.h>
#include <syslinux/vesacon.h>
#include "menu.h"
@@ -50,3 +51,17 @@ void start_console(void)
{
openconsole(&dev_rawcon_r, &dev_vesaserial_w);
}
+
+void draw_progress(const char *file, size_t cur, size_t total)
+{
+ int i;
+ float percent, bars, fill;
+ percent = ((float)cur / (float)total) * 100.0;
+
+ const char* loadmsg = cm->messages[MSG_LOAD];
+ int loadmsg_len = strlen(loadmsg);
+
+ printf("\033[%d;%dH\2#14%s %d%%",
+ LOADMSG_ROW, 1 + HSHIFT + ((WIDTH - loadmsg_len) >> 1), loadmsg, (int)percent);
+}
+
More information about the Syslinux
mailing list