iPXE
Functions
com32.c File Reference

SYSLINUX COM32 image format. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <assert.h>
#include <realmode.h>
#include <basemem.h>
#include <comboot.h>
#include <ipxe/uaccess.h>
#include <ipxe/image.h>
#include <ipxe/segment.h>
#include <ipxe/init.h>
#include <ipxe/io.h>
#include <ipxe/console.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static int com32_exec_loop (struct image *image)
 Execute COMBOOT image.
static int com32_identify (struct image *image)
 Check image name extension.
static int com32_load_image (struct image *image)
 Load COM32 image into memory.
static int com32_prepare_bounce_buffer (struct image *image)
 Prepare COM32 low memory bounce buffer.
static int com32_probe (struct image *image)
 Probe COM32 image.
static int com32_exec (struct image *image)
 Execute COMBOOT image.
struct image_type com32_image_type __image_type (PROBE_NORMAL)
 SYSLINUX COM32 image type.

Detailed Description

SYSLINUX COM32 image format.

Definition in file com32.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
static int com32_exec_loop ( struct image image) [static]

Execute COMBOOT image.

Parameters:
imageCOM32 image
Return values:
rcReturn status code

Definition at line 51 of file com32.c.

References __asm__(), assert, image::cmdline, COM32_BOUNCE_SEG, com32_cfarcall_wrapper(), com32_farcall_wrapper(), com32_intcall_wrapper(), COM32_START_PHYS, COMBOOT_EXIT, COMBOOT_EXIT_COMMAND, COMBOOT_EXIT_RUN_KERNEL, comboot_force_text_mode(), comboot_return, memory_map::count, DBGC, memory_region::end, get_fbms(), get_memmap(), hook_comboot_interrupts(), image::len, image::name, PHYS_CODE, memory_map::regions, image::replacement, rmsetjmp, memory_region::start, state, unhook_comboot_interrupts(), unregister_image(), and virt_to_phys().

Referenced by com32_exec().

                                                   {
        struct memory_map memmap;
        unsigned int i;
        int state;
        uint32_t avail_mem_top;

        state = rmsetjmp ( comboot_return );

        switch ( state ) {
        case 0: /* First time through; invoke COM32 program */

                /* Get memory map */
                get_memmap ( &memmap );

                /* Find end of block covering COM32 image loading area */
                for ( i = 0, avail_mem_top = 0 ; i < memmap.count ; i++ ) {
                        if ( (memmap.regions[i].start <= COM32_START_PHYS) &&
                             (memmap.regions[i].end > COM32_START_PHYS + image->len) ) {
                                avail_mem_top = memmap.regions[i].end;
                                break;
                        }
                }

                DBGC ( image, "COM32 %p: available memory top = 0x%x\n",
                       image, avail_mem_top );

                assert ( avail_mem_top != 0 );

                /* Hook COMBOOT API interrupts */
                hook_comboot_interrupts();

                /* Unregister image, so that a "boot" command doesn't
                 * throw us into an execution loop.  We never
                 * reregister ourselves; COMBOOT images expect to be
                 * removed on exit.
                 */
                unregister_image ( image );

                __asm__ __volatile__ ( PHYS_CODE (
                        /* Preserve registers */
                        "pushal\n\t"
                        /* Preserve stack pointer */
                        "subl $4, %k0\n\t"
                        "movl %%esp, (%k0)\n\t"
                        /* Switch to COM32 stack */
                        "movl %k0, %%esp\n\t"
                        /* Enable interrupts */
                        "sti\n\t"
                        /* Construct stack frame */
                        "pushl %k1\n\t"
                        "pushl %k2\n\t"
                        "pushl %k3\n\t"
                        "pushl %k4\n\t"
                        "pushl %k5\n\t"
                        "pushl %k6\n\t"
                        "pushl $6\n\t"
                        /* Call COM32 entry point */
                        "movl %k7, %k0\n\t"
                        "call *%k0\n\t"
                        /* Disable interrupts */
                        "cli\n\t"
                        /* Restore stack pointer */
                        "movl 24(%%esp), %%esp\n\t"
                        /* Restore registers */
                        "popal\n\t" )
                        :
                        : "r" ( avail_mem_top ),
                          "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
                          "r" ( virt_to_phys ( com32_farcall_wrapper ) ),
                          "r" ( get_fbms() * 1024 - ( COM32_BOUNCE_SEG << 4 ) ),
                          "i" ( COM32_BOUNCE_SEG << 4 ),
                          "r" ( virt_to_phys ( com32_intcall_wrapper ) ),
                          "r" ( virt_to_phys ( image->cmdline ?
                                               image->cmdline : "" ) ),
                          "i" ( COM32_START_PHYS )
                        : "memory" );
                DBGC ( image, "COM32 %p: returned\n", image );
                break;

        case COMBOOT_EXIT:
                DBGC ( image, "COM32 %p: exited\n", image );
                break;

        case COMBOOT_EXIT_RUN_KERNEL:
                assert ( image->replacement );
                DBGC ( image, "COM32 %p: exited to run kernel %s\n",
                       image, image->replacement->name );
                break;

        case COMBOOT_EXIT_COMMAND:
                DBGC ( image, "COM32 %p: exited after executing command\n",
                       image );
                break;

        default:
                assert ( 0 );
                break;
        }

        unhook_comboot_interrupts();
        comboot_force_text_mode();

        return 0;
}
static int com32_identify ( struct image image) [static]

