menu subsystem use it.
* 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);
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);
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);
All of these terminate the program.
+
INT 21h AH=01h [2.01] Get Key with Echo
Reads a key from the console input, with echo to the console
output. The read character is returned in AL. Extended
characters received from the keyboard are returned as NUL (00h)
+ the extended character code.
+
INT 21h AH=02h [2.01] Write Character
Writes a character in DL to the console (video and serial)
output.
+
INT 21h AH=04h [2.01] Write Character to Serial Port
Writes a character in DL to the serial console output
(if enabled.) If no serial port is configured, this routine
does nothing.
+
INT 21h AH=08h [2.09] Get Key without Echo
Reads a key fron the console input, without echoing it to the
console output. The read character is returned in AL.
+
INT 21h AH=09h [2.01] Write DOS String to Console
Writes a DOS $-terminated string in DS:DX to the console.
+
INT 21h AH=0Bh [2.00] Check Keyboard
Returns AL=FFh if there is a keystroke waiting (which can then
be read with INT 21h, AH=01h or AH=08h), otherwise AL=00h.
+
INT 21h AH=30h [2.00] Check DOS Version
This function returns AX=BX=CX=DX=0, corresponding to a
1 Idle loop call (AX=0013h) is a no-op
All other flags are reserved.
+
+
+AX=0016h [3.10] Run kernel image
+ Input: AX 0016h
+ DS:SI Filename of kernel image (zero-terminated string)
+ ES:BX Command line (zero-terminated string)
+ ECX IPAPPEND flags [PXELINUX]
+ EDX Reserved - MUST BE ZERO
+ Output: Does not return if successful; returns with CF=1 if
+ the kernel image is not found.
+
+ This function is similiar to AX=0003h Run command, except that
+ the filename and command line are treated as if specified in a
+ KERNEL and APPEND statement of a LABEL statement, which means:
+
+ - The filename has to be exact; no variants are tried;
+ - No global APPEND statement is applied;
+ - ALLOWOPTIONS and IMPLICIT statements in the configuration
+ file do not apply. It is therefore important that the
+ COMBOOT module doesn't allow the end user to violate the
+ intent of the administrator.
+
+ Additionally, this function returns with a failure if the file
+ doesn't exist, instead of returning to the command line. (It
+ may still return to the command line if the image is somehow
+ corrupt, however.)
clc
ret
+;
+; INT 22h AX=0016h Run kernel image
+;
+comapi_runkernel:
+ push ds
+ mov ds,P_DS
+ mov si,P_SI
+ mov di,KernelName
+ push di
+ call mangle_name
+ pop di
+ pop ds
+ call searchdir
+ jz comapi_err ; Kernel doesn't exist
+
+ ; The kernel image was found, so we can load it...
+ mov [Kernel_SI],si
+ mov [Kernel_EAX],ax
+ mov [Kernel_EAX+2],dx
+
+ push es
+ mov ds,P_ES
+ mov si,P_BX
+ push word real_mode_seg
+ pop es
+ mov di,cmd_line_here
+ call strcpy
+ dec di
+ mov [CmdLinePtr],di
+ pop es
+
+%if IS_PXELINUX
+ mov al,P_CL
+ mov [IPAppend],al
+%endif
+
+ mov bx,kernel_good_saved
+
section .data
int21_table:
int21 00h, comboot_return
;
; Anything else is assumed to be a Linux kernel.
;
+ section .bss
+ alignb 4
+Kernel_EAX resd 1
+Kernel_SI resw 1
+
+ section .text
+kernel_good_saved:
+ ; Alternate entry point for which the return from
+ ; searchdir is stored in memory. This is used for
+ ; COMBOOT function INT 22h, AX=0016h.
+ mov si,[Kernel_SI]
+ mov eax,[Kernel_EAX]
+ mov dx,[Kernel_EAX+2]
+
kernel_good:
pusha
mov si,KernelName