Annotation of qemu/roms/ipxe/src/arch/i386/image/com32.c, revision 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.