Check image name extension.

Parameters:
imageCOM32 image
Return values:
rcReturn status code

Definition at line 162 of file com32.c.

References copy_from_user(), image::data, DBGC, ENOEXEC, ext, image::len, magic, memcmp(), image::name, strcasecmp(), and strrchr().

Referenced by com32_probe().

                                                  {
        const char *ext;
        static const uint8_t magic[] = { 0xB8, 0xFF, 0x4C, 0xCD, 0x21 };
        uint8_t buf[5];

        if ( image->len >= 5 ) {
                /* Check for magic number
                 * mov eax,21cd4cffh
                 * B8 FF 4C CD 21
                 */
                copy_from_user ( buf, image->data, 0, sizeof(buf) );
                if ( ! memcmp ( buf, magic, sizeof(buf) ) ) {
                        DBGC ( image, "COM32 %p: found magic number\n",
                               image );
                        return 0;
                }
        }

        /* Magic number not found; check filename extension */

        ext = strrchr( image->name, '.' );

        if ( ! ext ) {
                DBGC ( image, "COM32 %p: no extension\n",
                       image );
                return -ENOEXEC;
        }

        ++ext;

        if ( strcasecmp( ext, "c32" ) ) {
                DBGC ( image, "COM32 %p: unrecognized extension %s\n",
                       image, ext );
                return -ENOEXEC;
        }

        return 0;
}
static int com32_load_image ( struct image image) [static]

Load COM32 image into memory.

Parameters:
imageCOM32 image
Return values:
rcReturn status code

Definition at line 207 of file com32.c.

References buffer, COM32_START_PHYS, image::data, DBGC, image::len, memcpy_user(), phys_to_user(), prep_segment(), rc, and strerror().

Referenced by com32_exec().

                                                    {
        size_t filesz, memsz;
        userptr_t buffer;
        int rc;

        filesz = image->len;
        memsz = filesz;
        buffer = phys_to_user ( COM32_START_PHYS );
        if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
                DBGC ( image, "COM32 %p: could not prepare segment: %s\n",
                       image, strerror ( rc ) );
                return rc;
        }

        /* Copy image to segment */
        memcpy_user ( buffer, 0, image->data, 0, filesz );

        return 0;
}
static int com32_prepare_bounce_buffer ( struct image image) [static]

Prepare COM32 low memory bounce buffer.

Parameters:
imageCOM32 image
Return values:
rcReturn status code

Definition at line 232 of file com32.c.

References COM32_BOUNCE_SEG, DBGC, prep_segment(), rc, real_to_user(), seg, and strerror().

Referenced by com32_exec().

                                                                {
        unsigned int seg;
        userptr_t seg_userptr;
        size_t filesz, memsz;
        int rc;

        seg = COM32_BOUNCE_SEG;
        seg_userptr = real_to_user ( seg, 0 );

        /* Ensure the entire 64k segment is free */
        memsz = 0xFFFF;
        filesz = 0;

        /* Prepare, verify, and load the real-mode segment */
        if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) {
                DBGC ( image, "COM32 %p: could not prepare bounce buffer segment: %s\n",
                       image, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int com32_probe ( struct image image) [static]

Probe COM32 image.

Parameters:
imageCOM32 image
Return values:
rcReturn status code

Definition at line 261 of file com32.c.

References com32_identify(), DBGC, image::name, and rc.

                                               {
        int rc;

        DBGC ( image, "COM32 %p: name '%s'\n", image, image->name );

        /* Check if this is a COMBOOT image */
        if ( ( rc = com32_identify ( image ) ) != 0 ) {
                return rc;
        }

        return 0;
}
static int com32_exec ( struct image image) [static]

Execute COMBOOT image.

Parameters:
imageCOM32 image
Return values:
rcReturn status code

Definition at line 280 of file com32.c.

References com32_exec_loop(), com32_load_image(), com32_prepare_bounce_buffer(), console_reset(), and rc.

                                              {
        int rc;

        /* Load image */
        if ( ( rc = com32_load_image ( image ) ) != 0 ) {
                return rc;
        }

        /* Prepare bounce buffer segment */
        if ( ( rc = com32_prepare_bounce_buffer ( image ) ) != 0 ) {
                return rc;
        }

        /* Reset console */
        console_reset();

        return com32_exec_loop ( image );
}
struct image_type com32_image_type __image_type ( PROBE_NORMAL  ) [read]

SYSLINUX COM32 image type.