aboutsummaryrefslogtreecommitdiffstats
path: root/com32
diff options
context:
space:
mode:
Diffstat (limited to 'com32')
-rw-r--r--com32/cmenu/libmenu/com32io.c11
-rw-r--r--com32/cmenu/libmenu/com32io.h2
-rw-r--r--com32/include/sys/times.h4
-rw-r--r--com32/include/syslinux/pmapi.h4
-rw-r--r--com32/include/unistd.h3
-rw-r--r--com32/lib/Makefile2
-rw-r--r--com32/lib/sys/sleep.c22
-rw-r--r--com32/lib/sys/times.c8
-rw-r--r--com32/lua/doc/syslinux.asc14
-rw-r--r--com32/lua/src/Makefile2
-rw-r--r--com32/lua/src/syslinux.c18
-rw-r--r--com32/lua/test/vesa.lua10
-rw-r--r--com32/modules/chain.c121
-rw-r--r--com32/modules/ifcpu.c15
14 files changed, 177 insertions, 59 deletions
diff --git a/com32/cmenu/libmenu/com32io.c b/com32/cmenu/libmenu/com32io.c
index 6a27d1a1..8e5016be 100644
--- a/com32/cmenu/libmenu/com32io.c
+++ b/com32/cmenu/libmenu/com32io.c
@@ -27,17 +27,6 @@ void getpos(char *row, char *col, char page)
*col = REG_DL(outreg);
}
-unsigned char sleep(unsigned int msec)
-{
- unsigned long micro = 1000 * msec;
-
- REG_AH(inreg) = 0x86;
- REG_CX(inreg) = (micro >> 16);
- REG_DX(inreg) = (micro & 0xFFFF);
- __intcall(0x15, &inreg, &outreg);
- return REG_AH(outreg);
-}
-
char inputc(char *scancode)
{
syslinux_idle(); /* So syslinux can perform periodic activity */
diff --git a/com32/cmenu/libmenu/com32io.h b/com32/cmenu/libmenu/com32io.h
index 6ff6857e..d9cce3d6 100644
--- a/com32/cmenu/libmenu/com32io.h
+++ b/com32/cmenu/libmenu/com32io.h
@@ -63,6 +63,4 @@ static inline char getvideomode(void) // Get the current video mode
return readbiosb(0x449);
}
-unsigned char sleep(unsigned int msec); // Sleep for specified time
-
#endif
diff --git a/com32/include/sys/times.h b/com32/include/sys/times.h
index 961c7b6d..90470063 100644
--- a/com32/include/sys/times.h
+++ b/com32/include/sys/times.h
@@ -11,10 +11,10 @@ struct tms {
/* Empty */
};
-#define HZ 18 /* Piddly resolution... */
+#define HZ 1000
#define CLK_TCK HZ
-typedef uint16_t clock_t;
+typedef uint32_t clock_t;
clock_t times(struct tms *);
diff --git a/com32/include/syslinux/pmapi.h b/com32/include/syslinux/pmapi.h
index c325b62b..fa390185 100644
--- a/com32/include/syslinux/pmapi.h
+++ b/com32/include/syslinux/pmapi.h
@@ -70,6 +70,10 @@ struct com32_pmapi {
int (*chdir)(const char *);
char *(*getcwd)(char *, size_t);
+
+ /* Should be "const volatile", but gcc miscompiles that sometimes */
+ volatile uint32_t *jiffies;
+ volatile uint32_t *ms_timer;
};
#endif /* _SYSLINUX_PMAPI_H */
diff --git a/com32/include/unistd.h b/com32/include/unistd.h
index c0b52d60..fc514f10 100644
--- a/com32/include/unistd.h
+++ b/com32/include/unistd.h
@@ -25,6 +25,9 @@ __extern int getscreensize(int, int *, int *);
__extern char *getcwd(char *, int);
__extern int chdir(const char *);
+__extern unsigned int sleep(unsigned int);
+__extern unsigned int msleep(unsigned int);
+
/* Standard file descriptor numbers. */
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index e8e89c08..2035df22 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -40,7 +40,7 @@ LIBOBJS = \
libgcc/__divdi3.o libgcc/__moddi3.o \
\
sys/intcall.o sys/farcall.o sys/cfarcall.o sys/zeroregs.o \
- sys/entry.o sys/exit.o sys/argv.o sys/times.o \
+ sys/entry.o sys/exit.o sys/argv.o sys/times.o sys/sleep.o \
sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o sys/ftell.o \
sys/close.o sys/open.o sys/fileread.o sys/fileclose.o \
sys/openmem.o \
diff --git a/com32/lib/sys/sleep.c b/com32/lib/sys/sleep.c
new file mode 100644
index 00000000..8a51c1c0
--- /dev/null
+++ b/com32/lib/sys/sleep.c
@@ -0,0 +1,22 @@
+/*
+ * sys/sleep.c
+ */
+
+#include <unistd.h>
+#include <sys/times.h>
+#include <syslinux/idle.h>
+
+unsigned int msleep(unsigned int msec)
+{
+ clock_t start = times(NULL);
+
+ while (times(NULL) - start < msec)
+ syslinux_idle();
+
+ return 0;
+}
+
+unsigned int sleep(unsigned int seconds)
+{
+ return msleep(seconds * 1000);
+}
diff --git a/com32/lib/sys/times.c b/com32/lib/sys/times.c
index 12ed671c..dd063f37 100644
--- a/com32/lib/sys/times.c
+++ b/com32/lib/sys/times.c
@@ -32,13 +32,11 @@
*/
#include <sys/times.h>
-#include <inttypes.h>
+#include <syslinux/pmapi.h>
#include <com32.h>
clock_t times(struct tms * buf)
{
- (void)buf; /* Ignored */
-
- /* Should we get this via INT 1Ah? */
- return *(uint16_t *) 0x46c;
+ (void)buf;
+ return *__com32.cs_pm->ms_timer;
}
diff --git a/com32/lua/doc/syslinux.asc b/com32/lua/doc/syslinux.asc
index 71593066..eb8ca7f1 100644
--- a/com32/lua/doc/syslinux.asc
+++ b/com32/lua/doc/syslinux.asc
@@ -23,7 +23,11 @@ Modules
SYSLINUX
~~~~~~~~
-.syslinux.sleep(ms)
+.syslinux.sleep(s)
+
+Sleep for +s+ seconds
+
+.syslinux.msleep(ms)
Sleep for +ms+ milliseconds
@@ -102,7 +106,7 @@ _Example_:
syslinux.boot_it(kernel, initrd, "init=/bin/bash")
- syslinux.sleep(20000)
+ syslinux.sleep(20)
......................................................
@@ -259,15 +263,15 @@ _Example_:
vesa.load_background("/background1.jpg")
- syslinux.sleep(1000)
+ syslinux.sleep(1)
for i = 1, #textline do
local c = textline:sub(i,i)
printf("%s", c)
- syslinux.sleep(200)
+ syslinux.msleep(200)
end
- syslinux.sleep(10000)
+ syslinux.sleep(10)
......................................................
diff --git a/com32/lua/src/Makefile b/com32/lua/src/Makefile
index eac3b281..d31c9bdc 100644
--- a/com32/lua/src/Makefile
+++ b/com32/lua/src/Makefile
@@ -43,8 +43,6 @@ LIBLUA_OBJS += dmi.o
LIBLUA_OBJS += pci.o
LIBLUA_OBJS += vesa.o
-# For function sleep() -- XXX: FIX THIS
-LIBLUA_OBJS += ../../cmenu/libmenu/com32io.o
CFLAGS += -DLUA_ANSI
diff --git a/com32/lua/src/syslinux.c b/com32/lua/src/syslinux.c
index be061c4c..cf0189f9 100644
--- a/com32/lua/src/syslinux.c
+++ b/com32/lua/src/syslinux.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <syslinux/boot.h>
#define lnetlib_c /* Define the library */
@@ -209,7 +210,7 @@ static int sl_boot_linux(lua_State * L)
/* DEBUG
printf("Command line: %s\n", newcmdline);
- sleep(1000);
+ msleep(1000);
*/
/* Look for specific command-line arguments we care about */
@@ -269,7 +270,7 @@ static int sl_boot_linux(lua_State * L)
printf("Loading extra file failed\n");
/* DEBUG
- sleep(10000);
+ msleep(10000);
*/
ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, newcmdline);
@@ -279,11 +280,19 @@ static int sl_boot_linux(lua_State * L)
return 0;
}
-/* sleep for msec milliseconds */
+/* sleep for sec seconds */
static int sl_sleep(lua_State * L)
{
+ unsigned int sec = luaL_checkint(L, 1);
+ sleep(sec);
+ return 0;
+}
+
+/* sleep for msec milliseconds */
+static int sl_msleep(lua_State * L)
+{
unsigned int msec = luaL_checkint(L, 1);
- sleep(msec);
+ msleep(msec);
return 0;
}
@@ -403,6 +412,7 @@ static const luaL_reg syslinuxlib[] = {
{"boot_linux", sl_boot_linux},
{"run_kernel_image", sl_run_kernel_image},
{"sleep", sl_sleep},
+ {"msleep", sl_msleep},
{"loadfile", sl_loadfile},
{"filesize", sl_filesize},
{"filename", sl_filename},
diff --git a/com32/lua/test/vesa.lua b/com32/lua/test/vesa.lua
index 7f35e5b5..8913accf 100644
--- a/com32/lua/test/vesa.lua
+++ b/com32/lua/test/vesa.lua
@@ -18,7 +18,7 @@ vesa.setmode()
printf("Hello World! - VESA mode")
-syslinux.sleep(1000)
+syslinux.sleep(1)
-- some text to display "typing style"
textline=[[
@@ -39,17 +39,17 @@ while ( true ) do
vesa.load_background("/PXE-RRZE_small.jpg")
-syslinux.sleep(1000)
+syslinux.sleep(1)
for i = 1, #textline do
local c = textline:sub(i,i)
printf("%s", c)
- syslinux.sleep(200)
+ syslinux.msleep(200)
end
-syslinux.sleep(10000)
+syslinux.sleep(10)
vesa.load_background("/sample2.jpg")
-syslinux.sleep(10000)
+syslinux.sleep(10)
end
diff --git a/com32/modules/chain.c b/com32/modules/chain.c
index 4f5baf19..48a83d2a 100644
--- a/com32/modules/chain.c
+++ b/com32/modules/chain.c
@@ -78,7 +78,11 @@
*
* grub=<loader>
* same as seg=0x800 file=<loader> & jumping to seg 0x820,
- * used with GRUB stage2 files.
+ * used with GRUB Legacy stage2 files.
+ *
+ * grubcfg=<filename>
+ * set an alternative config filename in stage2 of Grub Legacy,
+ * only applicable in combination with "grub=<loader>".
*
* grldr=<loader>
* pass the partition number to GRUB4DOS,
@@ -125,6 +129,7 @@ static struct options {
bool cmldr;
bool grub;
bool grldr;
+ const char *grubcfg;
bool swap;
bool hide;
bool sethidden;
@@ -1276,7 +1281,8 @@ Options: file=<loader> Load and execute file, instead of boot sector\n\
freedos=<loader> Load FreeDOS KERNEL.SYS\n\
msdos=<loader> Load MS-DOS IO.SYS\n\
pcdos=<loader> Load PC-DOS IBMBIO.COM\n\
- grub=<loader> Load GRUB stage2\n\
+ grub=<loader> Load GRUB Legacy stage2\n\
+ grubcfg=<filename> Set alternative config filename for GRUB Legacy\n\
grldr=<loader> Load GRUB4DOS grldr\n\
seg=<segment> Jump to <seg>:0000, instead of 0000:7C00\n\
swap Swap drive numbers, if bootdisk is not fd0/hd0\n\
@@ -1349,6 +1355,8 @@ int main(int argc, char *argv[])
opt.seg = 0x800; /* stage2 wants this address */
opt.loadfile = argv[i] + 5;
opt.grub = true;
+ } else if (!strncmp(argv[i], "grubcfg=", 8)) {
+ opt.grubcfg = argv[i] + 8;
} else if (!strncmp(argv[i], "grldr=", 6)) {
opt.loadfile = argv[i] + 6;
opt.grldr = true;
@@ -1392,6 +1400,11 @@ int main(int argc, char *argv[])
}
}
+ if (opt.grubcfg && !opt.grub) {
+ error("grubcfg=<filename> must be used together with grub=<loader>.\n");
+ goto bail;
+ }
+
if (opt.seg) {
regs.es = regs.cs = regs.ss = regs.ds = regs.fs = regs.gs = opt.seg;
} else {
@@ -1583,15 +1596,105 @@ int main(int argc, char *argv[])
}
if (opt.grub) {
- regs.ip = 0x200; /* jump 0x200 bytes into the loadfile */
+ /* Layout of stage2 file (from byte 0x0 to 0x270) */
+ struct grub_stage2_patch_area {
+ /* 0x0 to 0x205 */
+ char unknown[0x206];
+ /* 0x206: compatibility version number major */
+ uint8_t compat_version_major;
+ /* 0x207: compatibility version number minor */
+ uint8_t compat_version_minor;
+
+ /* 0x208: install_partition variable */
+ struct {
+ /* 0x208: sub-partition in sub-partition part2 */
+ uint8_t part3;
+ /* 0x209: sub-partition in top-level partition */
+ uint8_t part2;
+ /* 0x20a: top-level partiton number */
+ uint8_t part1;
+ /* 0x20b: BIOS drive number (must be 0) */
+ uint8_t drive;
+ } __attribute__ ((packed)) install_partition;
+
+ /* 0x20c: deprecated (historical reason only) */
+ uint32_t saved_entryno;
+ /* 0x210: stage2_ID: will always be STAGE2_ID_STAGE2 = 0 in stage2 */
+ uint8_t stage2_id;
+ /* 0x211: force LBA */
+ uint8_t force_lba;
+ /* 0x212: version string (will probably be 0.97) */
+ char version_string[5];
+ /* 0x217: config filename */
+ char config_file[89];
+ /* 0x270: start of code (after jump from 0x200) */
+ char codestart[1];
+ } __attribute__ ((packed)) *stage2;
+
+ if (data[ndata].size < sizeof(struct grub_stage2_patch_area)) {
+ error
+ ("The file specified by grub=<loader> is to small to be stage2 of GRUB Legacy.\n");
+ goto bail;
+ }
+
+ stage2 = data[ndata].data;
- /* GRUB's stage2 wants the partition number in the install_partition
- * variable, located at memory address 0x8208.
- * We only need to change the value of memory address 0x820a too:
- * -1: whole drive (default)
+ /*
+ * Check the compatibility version number to see if we loaded a real
+ * stage2 file or a stage2 file that we support.
+ */
+ if (stage2->compat_version_major != 3
+ || stage2->compat_version_minor != 2) {
+ error
+ ("The file specified by grub=<loader> is not a supported stage2 GRUB Legacy binary\n");
+ goto bail;
+ }
+
+ /* jump 0x200 bytes into the loadfile */
+ regs.ip = 0x200;
+
+ /*
+ * GRUB Legacy wants the partition number in the install_partition
+ * variable, located at offset 0x208 of stage2.
+ * When GRUB Legacy is loaded, it is located at memory address 0x8208.
+ *
+ * It looks very similar to the "boot information format" of the
+ * Multiboot specification:
+ * http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format
+ *
+ * 0x208 = part3: sub-partition in sub-partition part2
+ * 0x209 = part2: sub-partition in top-level partition
+ * 0x20a = part1: top-level partition number
+ * 0x20b = drive: BIOS drive number (must be 0)
+ *
+ * GRUB Legacy doesn't store the BIOS drive number at 0x20b, but at
+ * another location.
+ *
+ * Partition numbers always start from zero.
+ * Unused partition bytes must be set to 0xFF.
+ *
+ * We only care about top-level partition, so we only need to change
+ * "part1" to the appropriate value:
+ * -1: whole drive (default) (-1 = 0xFF)
* 0-3: primary partitions
- * 4-*: logical partitions */
- ((uint8_t*) data[ndata].data)[0x20a] = (uint8_t)(whichpart - 1);
+ * 4-*: logical partitions
+ */
+ stage2->install_partition.part1 = whichpart - 1;
+
+ /*
+ * Grub Legacy reserves 89 bytes (from 0x8217 to 0x826f) for the
+ * config filename. The filename passed via grubcfg= will overwrite
+ * the default config filename "/boot/grub/menu.lst".
+ */
+ if (opt.grubcfg) {
+ if (strlen(opt.grubcfg) > sizeof(stage2->config_file) - 1) {
+ error
+ ("The config filename length can't exceed 88 characters.\n");
+ goto bail;
+ }
+
+ strcpy((char *)stage2->config_file, opt.grubcfg);
+ }
}
ndata++;
diff --git a/com32/modules/ifcpu.c b/com32/modules/ifcpu.c
index cf6282f5..ae6893b9 100644
--- a/com32/modules/ifcpu.c
+++ b/com32/modules/ifcpu.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <string.h>
#include <cpuid.h>
+#include <unistd.h>
#include <syslinux/boot.h>
#include <com32.h>
#include <consoles.h>
@@ -61,18 +62,6 @@ static void usage(void)
"if you want to match many cpu features, just separate them with a single space.\n");
}
-static unsigned char sleep(unsigned int msec)
-{
- unsigned long micro = 1000 * msec;
- com32sys_t inreg, outreg;
-
- REG_AH(inreg) = 0x86;
- REG_CX(inreg) = (micro >> 16);
- REG_DX(inreg) = (micro & 0xFFFF);
- __intcall(0x15, &inreg, &outreg);
- return REG_AH(outreg);
-}
-
/* XXX: this really should be librarized */
static void boot_args(char **args)
{
@@ -172,7 +161,7 @@ int main(int argc, char *argv[])
hardware_matches ? *args[0] : *args[1]);
printf("Sleeping 5sec before booting\n");
if (!dryrun)
- sleep(5000);
+ sleep(5);
}
if (!dryrun)