summaryrefslogtreecommitdiff
path: root/com32
diff options
context:
space:
mode:
authorhpa <hpa>2005-08-21 05:11:50 +0000
committerhpa <hpa>2005-08-21 05:11:50 +0000
commit87575da8034373b0bf9ea147329b6d24dc5a825a (patch)
tree43da9ec5949105159f1615694be826d0cbe7f2c8 /com32
parente5450b7cd33808991aa8d0747523a6874c4204e5 (diff)
downloadsyslinux-87575da8034373b0bf9ea147329b6d24dc5a825a.tar.gz
Add more low-level API function to load the kernel, and make the
menu subsystem use it.
Diffstat (limited to 'com32')
-rw-r--r--com32/include/com32.h21
-rw-r--r--com32/modules/menu.c33
2 files changed, 46 insertions, 8 deletions
diff --git a/com32/include/com32.h b/com32/include/com32.h
index 29656e47..5706683c 100644
--- a/com32/include/com32.h
+++ b/com32/include/com32.h
@@ -88,18 +88,35 @@ void __farcall(uint16_t __es, uint16_t __eo,
* 0..0xFFFFF and real-mode style SEG:OFFS pointers. Note that a
* 32-bit linear pointer is not compatible with a SEG:OFFS pointer
* stored in two consecutive 16-bit words.
+ *
+ * Use OFFS_WRT() if you want to compute an offset relative to a
+ * specific segment. OFFS_VALID() will return whether or not the
+ * pointer is actually reachable from the target segment.
*/
-static inline uint16_t SEG(void *__p)
+static inline uint16_t SEG(const volatile void *__p)
{
return (uint16_t)(((uintptr_t)__p) >> 4);
}
-static inline uint16_t OFFS(void *__p)
+static inline uint16_t OFFS(const volatile void *__p)
{
/* The double cast here is to shut up gcc */
return (uint16_t)(uintptr_t)__p & 0x000F;
}
+static inline uint16_t OFFS_WRT(const volatile void *__p, uint16_t seg)
+{
+ return (uint16_t)((uintptr_t)__p - ((uintptr_t)seg << 4));
+}
+
+static inline int OFFS_VALID(const volatile void *__p, uint16_t seg)
+{
+ uintptr_t __segstart = (uintptr_t)seg << 4;
+ uintptr_t __ptr = (uintptr_t)__p;
+
+ return (__ptr >= __segstart) && (__ptr <= __segstart+0xffff);
+}
+
static inline void *MK_PTR(uint16_t __seg, uint16_t __offs)
{
return (void *)((__seg << 4) + __offs);
diff --git a/com32/modules/menu.c b/com32/modules/menu.c
index 85ff8d5a..d67f5b55 100644
--- a/com32/modules/menu.c
+++ b/com32/modules/menu.c
@@ -588,10 +588,11 @@ run_menu(void)
static void
-execute(const char *cmdline)
+execute(char *cmdline)
{
#ifdef __COM32__
- static com32sys_t ireg;
+ com32sys_t ireg;
+ memset(&ireg, 0, sizeof ireg);
if ( !strncmp(cmdline, ".localboot", 10) && isspace(cmdline[10]) ) {
unsigned long localboot = strtoul(cmdline+10, NULL, 0);
@@ -599,10 +600,30 @@ execute(const char *cmdline)
ireg.eax.w[0] = 0x0014; /* Local boot */
ireg.edx.w[0] = localboot;
} else {
- strcpy(__com32.cs_bounce, cmdline);
- ireg.eax.w[0] = 0x0003; /* Run command */
- ireg.ebx.w[0] = OFFS(__com32.cs_bounce);
- ireg.es = SEG(__com32.cs_bounce);
+ const char *p;
+ char *q = __com32.cs_bounce;
+ const char *kernel, *args;
+
+ kernel = q;
+ p = cmdline;
+ while ( *p && !isspace(*p) ) {
+ *p++ = *q++;
+ }
+ *q++ = '\0';
+
+ args = q;
+ while ( *p && isspace(*p) )
+ p++;
+
+ strcpy(q, p);
+
+ ireg.eax.w[0] = 0x0016;
+ ireg.esi.w[0] = OFFS(kernel);
+ ireg.ds = SEG(kernel);
+ ireg.ebx.w[0] = OFFS(args);
+ ireg.es = SEG(kernel);
+ /* ireg.ecx.l = 0; */ /* We do ipappend "manually" */
+ /* ireg.edx.l = 0; */
}
__intcall(0x22, &ireg, NULL);