Annotation of qemu/roms/ipxe/src/arch/i386/image/com32.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2008 Daniel Verkamp <[email protected]>.
                      3:  *
                      4:  * This program is free software; you can redistribute it and/or
                      5:  * modify it under the terms of the GNU General Public License as
                      6:  * published by the Free Software Foundation; either version 2 of the
                      7:  * License, or any later version.
                      8:  *
                      9:  * This program is distributed in the hope that it will be useful, but
                     10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     12:  * General Public License for more details.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License
                     15:  * along with this program; if not, write to the Free Software
                     16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  */
                     18: 
                     19: /**
                     20:  * @file
                     21:  *
                     22:  * SYSLINUX COM32 image format
                     23:  *
                     24:  */
                     25: 
                     26: FILE_LICENCE ( GPL2_OR_LATER );
                     27: 
                     28: #include <stdint.h>
                     29: #include <stdlib.h>
                     30: #include <string.h>
                     31: #include <strings.h>
                     32: #include <errno.h>
                     33: #include <assert.h>
                     34: #include <realmode.h>
                     35: #include <basemem.h>
                     36: #include <comboot.h>
                     37: #include <ipxe/uaccess.h>
                     38: #include <ipxe/image.h>
                     39: #include <ipxe/segment.h>
                     40: #include <ipxe/init.h>
                     41: #include <ipxe/io.h>
                     42: 
                     43: struct idt_register com32_external_idtr = {
                     44:        .limit = COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) - 1,
                     45:        .base = COM32_IDT
                     46: };
                     47: 
                     48: struct idt_register com32_internal_idtr;
                     49: 
                     50: /**
                     51:  * Execute COMBOOT image
                     52:  *
                     53:  * @v image            COM32 image
                     54:  * @ret rc             Return status code
                     55:  */
                     56: static int com32_exec_loop ( struct image *image ) {
                     57:        struct memory_map memmap;
                     58:        unsigned int i;
                     59:        int state;
                     60:        uint32_t avail_mem_top;
                     61: 
                     62:        state = rmsetjmp ( comboot_return );
                     63: 
                     64:        switch ( state ) {
                     65:        case 0: /* First time through; invoke COM32 program */
                     66: 
                     67:                /* Get memory map */
                     68:                get_memmap ( &memmap );
                     69: 
                     70:                /* Find end of block covering COM32 image loading area */
                     71:                for ( i = 0, avail_mem_top = 0 ; i < memmap.count ; i++ ) {
                     72:                        if ( (memmap.regions[i].start <= COM32_START_PHYS) &&
                     73:                             (memmap.regions[i].end > COM32_START_PHYS + image->len) ) {
                     74:                                avail_mem_top = memmap.regions[i].end;
                     75:                                break;
                     76:                        }
                     77:                }
                     78: 
                     79:                DBGC ( image, "COM32 %p: available memory top = 0x%x\n",
                     80:                       image, avail_mem_top );
                     81: 
                     82:                assert ( avail_mem_top != 0 );
                     83: 
                     84:                com32_external_esp = phys_to_virt ( avail_mem_top );
                     85: 
                     86:                /* Hook COMBOOT API interrupts */
                     87:                hook_comboot_interrupts();
                     88: 
                     89:                /* Unregister image, so that a "boot" command doesn't
                     90:                 * throw us into an execution loop.  We never
                     91:                 * reregister ourselves; COMBOOT images expect to be
                     92:                 * removed on exit.
                     93:                 */
                     94:                unregister_image ( image );
                     95: 
                     96:                __asm__ __volatile__ (
                     97:                        "sidt com32_internal_idtr\n\t"
                     98:                        "lidt com32_external_idtr\n\t"         /* Set up IDT */
                     99:                        "movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */
                    100:                        "movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */
                    101:                        "call _virt_to_phys\n\t"               /* Switch to flat physical address space */
                    102:                        "sti\n\t"                              /* Enable interrupts */
                    103:                        "pushl %0\n\t"                         /* Pointer to CDECL helper function */
                    104:                        "pushl %1\n\t"                         /* Pointer to FAR call helper function */
                    105:                        "pushl %2\n\t"                         /* Size of low memory bounce buffer */
                    106:                        "pushl %3\n\t"                         /* Pointer to low memory bounce buffer */
                    107:                        "pushl %4\n\t"                         /* Pointer to INT call helper function */
                    108:                        "pushl %5\n\t"                         /* Pointer to the command line arguments */
                    109:                        "pushl $6\n\t"                         /* Number of additional arguments */
                    110:                        "call *%6\n\t"                         /* Execute image */
                    111:                        "cli\n\t"                              /* Disable interrupts */
                    112:                        "call _phys_to_virt\n\t"               /* Switch back to internal virtual address space */
                    113:                        "lidt com32_internal_idtr\n\t"         /* Switch back to internal IDT (for debugging) */
                    114:                        "movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */
                    115:                :
                    116:                :
                    117:                        /* %0 */ "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
                    118:                        /* %1 */ "r" ( virt_to_phys ( com32_farcall_wrapper ) ),
                    119:                        /* %2 */ "r" ( get_fbms() * 1024 - (COM32_BOUNCE_SEG << 4) ),
                    120:                        /* %3 */ "i" ( COM32_BOUNCE_SEG << 4 ),
                    121:                        /* %4 */ "r" ( virt_to_phys ( com32_intcall_wrapper ) ),
                    122:                        /* %5 */ "r" ( virt_to_phys ( image->cmdline ?
                    123:                                                      image->cmdline : "" ) ),
                    124:                        /* %6 */ "r" ( COM32_START_PHYS )
                    125:                :
                    126:                        "memory" );
                    127:                DBGC ( image, "COM32 %p: returned\n", image );
                    128:                break;
                    129: 
                    130:        case COMBOOT_EXIT:
                    131:                DBGC ( image, "COM32 %p: exited\n", image );
                    132:                break;
                    133: 
                    134:        case COMBOOT_EXIT_RUN_KERNEL:
                    135:                assert ( image->replacement );
                    136:                DBGC ( image, "COM32 %p: exited to run kernel %s\n",
                    137:                       image, image->replacement->name );
                    138:                break;
                    139: 
                    140:        case COMBOOT_EXIT_COMMAND:
                    141:                DBGC ( image, "COM32 %p: exited after executing command\n",
                    142:                       image );
                    143:                break;
                    144: 
                    145:        default:
                    146:                assert ( 0 );
                    147:                break;
                    148:        }
                    149: 
                    150:        unhook_comboot_interrupts();
                    151:        comboot_force_text_mode();
                    152: 
                    153:        return 0;
                    154: }
                    155: 
                    156: /**
                    157:  * Check image name extension
                    158:  * 
                    159:  * @v image            COM32 image
                    160:  * @ret rc             Return status code
                    161:  */
                    162: static int com32_identify ( struct image *image ) {
                    163:        const char *ext;
                    164:        static const uint8_t magic[] = { 0xB8, 0xFF, 0x4C, 0xCD, 0x21 };
                    165:        uint8_t buf[5];
                    166:        
                    167:        if ( image->len >= 5 ) {
                    168:                /* Check for magic number
                    169:                 * mov eax,21cd4cffh
                    170:                 * B8 FF 4C CD 21
                    171:                 */
                    172:                copy_from_user ( buf, image->data, 0, sizeof(buf) );
                    173:                if ( ! memcmp ( buf, magic, sizeof(buf) ) ) {
                    174:                        DBGC ( image, "COM32 %p: found magic number\n",
                    175:                               image );
                    176:                        return 0;
                    177:                }
                    178:        }
                    179: 
                    180:        /* Magic number not found; check filename extension */
                    181: 
                    182:        ext = strrchr( image->name, '.' );
                    183: 
                    184:        if ( ! ext ) {
                    185:                DBGC ( image, "COM32 %p: no extension\n",
                    186:                       image );
                    187:                return -ENOEXEC;
                    188:        }
                    189: 
                    190:        ++ext;
                    191: 
                    192:        if ( strcasecmp( ext, "c32" ) ) {
                    193:                DBGC ( image, "COM32 %p: unrecognized extension %s\n",
                    194:                       image, ext );
                    195:                return -ENOEXEC;
                    196:        }
                    197: 
                    198:        return 0;
                    199: }
                    200: 
                    201: 
                    202: /**
                    203:  * Load COM32 image into memory and set up the IDT
                    204:  * @v image            COM32 image
                    205:  * @ret rc             Return status code
                    206:  */
                    207: static int com32_load_image ( struct image *image ) {
                    208:        physaddr_t com32_irq_wrapper_phys;
                    209:        struct idt_descriptor *idt;
                    210:        struct ijb_entry *ijb;
                    211:        size_t filesz, memsz;
                    212:        userptr_t buffer;
                    213:        int rc, i;
                    214: 
                    215:        /* The interrupt descriptor table, interrupt jump buffer, and
                    216:         * image data are all contiguous in memory. Prepare them all at once.
                    217:         */
                    218:        filesz = image->len +
                    219:                COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) +
                    220:                COM32_NUM_IDT_ENTRIES * sizeof ( struct ijb_entry );
                    221:        memsz = filesz;
                    222:        buffer = phys_to_user ( COM32_IDT );
                    223:        if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
                    224:                DBGC ( image, "COM32 %p: could not prepare segment: %s\n",
                    225:                       image, strerror ( rc ) );
                    226:                return rc;
                    227:        }
                    228: 
                    229:        /* Write the IDT and IJB */
                    230:        idt = phys_to_virt ( COM32_IDT );
                    231:        ijb = phys_to_virt ( COM32_IJB );
                    232:        com32_irq_wrapper_phys = virt_to_phys ( com32_irq_wrapper );
                    233: 
                    234:        for ( i = 0; i < COM32_NUM_IDT_ENTRIES; i++ ) {
                    235:                uint32_t ijb_address = virt_to_phys ( &ijb[i] );
                    236: 
                    237:                idt[i].offset_low = ijb_address & 0xFFFF;
                    238:                idt[i].selector = PHYSICAL_CS;
                    239:                idt[i].flags = IDT_INTERRUPT_GATE_FLAGS;
                    240:                idt[i].offset_high = ijb_address >> 16;
                    241: 
                    242:                ijb[i].pusha_instruction = IJB_PUSHA;
                    243:                ijb[i].mov_instruction = IJB_MOV_AL_IMM8;
                    244:                ijb[i].mov_value = i;
                    245:                ijb[i].jump_instruction = IJB_JMP_REL32;
                    246:                ijb[i].jump_destination = com32_irq_wrapper_phys -
                    247:                        virt_to_phys ( &ijb[i + 1] );
                    248:        }
                    249: 
                    250:        /* Copy image to segment */
                    251:        buffer = phys_to_user ( COM32_START_PHYS );
                    252:        memcpy_user ( buffer, 0, image->data, 0, filesz );
                    253: 
                    254:        return 0;
                    255: }
                    256: 
                    257: /**
                    258:  * Prepare COM32 low memory bounce buffer
                    259:  * @v image            COM32 image
                    260:  * @ret rc             Return status code
                    261:  */
                    262: static int com32_prepare_bounce_buffer ( struct image * image ) {
                    263:        unsigned int seg;
                    264:        userptr_t seg_userptr;
                    265:        size_t filesz, memsz;
                    266:        int rc;
                    267: 
                    268:        seg = COM32_BOUNCE_SEG;
                    269:        seg_userptr = real_to_user ( seg, 0 );
                    270: 
                    271:        /* Ensure the entire 64k segment is free */
                    272:        memsz = 0xFFFF;
                    273:        filesz = 0;
                    274: 
                    275:        /* Prepare, verify, and load the real-mode segment */
                    276:        if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) {
                    277:                DBGC ( image, "COM32 %p: could not prepare bounce buffer segment: %s\n",
                    278:                       image, strerror ( rc ) );
                    279:                return rc;
                    280:        }
                    281: 
                    282:        return 0;
                    283: }
                    284: 
                    285: /**
                    286:  * Probe COM32 image
                    287:  *
                    288:  * @v image            COM32 image
                    289:  * @ret rc             Return status code
                    290:  */
                    291: static int com32_probe ( struct image *image ) {
                    292:        int rc;
                    293: 
                    294:        DBGC ( image, "COM32 %p: name '%s'\n", image, image->name );
                    295: 
                    296:        /* Check if this is a COMBOOT image */
                    297:        if ( ( rc = com32_identify ( image ) ) != 0 ) {
                    298:                return rc;
                    299:        }
                    300: 
                    301:        return 0;
                    302: }
                    303: 
                    304: /**
                    305:  * Execute COMBOOT image
                    306:  *
                    307:  * @v image            COM32 image
                    308:  * @ret rc             Return status code
                    309:  */
                    310: static int com32_exec ( struct image *image ) {
                    311:        int rc;
                    312: 
                    313:        /* Load image */
                    314:        if ( ( rc = com32_load_image ( image ) ) != 0 ) {
                    315:                return rc;
                    316:        }
                    317: 
                    318:        /* Prepare bounce buffer segment */
                    319:        if ( ( rc = com32_prepare_bounce_buffer ( image ) ) != 0 ) {
                    320:                return rc;
                    321:        }
                    322: 
                    323:        return com32_exec_loop ( image );
                    324: }
                    325: 
                    326: /** SYSLINUX COM32 image type */
                    327: struct image_type com32_image_type __image_type ( PROBE_NORMAL ) = {
                    328:        .name = "COM32",
                    329:        .probe = com32_probe,
                    330:        .exec = com32_exec,
                    331: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.