diff options
author | hpa <hpa> | 2005-08-21 05:11:50 +0000 |
---|---|---|
committer | hpa <hpa> | 2005-08-21 05:11:50 +0000 |
commit | 87575da8034373b0bf9ea147329b6d24dc5a825a (patch) | |
tree | 43da9ec5949105159f1615694be826d0cbe7f2c8 /com32 | |
parent | e5450b7cd33808991aa8d0747523a6874c4204e5 (diff) | |
download | syslinux-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.h | 21 | ||||
-rw-r--r-- | com32/modules/menu.c | 33 |
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); |