diff options
| author | Michael Brown | 2016-04-14 17:48:41 +0200 |
|---|---|---|
| committer | Michael Brown | 2016-04-15 16:31:36 +0200 |
| commit | 5e5450c2d04e6f976ea4cef5db50e136d4a06282 (patch) | |
| tree | 21a059921d77d68d0508f984a0667d84c1666e12 /src/arch/i386/image | |
| parent | [pool] Fix check for reopenable pooled connections (diff) | |
| download | ipxe-5e5450c2d04e6f976ea4cef5db50e136d4a06282.tar.gz ipxe-5e5450c2d04e6f976ea4cef5db50e136d4a06282.tar.xz ipxe-5e5450c2d04e6f976ea4cef5db50e136d4a06282.zip | |
[comboot] Support COMBOOT in 64-bit builds
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch/i386/image')
| -rw-r--r-- | src/arch/i386/image/com32.c | 296 | ||||
| -rw-r--r-- | src/arch/i386/image/comboot.c | 331 |
2 files changed, 0 insertions, 627 deletions
diff --git a/src/arch/i386/image/com32.c b/src/arch/i386/image/com32.c deleted file mode 100644 index ff64fd1a1..000000000 --- a/src/arch/i386/image/com32.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>. - * - * 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; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * @file - * - * SYSLINUX COM32 image format - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#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> - -/** - * Execute COMBOOT image - * - * @v image COM32 image - * @ret rc Return status code - */ -static int com32_exec_loop ( struct image *image ) { - 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 ); - - com32_external_esp = phys_to_virt ( avail_mem_top ); - - /* 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__ ( - "movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */ - "movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */ - "call _virt_to_phys\n\t" /* Switch to flat physical address space */ - "sti\n\t" /* Enable interrupts */ - "pushl %0\n\t" /* Pointer to CDECL helper function */ - "pushl %1\n\t" /* Pointer to FAR call helper function */ - "pushl %2\n\t" /* Size of low memory bounce buffer */ - "pushl %3\n\t" /* Pointer to low memory bounce buffer */ - "pushl %4\n\t" /* Pointer to INT call helper function */ - "pushl %5\n\t" /* Pointer to the command line arguments */ - "pushl $6\n\t" /* Number of additional arguments */ - "call *%6\n\t" /* Execute image */ - "cli\n\t" /* Disable interrupts */ - "call _phys_to_virt\n\t" /* Switch back to internal virtual address space */ - "movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */ - : - : - /* %0 */ "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ), - /* %1 */ "r" ( virt_to_phys ( com32_farcall_wrapper ) ), - /* %2 */ "r" ( get_fbms() * 1024 - (COM32_BOUNCE_SEG << 4) ), - /* %3 */ "i" ( COM32_BOUNCE_SEG << 4 ), - /* %4 */ "r" ( virt_to_phys ( com32_intcall_wrapper ) ), - /* %5 */ "r" ( virt_to_phys ( image->cmdline ? - image->cmdline : "" ) ), - /* %6 */ "r" ( 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; -} - -/** - * Check image name extension - * - * @v image COM32 image - * @ret rc Return status code - */ -static int com32_identify ( struct image *image ) { - 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; -} - - -/** - * Load COM32 image into memory - * @v image COM32 image - * @ret rc Return status code - */ -static int com32_load_image ( struct image *image ) { - 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; -} - -/** - * Prepare COM32 low memory bounce buffer - * @v image COM32 image - * @ret rc Return status code - */ -static int com32_prepare_bounce_buffer ( struct image * image ) { - 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; -} - -/** - * Probe COM32 image - * - * @v image COM32 image - * @ret rc Return status code - */ -static int com32_probe ( struct image *image ) { - 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; -} - -/** - * Execute COMBOOT image - * - * @v image COM32 image - * @ret rc Return status code - */ -static int com32_exec ( struct image *image ) { - 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 ); -} - -/** SYSLINUX COM32 image type */ -struct image_type com32_image_type __image_type ( PROBE_NORMAL ) = { - .name = "COM32", - .probe = com32_probe, - .exec = com32_exec, -}; diff --git a/src/arch/i386/image/comboot.c b/src/arch/i386/image/comboot.c deleted file mode 100644 index 20b5ae1e7..000000000 --- a/src/arch/i386/image/comboot.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>. - * - * 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; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * @file - * - * SYSLINUX COMBOOT (16-bit) image format - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#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/features.h> -#include <ipxe/console.h> - -FEATURE ( FEATURE_IMAGE, "COMBOOT", DHCP_EB_FEATURE_COMBOOT, 1 ); - -/** - * COMBOOT PSP, copied to offset 0 of code segment - */ -struct comboot_psp { - /** INT 20 instruction, executed if COMBOOT image returns with RET */ - uint16_t int20; - /** Segment of first non-free paragraph of memory */ - uint16_t first_non_free_para; -}; - -/** Offset in PSP of command line */ -#define COMBOOT_PSP_CMDLINE_OFFSET 0x81 - -/** Maximum length of command line in PSP - * (127 bytes minus space and CR) */ -#define COMBOOT_MAX_CMDLINE_LEN 125 - - -/** - * Copy command line to PSP - * - * @v image COMBOOT image - */ -static void comboot_copy_cmdline ( struct image * image, userptr_t seg_userptr ) { - const char *cmdline = ( image->cmdline ? image->cmdline : "" ); - int cmdline_len = strlen ( cmdline ); - if( cmdline_len > COMBOOT_MAX_CMDLINE_LEN ) - cmdline_len = COMBOOT_MAX_CMDLINE_LEN; - uint8_t len_byte = cmdline_len; - char spc = ' ', cr = '\r'; - - /* Copy length to byte before command line */ - copy_to_user ( seg_userptr, COMBOOT_PSP_CMDLINE_OFFSET - 1, - &len_byte, 1 ); - - /* Command line starts with space */ - copy_to_user ( seg_userptr, - COMBOOT_PSP_CMDLINE_OFFSET, - &spc, 1 ); - - /* Copy command line */ - copy_to_user ( seg_userptr, - COMBOOT_PSP_CMDLINE_OFFSET + 1, - cmdline, cmdline_len ); - - /* Command line ends with CR */ - copy_to_user ( seg_userptr, - COMBOOT_PSP_CMDLINE_OFFSET + cmdline_len + 1, - &cr, 1 ); -} - -/** - * Initialize PSP - * - * @v image COMBOOT image - * @v seg_userptr segment to initialize - */ -static void comboot_init_psp ( struct image * image, userptr_t seg_userptr ) { - struct comboot_psp psp; - - /* Fill PSP */ - - /* INT 20h instruction, byte order reversed */ - psp.int20 = 0x20CD; - - /* get_fbms() returns BIOS free base memory counter, which is in - * kilobytes; x * 1024 / 16 == x * 64 == x << 6 */ - psp.first_non_free_para = get_fbms() << 6; - - DBGC ( image, "COMBOOT %p: first non-free paragraph = 0x%x\n", - image, psp.first_non_free_para ); - - /* Copy the PSP to offset 0 of segment. - * The rest of the PSP was already zeroed by - * comboot_prepare_segment. */ - copy_to_user ( seg_userptr, 0, &psp, sizeof( psp ) ); - - /* Copy the command line to the PSP */ - comboot_copy_cmdline ( image, seg_userptr ); -} - -/** - * Execute COMBOOT image - * - * @v image COMBOOT image - * @ret rc Return status code - */ -static int comboot_exec_loop ( struct image *image ) { - userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 ); - int state; - - state = rmsetjmp ( comboot_return ); - - switch ( state ) { - case 0: /* First time through; invoke COMBOOT program */ - - /* Initialize PSP */ - comboot_init_psp ( image, seg_userptr ); - - /* Hook COMBOOT API interrupts */ - hook_comboot_interrupts(); - - DBGC ( image, "executing 16-bit COMBOOT image at %4x:0100\n", - COMBOOT_PSP_SEG ); - - /* 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 ); - - /* Store stack segment at 0x38 and stack pointer at 0x3A - * in the PSP and jump to the image */ - __asm__ __volatile__ ( - REAL_CODE ( /* Save return address with segment on old stack */ - "popw %%ax\n\t" - "pushw %%cs\n\t" - "pushw %%ax\n\t" - /* Set DS=ES=segment with image */ - "movw %w0, %%ds\n\t" - "movw %w0, %%es\n\t" - /* Set SS:SP to new stack (end of image segment) */ - "movw %w0, %%ss\n\t" - "xor %%sp, %%sp\n\t" - "pushw $0\n\t" - "pushw %w0\n\t" - "pushw $0x100\n\t" - /* Zero registers (some COM files assume GP regs are 0) */ - "xorw %%ax, %%ax\n\t" - "xorw %%bx, %%bx\n\t" - "xorw %%cx, %%cx\n\t" - "xorw %%dx, %%dx\n\t" - "xorw %%si, %%si\n\t" - "xorw %%di, %%di\n\t" - "xorw %%bp, %%bp\n\t" - "lret\n\t" ) - : : "r" ( COMBOOT_PSP_SEG ) : "eax" ); - DBGC ( image, "COMBOOT %p: returned\n", image ); - break; - - case COMBOOT_EXIT: - DBGC ( image, "COMBOOT %p: exited\n", image ); - break; - - case COMBOOT_EXIT_RUN_KERNEL: - assert ( image->replacement ); - DBGC ( image, "COMBOOT %p: exited to run kernel %s\n", - image, image->replacement->name ); - break; - - case COMBOOT_EXIT_COMMAND: - DBGC ( image, "COMBOOT %p: exited after executing command\n", - image ); - break; - - default: - assert ( 0 ); - break; - } - - unhook_comboot_interrupts(); - comboot_force_text_mode(); - - return 0; -} - -/** - * Check image name extension - * - * @v image COMBOOT image - * @ret rc Return status code - */ -static int comboot_identify ( struct image *image ) { - const char *ext; - - ext = strrchr( image->name, '.' ); - - if ( ! ext ) { - DBGC ( image, "COMBOOT %p: no extension\n", - image ); - return -ENOEXEC; - } - - ++ext; - - if ( strcasecmp( ext, "cbt" ) ) { - DBGC ( image, "COMBOOT %p: unrecognized extension %s\n", - image, ext ); - return -ENOEXEC; - } - - return 0; -} - -/** - * Load COMBOOT image into memory, preparing a segment and returning it - * @v image COMBOOT image - * @ret rc Return status code - */ -static int comboot_prepare_segment ( struct image *image ) -{ - userptr_t seg_userptr; - size_t filesz, memsz; - int rc; - - /* Load image in segment */ - seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 ); - - /* Allow etra 0x100 bytes before image for PSP */ - filesz = image->len + 0x100; - - /* Ensure the entire 64k segment is free */ - memsz = 0xFFFF; - - /* Prepare, verify, and load the real-mode segment */ - if ( ( rc = prep_segment ( seg_userptr, filesz, memsz ) ) != 0 ) { - DBGC ( image, "COMBOOT %p: could not prepare segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - /* Zero PSP */ - memset_user ( seg_userptr, 0, 0, 0x100 ); - - /* Copy image to segment:0100 */ - memcpy_user ( seg_userptr, 0x100, image->data, 0, image->len ); - - return 0; -} - -/** - * Probe COMBOOT image - * - * @v image COMBOOT image - * @ret rc Return status code - */ -static int comboot_probe ( struct image *image ) { - int rc; - - DBGC ( image, "COMBOOT %p: name '%s'\n", - image, image->name ); - - /* Check if this is a COMBOOT image */ - if ( ( rc = comboot_identify ( image ) ) != 0 ) { - - return rc; - } - - return 0; -} - -/** - * Execute COMBOOT image - * - * @v image COMBOOT image - * @ret rc Return status code - */ -static int comboot_exec ( struct image *image ) { - int rc; - - /* Sanity check for filesize */ - if( image->len >= 0xFF00 ) { - DBGC( image, "COMBOOT %p: image too large\n", - image ); - return -ENOEXEC; - } - - /* Prepare segment and load image */ - if ( ( rc = comboot_prepare_segment ( image ) ) != 0 ) { - return rc; - } - - /* Reset console */ - console_reset(); - - return comboot_exec_loop ( image ); -} - -/** SYSLINUX COMBOOT (16-bit) image type */ -struct image_type comboot_image_type __image_type ( PROBE_NORMAL ) = { - .name = "COMBOOT", - .probe = comboot_probe, - .exec = comboot_exec, -}; |
