core: add a direct 32-bit API
authorH. Peter Anvin <hpa@zytor.com>
Wed, 24 Feb 2010 02:14:12 +0000 (18:14 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Wed, 24 Feb 2010 02:14:12 +0000 (18:14 -0800)
Add a direct 32-bit API to some functions; initially read file only.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
com32/include/com32.h
com32/include/syslinux/pmapi.h [new file with mode: 0644]
com32/lib/sys/entry.S
com32/lib/sys/fileread.c
core/com32.inc
core/fs/fs.c
core/include/core.h
core/include/fs.h
core/include/pmapi.h [new file with mode: 0644]
core/pmapi.c [new file with mode: 0644]
doc/comboot.txt

index aa7fb4b..9334efb 100644 (file)
@@ -1,7 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
  *   Copyright 2002-2009 H. Peter Anvin - All Rights Reserved
- *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
  *
  *   Permission is hereby granted, free of charge, to any person
  *   obtaining a copy of this software and associated documentation
@@ -92,6 +92,8 @@ typedef struct {
 #define EFLAGS_VIP             0x00100000
 #define EFLAGS_ID              0x00200000
 
+struct com32_pmapi;
+
 extern struct com32_sys_args {
     uint32_t cs_sysargs;
     char *cs_cmdline;
@@ -101,6 +103,7 @@ extern struct com32_sys_args {
     void __cdecl(*cs_farcall) (uint32_t, const com32sys_t *, com32sys_t *);
     int __cdecl(*cs_cfarcall) (uint32_t, const void *, uint32_t);
     uint32_t cs_memsize;
+    const struct com32_pmapi *cs_pm;
 } __com32;
 
 /*
diff --git a/com32/include/syslinux/pmapi.h b/com32/include/syslinux/pmapi.h
new file mode 100644 (file)
index 0000000..848a554
--- /dev/null
@@ -0,0 +1,45 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2002-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * pmapi.h
+ *
+ * Definitions for the Syslinux 4 protected-mode ABI
+ */
+
+#ifndef _SYSLINUX_PMAPI_H
+#define _SYSLINUX_PMAPI_H
+
+#include <stddef.h>
+#include <inttypes.h>
+
+struct com32_pmapi {
+    size_t (*read_file)(uint16_t *, void *, size_t);
+};
+
+#endif /* _SYSLINUX_PMAPI_H */
index a3a1eaa..629f336 100644 (file)
@@ -30,7 +30,7 @@
  */
 
 /* Number of arguments in our version of the entry structure */
-#define COM32_ARGS 7
+#define COM32_ARGS 8
 
                .section ".init","ax"
                .globl _start
index 54ff711..cfd4955 100644 (file)
 #include <errno.h>
 #include <string.h>
 #include <com32.h>
+#include <syslinux/pmapi.h>
 #include <minmax.h>
 #include "file.h"
 
 int __file_get_block(struct file_info *fp)
 {
-    com32sys_t ireg, oreg;
+    ssize_t bytes_read;
 
-    memset(&ireg, 0, sizeof ireg);
-    ireg.eax.w[0] = 0x0007;    /* Read file */
-    ireg.ebx.w[0] = OFFS(__com32.cs_bounce);
-    ireg.es = SEG(__com32.cs_bounce);
-    ireg.esi.w[0] = fp->i.filedes;
-    ireg.ecx.w[0] = MAXBLOCK >> fp->i.blocklg2;
-
-    __intcall(0x22, &ireg, &oreg);
-
-    if (oreg.eflags.l & EFLAGS_CF) {
+    bytes_read = __com32.cs_pm->read_file(&fp->i.filedes, fp->i.buf,
+                                         MAXBLOCK >> fp->i.blocklg2);
+    if (!bytes_read) {
        errno = EIO;
        return -1;
     }
-
-    fp->i.filedes = oreg.esi.w[0];
-    fp->i.nbytes = oreg.ecx.l;
-    fp->i.datap = fp->i.buf;
-    memcpy(fp->i.buf, __com32.cs_bounce, fp->i.nbytes);
-
+    
+    fp->i.nbytes = bytes_read;
+    fp->i.datap  = fp->i.buf;
     return 0;
 }
 
@@ -74,19 +65,33 @@ ssize_t __file_read(struct file_info * fp, void *buf, size_t count)
            if (fp->i.offset >= fp->i.length || !fp->i.filedes)
                return n;       /* As good as it gets... */
 
-           if (__file_get_block(fp))
-               return n ? n : -1;
+           if (count > MAXBLOCK) {
+               /* Large transfer: copy directly, without buffering */
+               ncopy = __com32.cs_pm->read_file(&fp->i.filedes, bufp,
+                                                count >> fp->i.blocklg2);
+               if (!ncopy) {
+                   errno = EIO;
+                   return n ? n : -1;
+               }
+
+               goto got_data;
+           } else {
+               if (__file_get_block(fp))
+                   return n ? n : -1;
+           }
        }
 
        ncopy = min(count, fp->i.nbytes);
        memcpy(bufp, fp->i.datap, ncopy);
 
-       n += ncopy;
-       bufp += ncopy;
-       count -= ncopy;
        fp->i.datap += ncopy;
        fp->i.offset += ncopy;
        fp->i.nbytes -= ncopy;
+
+    got_data:
+       n += ncopy;
+       bufp += ncopy;
+       count -= ncopy;
     }
 
     return n;
index cb17279..810ee03 100644 (file)
@@ -1,7 +1,7 @@
 ;; -----------------------------------------------------------------------
 ;;
 ;;   Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-;;   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+;;   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
 ;;
 ;;   This program is free software; you can redistribute it and/or modify
 ;;   it under the terms of the GNU General Public License as published by
@@ -17,6 +17,8 @@
 ;; Common code for running a COM32 image
 ;;
 
+               extern pm_api_vector
+
 ;
 ; Load a COM32 image.  A COM32 image is the 32-bit analogue to a DOS
 ; .com file.  A COM32 image is loaded at address 0x101000, with %esp
@@ -82,6 +84,7 @@ com32_start:
 .pm:
                ; Set up the calling stack frame
 
+               push dword pm_api_vector
                push dword [HighMemSize]        ; Memory managed by Syslinux
                push dword core_cfarcall        ; Cfarcall entry point
                push dword core_farcall         ; Farcall entry point
@@ -89,7 +92,7 @@ com32_start:
                push dword core_real_mode       ; Bounce buffer address
                push dword core_intcall         ; Intcall entry point
                push dword command_line         ; Command line pointer
-               push dword 7                    ; Argument count
+               push dword 8                    ; Argument count
                sti                             ; Interrupts OK now
                call com32_entry                ; Run the program...
                ; ... on return, fall through to com32_exit ...
@@ -123,7 +126,7 @@ not_com32r_msg      db ': not a COM32R image', CR, LF, 0
                global __com32
                alignz 4
 __com32:
-               dd 7                            ; Argument count
+               dd 8                            ; Argument count
                dd 0                            ; No command line
                dd core_intcall                 ; Intcall entry point
                dd core_xfer_buf                ; Bounce buffer address
@@ -131,3 +134,4 @@ __com32:
                dd core_farcall                 ; Farcall entry point
                dd core_cfarcall                ; Cfarcall entry point
 HighMemSize    dd 0                            ; End of memory pointer (bytes)
+               dd pm_api_vector                ; Protected mode functions
index d67a87c..e0f469b 100644 (file)
@@ -137,6 +137,27 @@ void getfssec(com32sys_t *regs)
     regs->ecx.l = bytes_read;
 }
 
+size_t pmapi_read_file(uint16_t *handle, void *buf, size_t sectors)
+{
+    bool have_more;
+    size_t bytes_read;
+    struct file *file;
+
+    file = handle_to_file(*handle);
+    bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);
+
+    /*
+     * If we reach EOF, the filesystem driver will have already closed
+     * the underlying file... this really should be cleaner.
+     */
+    if (!have_more) {
+       _close_file(file);
+       *handle = 0;
+    }
+
+    return bytes_read;
+}
+
 void pm_searchdir(com32sys_t *regs)
 {
     char *name = MK_PTR(regs->ds, regs->edi.w[0]);
index c955e73..e6364f8 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <klibc/compiler.h>
 #include <com32.h>
+#include <syslinux/pmapi.h>
 
 extern char core_xfer_buf[65536];
 extern char core_cache_buf[65536];
index 8a173d9..1f4ad28 100644 (file)
@@ -187,6 +187,7 @@ void mangle_name(char *, const char *);
 char *unmangle_name(char *, const char *);
 int searchdir(const char *name);
 void _close_file(struct file *);
+size_t pmapi_read_file(uint16_t *handle, void *buf, size_t sectors);
 
 /* chdir.c */
 void pm_realpath(com32sys_t *regs);
diff --git a/core/include/pmapi.h b/core/include/pmapi.h
new file mode 100644 (file)
index 0000000..57d2e6f
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef PMAPI_H
+#define PMAPI_H
+
+#include <syslinux/pmapi.h>
+
+size_t pmapi_read_file(uint16_t *, void *, size_t);
+
+#endif /* PMAPI_H */
diff --git a/core/pmapi.c b/core/pmapi.c
new file mode 100644 (file)
index 0000000..f45a7fc
--- /dev/null
@@ -0,0 +1,23 @@
+/* -----------------------------------------------------------------------
+ *
+ *   Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <inttypes.h>
+#include <com32.h>
+#include <syslinux/pmapi.h>
+#include "core.h"
+#include "fs.h"
+
+const struct com32_pmapi pm_api_vector =
+{
+    .read_file = pmapi_read_file,
+};
index 6d026aa..7950688 100644 (file)
@@ -90,19 +90,22 @@ The following arguments are passed to the program on the stack:
  [ESP+24] dword Pointer to FAR call helper function (new in 2.05)
  [ESP+28] dword Pointer to CDECL helper function (new in 3.54)
  [ESP+32] dword Amount of memory controlled by the Syslinux core (new in 3.74)
-
-This corresponds to the following C prototype, available in the file
-com32/include/com32.h:
-
-/* The standard prototype for _start() */
-int _start(unsigned int __nargs,
-          char *__cmdline,
-          void (*__intcall)(uint8_t, com32sys_t *, com32sys_t *),
-          void *__bounce_ptr,
-          unsigned int __bounce_len,
-          void (*__farcall)(uint32_t, com32sys_t *, com32sys_t *),
-          int (*__cfarcall)(uint32_t, void *, size_t)
-          );
+ [ESP+36] dword        Pointer to protected-mode functions (new in 4.00)
+
+The libcom32 startup code loads this into a structure named __com32,
+defined in <com32.h>:
+
+extern struct com32_sys_args {
+    uint32_t cs_sysargs;
+    char *cs_cmdline;
+    void __cdecl(*cs_intcall)(uint8_t, const com32sys_t *, com32sys_t *);
+    void *cs_bounce;
+    uint32_t cs_bounce_size;
+    void __cdecl(*cs_farcall)(uint32_t, const com32sys_t *, com32sys_t *);
+    int __cdecl(*cs_cfarcall)(uint32_t, const void *, uint32_t);
+    uint32_t cs_memsize;
+    struct com32_pmapi *cs_pm;
+} __com32;
 
 The intcall helper function can be used to issue BIOS or Syslinux API
 calls, and takes the interrupt number as first argument.  The second
@@ -149,6 +152,12 @@ The cfarcall helper function takes (CS << 16)+IP, a pointer to a stack
 frame, a size of that stack frame, and returns the return value of EAX
 (which may need to be appropriate truncated by the user.)
 
+Starting in version 4.00, some of these API calls are available as
+protected-mode function calls, using the regparm(3) calling convention
+(the first three argumetns in EAX, EDX, ECX; the rest on the stack.)
+Those functions are defined in struct com32_pmapi, defined in
+<syslinux/pmapi.h>.
+
 
        ++++ SYSLINUX API CALLS +++
 
@@ -342,6 +351,16 @@ AX=0007h [2.08] Read file
        WARNING: Calling this function with an invalid file handle
        will probably crash the system.
 
+       32-BIT VERSION:
+
+       size_t cs_pm->read_file(uint16_t *handle, void *buf, size_t blocks)
+
+       handle  - file handle (input and output, set to zero on end of file)
+       buf     - buffer to write to
+       blocks  - number of blocks to read
+
+       Returns number of bytes read, or 0 on failure.
+
 
 AX=0008h [2.08] Close file