Add more low-level API function to load the kernel, and make the
authorhpa <hpa>
Sun, 21 Aug 2005 05:11:50 +0000 (05:11 +0000)
committerhpa <hpa>
Sun, 21 Aug 2005 05:11:50 +0000 (05:11 +0000)
menu subsystem use it.

com32/include/com32.h
com32/modules/menu.c
comboot.doc
comboot.inc
ui.inc

index 29656e4..5706683 100644 (file)
@@ -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);
index 85ff8d5..d67f5b5 100644 (file)
@@ -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);
index ec521ad..4af8045 100644 (file)
@@ -158,38 +158,45 @@ INT 21h AH=4Ch    [2.00] Terminate program
 
        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
@@ -626,3 +633,29 @@ AX=0015h [3.10] Get feature flags
                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.)
index 90d9e4b..91e260a 100644 (file)
@@ -681,6 +681,44 @@ comapi_features:
                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
diff --git a/ui.inc b/ui.inc
index 0d7cc40..c656a0c 100644 (file)
--- a/ui.inc
+++ b/ui.inc
@@ -439,6 +439,20 @@ kernel_corrupt: mov si,err_notkernel
 ;
 ; 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