diff options
author | Michael Brown <mcb30@ipxe.org> | 2016-04-14 16:48:41 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2016-04-15 15:31:36 +0100 |
commit | 5e5450c2d04e6f976ea4cef5db50e136d4a06282 (patch) | |
tree | 21a059921d77d68d0508f984a0667d84c1666e12 /src/arch/i386 | |
parent | 4afb75842314c454980c748586764afb187cef7c (diff) | |
download | ipxe-5e5450c2d04e6f976ea4cef5db50e136d4a06282.tar.gz |
[comboot] Support COMBOOT in 64-bit builds
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/arch/i386')
-rw-r--r-- | src/arch/i386/Makefile | 2 | ||||
-rw-r--r-- | src/arch/i386/image/com32.c | 296 | ||||
-rw-r--r-- | src/arch/i386/image/comboot.c | 331 | ||||
-rw-r--r-- | src/arch/i386/include/comboot.h | 132 | ||||
-rw-r--r-- | src/arch/i386/interface/syslinux/com32_call.c | 191 | ||||
-rw-r--r-- | src/arch/i386/interface/syslinux/com32_wrapper.S | 97 | ||||
-rw-r--r-- | src/arch/i386/interface/syslinux/comboot_call.c | 705 | ||||
-rw-r--r-- | src/arch/i386/interface/syslinux/comboot_resolv.c | 61 | ||||
-rw-r--r-- | src/arch/i386/tests/comboot/shuffle-simple.asm | 40 | ||||
-rw-r--r-- | src/arch/i386/tests/comboot/version.asm | 136 |
10 files changed, 0 insertions, 1991 deletions
diff --git a/src/arch/i386/Makefile b/src/arch/i386/Makefile index a52986048..fe3adc9ce 100644 --- a/src/arch/i386/Makefile +++ b/src/arch/i386/Makefile @@ -83,9 +83,7 @@ endif # i386-specific directories containing source files # SRCDIRS += arch/i386/core -SRCDIRS += arch/i386/image SRCDIRS += arch/i386/tests -SRCDIRS += arch/i386/interface/syslinux # Include common x86 Makefile # 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, -}; diff --git a/src/arch/i386/include/comboot.h b/src/arch/i386/include/comboot.h deleted file mode 100644 index 5cb1ba54c..000000000 --- a/src/arch/i386/include/comboot.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef COMBOOT_H -#define COMBOOT_H - -/** - * @file - * - * SYSLINUX COMBOOT - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <rmsetjmp.h> -#include <ipxe/in.h> - -/** Segment used for COMBOOT PSP and image */ -#define COMBOOT_PSP_SEG 0x07C0 - -/** Entry point address of COM32 images */ -#define COM32_START_PHYS 0x101000 - -/** COM32 bounce buffer segment */ -#define COM32_BOUNCE_SEG 0x07C0 - -/** Size of SYSLINUX file block in bytes */ -#define COMBOOT_FILE_BLOCKSZ 512 - -/** COMBOOT feature flags (INT 22h AX=15h) */ -#define COMBOOT_FEATURE_LOCAL_BOOT (1 << 0) -#define COMBOOT_FEATURE_IDLE_LOOP (1 << 1) - -/** Maximum number of shuffle descriptors for - * shuffle and boot functions - * (INT 22h AX=0012h, 001Ah, 001Bh) - */ -#define COMBOOT_MAX_SHUFFLE_DESCRIPTORS 682 - -typedef union { - uint32_t l; - uint16_t w[2]; - uint8_t b[4]; -} com32_reg32_t; - -typedef struct { - uint16_t gs; /* Offset 0 */ - uint16_t fs; /* Offset 2 */ - uint16_t es; /* Offset 4 */ - uint16_t ds; /* Offset 6 */ - - com32_reg32_t edi; /* Offset 8 */ - com32_reg32_t esi; /* Offset 12 */ - com32_reg32_t ebp; /* Offset 16 */ - com32_reg32_t _unused_esp; /* Offset 20 */ - com32_reg32_t ebx; /* Offset 24 */ - com32_reg32_t edx; /* Offset 28 */ - com32_reg32_t ecx; /* Offset 32 */ - com32_reg32_t eax; /* Offset 36 */ - - com32_reg32_t eflags; /* Offset 40 */ -} com32sys_t; - -typedef struct { - uint32_t eax; /* Offset 0 */ - uint32_t ecx; /* Offset 4 */ - uint32_t edx; /* Offset 8 */ - uint32_t ebx; /* Offset 12 */ - uint32_t esp; /* Offset 16 */ - uint32_t ebp; /* Offset 20 */ - uint32_t esi; /* Offset 24 */ - uint32_t edi; /* Offset 28 */ - - uint32_t eip; /* Offset 32 */ -} syslinux_pm_regs; - -typedef struct { - uint16_t es; /* Offset 0 */ - uint16_t _unused_cs; /* Offset 2 */ - uint16_t ds; /* Offset 4 */ - uint16_t ss; /* Offset 6 */ - uint16_t fs; /* Offset 8 */ - uint16_t gs; /* Offset 10 */ - - uint32_t eax; /* Offset 12 */ - uint32_t ecx; /* Offset 16 */ - uint32_t edx; /* Offset 20 */ - uint32_t ebx; /* Offset 24 */ - uint32_t esp; /* Offset 28 */ - uint32_t ebp; /* Offset 32 */ - uint32_t esi; /* Offset 36 */ - uint32_t edi; /* Offset 40 */ - - uint16_t ip; /* Offset 44 */ - uint16_t cs; /* Offset 46 */ -} syslinux_rm_regs; - -typedef struct { - uint32_t dest; - uint32_t src; - uint32_t len; -} comboot_shuffle_descriptor; - -extern void hook_comboot_interrupts ( ); -extern void unhook_comboot_interrupts ( ); - -/* These are not the correct prototypes, but it doens't matter, - * as we only ever get the address of these functions; - * they are only called from COM32 code running in PHYS_CODE - */ -extern void com32_intcall_wrapper ( ); -extern void com32_farcall_wrapper ( ); -extern void com32_cfarcall_wrapper ( ); - -/* Resolve a hostname to an (IPv4) address */ -extern int comboot_resolv ( const char *name, struct in_addr *address ); - -/* setjmp/longjmp context buffer used to return after loading an image */ -extern rmjmp_buf comboot_return; - -extern void *com32_external_esp; - -#define COMBOOT_EXIT 1 -#define COMBOOT_EXIT_RUN_KERNEL 2 -#define COMBOOT_EXIT_COMMAND 3 - -extern void comboot_force_text_mode ( void ); - -#define COMBOOT_VIDEO_GRAPHICS 0x01 -#define COMBOOT_VIDEO_NONSTANDARD 0x02 -#define COMBOOT_VIDEO_VESA 0x04 -#define COMBOOT_VIDEO_NOTEXT 0x08 - -#endif diff --git a/src/arch/i386/interface/syslinux/com32_call.c b/src/arch/i386/interface/syslinux/com32_call.c deleted file mode 100644 index 75dcc238f..000000000 --- a/src/arch/i386/interface/syslinux/com32_call.c +++ /dev/null @@ -1,191 +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 helpers - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <realmode.h> -#include <comboot.h> -#include <assert.h> -#include <ipxe/uaccess.h> - -static com32sys_t __bss16 ( com32_regs ); -#define com32_regs __use_data16 ( com32_regs ) - -static uint8_t __bss16 ( com32_int_vector ); -#define com32_int_vector __use_data16 ( com32_int_vector ) - -static uint32_t __bss16 ( com32_farcall_proc ); -#define com32_farcall_proc __use_data16 ( com32_farcall_proc ) - -uint16_t __bss16 ( com32_saved_sp ); - -/** - * Interrupt call helper - */ -void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) { - - memcpy_user ( virt_to_user( &com32_regs ), 0, - phys_to_user ( inregs_phys ), 0, - sizeof(com32sys_t) ); - - com32_int_vector = interrupt; - - __asm__ __volatile__ ( - REAL_CODE ( /* Save all registers */ - "pushal\n\t" - "pushw %%ds\n\t" - "pushw %%es\n\t" - "pushw %%fs\n\t" - "pushw %%gs\n\t" - /* Mask off unsafe flags */ - "movl (com32_regs + 40), %%eax\n\t" - "andl $0x200cd7, %%eax\n\t" - "movl %%eax, (com32_regs + 40)\n\t" - /* Load com32_regs into the actual registers */ - "movw %%sp, %%ss:(com32_saved_sp)\n\t" - "movw $com32_regs, %%sp\n\t" - "popw %%gs\n\t" - "popw %%fs\n\t" - "popw %%es\n\t" - "popw %%ds\n\t" - "popal\n\t" - "popfl\n\t" - "movw %%ss:(com32_saved_sp), %%sp\n\t" - /* patch INT instruction */ - "pushw %%ax\n\t" - "movb %%ss:(com32_int_vector), %%al\n\t" - "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t" - /* perform a jump to avoid problems with cache - * consistency in self-modifying code on some CPUs (486) - */ - "jmp 1f\n" - "1:\n\t" - "popw %%ax\n\t" - "com32_intcall_instr:\n\t" - /* INT instruction to be patched */ - "int $0xFF\n\t" - /* Copy regs back to com32_regs */ - "movw %%sp, %%ss:(com32_saved_sp)\n\t" - "movw $(com32_regs + 44), %%sp\n\t" - "pushfl\n\t" - "pushal\n\t" - "pushw %%ds\n\t" - "pushw %%es\n\t" - "pushw %%fs\n\t" - "pushw %%gs\n\t" - "movw %%ss:(com32_saved_sp), %%sp\n\t" - /* Restore registers */ - "popw %%gs\n\t" - "popw %%fs\n\t" - "popw %%es\n\t" - "popw %%ds\n\t" - "popal\n\t") - : : ); - - if ( outregs_phys ) { - memcpy_user ( phys_to_user ( outregs_phys ), 0, - virt_to_user( &com32_regs ), 0, - sizeof(com32sys_t) ); - } -} - -/** - * Farcall helper - */ -void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) { - - memcpy_user ( virt_to_user( &com32_regs ), 0, - phys_to_user ( inregs_phys ), 0, - sizeof(com32sys_t) ); - - com32_farcall_proc = proc; - - __asm__ __volatile__ ( - REAL_CODE ( /* Save all registers */ - "pushal\n\t" - "pushw %%ds\n\t" - "pushw %%es\n\t" - "pushw %%fs\n\t" - "pushw %%gs\n\t" - /* Mask off unsafe flags */ - "movl (com32_regs + 40), %%eax\n\t" - "andl $0x200cd7, %%eax\n\t" - "movl %%eax, (com32_regs + 40)\n\t" - /* Load com32_regs into the actual registers */ - "movw %%sp, %%ss:(com32_saved_sp)\n\t" - "movw $com32_regs, %%sp\n\t" - "popw %%gs\n\t" - "popw %%fs\n\t" - "popw %%es\n\t" - "popw %%ds\n\t" - "popal\n\t" - "popfl\n\t" - "movw %%ss:(com32_saved_sp), %%sp\n\t" - /* Call procedure */ - "lcall *%%ss:(com32_farcall_proc)\n\t" - /* Copy regs back to com32_regs */ - "movw %%sp, %%ss:(com32_saved_sp)\n\t" - "movw $(com32_regs + 44), %%sp\n\t" - "pushfl\n\t" - "pushal\n\t" - "pushw %%ds\n\t" - "pushw %%es\n\t" - "pushw %%fs\n\t" - "pushw %%gs\n\t" - "movw %%ss:(com32_saved_sp), %%sp\n\t" - /* Restore registers */ - "popw %%gs\n\t" - "popw %%fs\n\t" - "popw %%es\n\t" - "popw %%ds\n\t" - "popal\n\t") - : : ); - - if ( outregs_phys ) { - memcpy_user ( phys_to_user ( outregs_phys ), 0, - virt_to_user( &com32_regs ), 0, - sizeof(com32sys_t) ); - } -} - -/** - * CDECL farcall helper - */ -int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) { - int32_t eax; - - copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz ); - com32_farcall_proc = proc; - - __asm__ __volatile__ ( - REAL_CODE ( "lcall *%%ss:(com32_farcall_proc)\n\t" ) - : "=a" (eax) - : - : "ecx", "edx" ); - - remove_user_from_rm_stack ( 0, stacksz ); - - return eax; -} diff --git a/src/arch/i386/interface/syslinux/com32_wrapper.S b/src/arch/i386/interface/syslinux/com32_wrapper.S deleted file mode 100644 index c9d1452b4..000000000 --- a/src/arch/i386/interface/syslinux/com32_wrapper.S +++ /dev/null @@ -1,97 +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_LICENCE ( GPL2_OR_LATER ) - - .text - .arch i386 - .code32 - - .globl com32_farcall_wrapper -com32_farcall_wrapper: - - movl $com32_farcall, %eax - jmp com32_wrapper - - - .globl com32_cfarcall_wrapper -com32_cfarcall_wrapper: - - movl $com32_cfarcall, %eax - jmp com32_wrapper - - - .globl com32_intcall_wrapper -com32_intcall_wrapper: - - movl $com32_intcall, %eax - /*jmp com32_wrapper*/ /* fall through */ - -com32_wrapper: - cli - - /* Switch to internal virtual address space */ - call _phys_to_virt - - mov %eax, (com32_helper_function) - - /* Save external COM32 stack pointer */ - movl %esp, (com32_external_esp) - - /* Copy arguments to caller-save registers */ - movl 12(%esp), %eax - movl 8(%esp), %ecx - movl 4(%esp), %edx - - /* Switch to internal stack */ - movl (com32_internal_esp), %esp - - /* Copy arguments to internal stack */ - pushl %eax - pushl %ecx - pushl %edx - - call *(com32_helper_function) - - /* Clean up stack */ - addl $12, %esp - - /* Save internal stack pointer and restore external stack pointer */ - movl %esp, (com32_internal_esp) - movl (com32_external_esp), %esp - - /* Switch to external flat physical address space */ - call _virt_to_phys - - sti - ret - - - .data - -/* Internal iPXE virtual address space %esp */ -.globl com32_internal_esp -.lcomm com32_internal_esp, 4 - -/* External flat physical address space %esp */ -.globl com32_external_esp -.lcomm com32_external_esp, 4 - -/* Function pointer of helper to call */ -.lcomm com32_helper_function, 4 diff --git a/src/arch/i386/interface/syslinux/comboot_call.c b/src/arch/i386/interface/syslinux/comboot_call.c deleted file mode 100644 index 565977811..000000000 --- a/src/arch/i386/interface/syslinux/comboot_call.c +++ /dev/null @@ -1,705 +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 API - * - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <errno.h> -#include <realmode.h> -#include <biosint.h> -#include <ipxe/console.h> -#include <stdlib.h> -#include <comboot.h> -#include <bzimage.h> -#include <pxe_call.h> -#include <rmsetjmp.h> -#include <string.h> -#include <ipxe/posix_io.h> -#include <ipxe/process.h> -#include <ipxe/serial.h> -#include <ipxe/init.h> -#include <ipxe/image.h> -#include <ipxe/version.h> -#include <usr/imgmgmt.h> - -/** The "SYSLINUX" version string */ -static char __bss16_array ( syslinux_version, [32] ); -#define syslinux_version __use_data16 ( syslinux_version ) - -/** The "SYSLINUX" copyright string */ -static char __data16_array ( syslinux_copyright, [] ) = " http://ipxe.org"; -#define syslinux_copyright __use_data16 ( syslinux_copyright ) - -static char __data16_array ( syslinux_configuration_file, [] ) = ""; -#define syslinux_configuration_file __use_data16 ( syslinux_configuration_file ) - -/** Feature flags */ -static uint8_t __data16 ( comboot_feature_flags ) = COMBOOT_FEATURE_IDLE_LOOP; -#define comboot_feature_flags __use_data16 ( comboot_feature_flags ) - -typedef union { - syslinux_pm_regs pm; syslinux_rm_regs rm; -} syslinux_regs; - -/** Initial register values for INT 22h AX=1Ah and 1Bh */ -static syslinux_regs __text16 ( comboot_initial_regs ); -#define comboot_initial_regs __use_text16 ( comboot_initial_regs ) - -static struct segoff __text16 ( int20_vector ); -#define int20_vector __use_text16 ( int20_vector ) - -static struct segoff __text16 ( int21_vector ); -#define int21_vector __use_text16 ( int21_vector ) - -static struct segoff __text16 ( int22_vector ); -#define int22_vector __use_text16 ( int22_vector ) - -extern void int20_wrapper ( void ); -extern void int21_wrapper ( void ); -extern void int22_wrapper ( void ); - -/* setjmp/longjmp context buffer used to return after loading an image */ -rmjmp_buf comboot_return; - -/* Mode flags set by INT 22h AX=0017h */ -static uint16_t comboot_graphics_mode = 0; - -/** - * Print a string with a particular terminator - */ -static void print_user_string ( unsigned int segment, unsigned int offset, char terminator ) { - int i = 0; - char c; - userptr_t str = real_to_user ( segment, offset ); - for ( ; ; ) { - copy_from_user ( &c, str, i, 1 ); - if ( c == terminator ) break; - putchar ( c ); - i++; - } -} - - -/** - * Perform a series of memory copies from a list in low memory - */ -static void shuffle ( unsigned int list_segment, unsigned int list_offset, unsigned int count ) -{ - comboot_shuffle_descriptor shuf[COMBOOT_MAX_SHUFFLE_DESCRIPTORS]; - unsigned int i; - - /* Copy shuffle descriptor list so it doesn't get overwritten */ - copy_from_user ( shuf, real_to_user ( list_segment, list_offset ), 0, - count * sizeof( comboot_shuffle_descriptor ) ); - - /* Do the copies */ - for ( i = 0; i < count; i++ ) { - userptr_t src_u = phys_to_user ( shuf[ i ].src ); - userptr_t dest_u = phys_to_user ( shuf[ i ].dest ); - - if ( shuf[ i ].src == 0xFFFFFFFF ) { - /* Fill with 0 instead of copying */ - memset_user ( dest_u, 0, 0, shuf[ i ].len ); - } else if ( shuf[ i ].dest == 0xFFFFFFFF ) { - /* Copy new list of descriptors */ - count = shuf[ i ].len / sizeof( comboot_shuffle_descriptor ); - assert ( count <= COMBOOT_MAX_SHUFFLE_DESCRIPTORS ); - copy_from_user ( shuf, src_u, 0, shuf[ i ].len ); - i = -1; - } else { - /* Regular copy */ - memmove_user ( dest_u, 0, src_u, 0, shuf[ i ].len ); - } - } -} - - -/** - * Set default text mode - */ -void comboot_force_text_mode ( void ) { - if ( comboot_graphics_mode & COMBOOT_VIDEO_VESA ) { - /* Set VGA mode 3 via VESA VBE mode set */ - __asm__ __volatile__ ( - REAL_CODE ( - "mov $0x4F02, %%ax\n\t" - "mov $0x03, %%bx\n\t" - "int $0x10\n\t" - ) - : : ); - } else if ( comboot_graphics_mode & COMBOOT_VIDEO_GRAPHICS ) { - /* Set VGA mode 3 via standard VGA mode set */ - __asm__ __volatile__ ( - REAL_CODE ( - "mov $0x03, %%ax\n\t" - "int $0x10\n\t" - ) - : : ); - } - - comboot_graphics_mode = 0; -} - - -/** - * Fetch kernel and optional initrd - */ -static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) { - struct image *kernel; - struct image *initrd; - char *initrd_file; - int rc; - - /* Find initrd= parameter, if any */ - if ( ( initrd_file = strstr ( cmdline, "initrd=" ) ) != NULL ) { - char *initrd_end; - - /* skip "initrd=" */ - initrd_file += 7; - - /* Find terminating space, if any, and replace with NUL */ - initrd_end = strchr ( initrd_file, ' ' ); - if ( initrd_end ) - *initrd_end = '\0'; - - DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file ); - - /* Fetch initrd */ - if ( ( rc = imgdownload_string ( initrd_file, 0, - &initrd ) ) != 0 ) { - DBG ( "COMBOOT: could not fetch initrd: %s\n", - strerror ( rc ) ); - return rc; - } - - /* Restore space after initrd name, if applicable */ - if ( initrd_end ) - *initrd_end = ' '; - } - - DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file ); - - /* Fetch kernel */ - if ( ( rc = imgdownload_string ( kernel_file, 0, &kernel ) ) != 0 ) { - DBG ( "COMBOOT: could not fetch kernel: %s\n", - strerror ( rc ) ); - return rc; - } - - /* Replace comboot image with kernel */ - if ( ( rc = image_replace ( kernel ) ) != 0 ) { - DBG ( "COMBOOT: could not replace with kernel: %s\n", - strerror ( rc ) ); - return rc; - } - - return 0; -} - - -/** - * Terminate program interrupt handler - */ -static __asmcall void int20 ( struct i386_all_regs *ix86 __unused ) { - rmlongjmp ( comboot_return, COMBOOT_EXIT ); -} - - -/** - * DOS-compatible API - */ -static __asmcall void int21 ( struct i386_all_regs *ix86 ) { - ix86->flags |= CF; - - switch ( ix86->regs.ah ) { - case 0x00: - case 0x4C: /* Terminate program */ - rmlongjmp ( comboot_return, COMBOOT_EXIT ); - break; - - case 0x01: /* Get Key with Echo */ - case 0x08: /* Get Key without Echo */ - /* TODO: handle extended characters? */ - ix86->regs.al = getchar( ); - - /* Enter */ - if ( ix86->regs.al == 0x0A ) - ix86->regs.al = 0x0D; - - if ( ix86->regs.ah == 0x01 ) - putchar ( ix86->regs.al ); - - ix86->flags &= ~CF; - break; - - case 0x02: /* Write Character */ - putchar ( ix86->regs.dl ); - ix86->flags &= ~CF; - break; - - case 0x04: /* Write Character to Serial Port */ - if ( serial_console.base ) { - uart_transmit ( &serial_console, ix86->regs.dl ); - ix86->flags &= ~CF; - } - break; - - case 0x09: /* Write DOS String to Console */ - print_user_string ( ix86->segs.ds, ix86->regs.dx, '$' ); - ix86->flags &= ~CF; - break; - - case 0x0B: /* Check Keyboard */ - if ( iskey() ) - ix86->regs.al = 0xFF; - else - ix86->regs.al = 0x00; - - ix86->flags &= ~CF; - break; - - case 0x30: /* Check DOS Version */ - /* Bottom halves all 0; top halves spell "SYSLINUX" */ - ix86->regs.eax = 0x59530000; - ix86->regs.ebx = 0x4C530000; - ix86->regs.ecx = 0x4E490000; - ix86->regs.edx = 0x58550000; - ix86->flags &= ~CF; - break; - - default: - DBG ( "COMBOOT unknown int21 function %02x\n", ix86->regs.ah ); - break; - } -} - - -/** - * Dispatch PXE API call weakly - * - * @v ix86 Registers for PXE call - * @ret present Zero if the PXE stack is present, nonzero if not - * - * A successful return only indicates that the PXE stack was available - * for dispatching the call; it says nothing about the success of - * whatever the call asked for. - */ -__weak int pxe_api_call_weak ( struct i386_all_regs *ix86 __unused ) { - return -1; -} - -/** - * SYSLINUX API - */ -static __asmcall void int22 ( struct i386_all_regs *ix86 ) { - ix86->flags |= CF; - - switch ( ix86->regs.ax ) { - case 0x0001: /* Get Version */ - - /* Number of INT 22h API functions available */ - ix86->regs.ax = 0x001D; - - /* SYSLINUX version number */ - ix86->regs.ch = 0; /* major */ - ix86->regs.cl = 0; /* minor */ - - /* SYSLINUX derivative ID */ - ix86->regs.dl = BZI_LOADER_TYPE_IPXE; - - /* SYSLINUX version */ - snprintf ( syslinux_version, sizeof ( syslinux_version ), - "\r\niPXE %s", product_version ); - - /* SYSLINUX version and copyright strings */ - ix86->segs.es = rm_ds; - ix86->regs.si = ( ( unsigned ) __from_data16 ( syslinux_version ) ); - ix86->regs.di = ( ( unsigned ) __from_data16 ( syslinux_copyright ) ); - - ix86->flags &= ~CF; - break; - - case 0x0002: /* Write String */ - print_user_string ( ix86->segs.es, ix86->regs.bx, '\0' ); - ix86->flags &= ~CF; - break; - - case 0x0003: /* Run command */ - { - userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx ); - int len = strlen_user ( cmd_u, 0 ); - char cmd[len + 1]; - copy_from_user ( cmd, cmd_u, 0, len + 1 ); - DBG ( "COMBOOT: executing command '%s'\n", cmd ); - system ( cmd ); - DBG ( "COMBOOT: exiting after executing command...\n" ); - rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND ); - } - break; - - case 0x0004: /* Run default command */ - /* FIXME: just exit for now */ - rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND ); - break; - - case 0x0005: /* Force text mode */ - comboot_force_text_mode ( ); - ix86->flags &= ~CF; - break; - - case 0x0006: /* Open file */ - { - int fd; - userptr_t file_u = real_to_user ( ix86->segs.es, ix86->regs.si ); - int len = strlen_user ( file_u, 0 ); - char file[len + 1]; - - copy_from_user ( file, file_u, 0, len + 1 ); - - if ( file[0] == '\0' ) { - DBG ( "COMBOOT: attempted open with empty file name\n" ); - break; - } - - DBG ( "COMBOOT: opening file '%s'\n", file ); - - fd = open ( file ); - - if ( fd < 0 ) { - DBG ( "COMBOOT: error opening file %s\n", file ); - break; - } - - /* This relies on the fact that a iPXE POSIX fd will - * always fit in 16 bits. - */ -#if (POSIX_FD_MAX > 65535) -#error POSIX_FD_MAX too large -#endif - ix86->regs.si = (uint16_t) fd; - - ix86->regs.cx = COMBOOT_FILE_BLOCKSZ; - ix86->regs.eax = fsize ( fd ); - ix86->flags &= ~CF; - } - break; - - case 0x0007: /* Read file */ - { - int fd = ix86->regs.si; - int len = ix86->regs.cx * COMBOOT_FILE_BLOCKSZ; - int rc; - fd_set fds; - userptr_t buf = real_to_user ( ix86->segs.es, ix86->regs.bx ); - - /* Wait for data ready to read */ - FD_ZERO ( &fds ); - FD_SET ( fd, &fds ); - - select ( &fds, 1 ); - - rc = read_user ( fd, buf, 0, len ); - if ( rc < 0 ) { - DBG ( "COMBOOT: read failed\n" ); - ix86->regs.si = 0; - break; - } - - ix86->regs.ecx = rc; - ix86->flags &= ~CF; - } - break; - - case 0x0008: /* Close file */ - { - int fd = ix86->regs.si; - close ( fd ); - ix86->flags &= ~CF; - } - break; - - case 0x0009: /* Call PXE Stack */ - if ( pxe_api_call_weak ( ix86 ) != 0 ) - ix86->flags |= CF; - else - ix86->flags &= ~CF; - break; - - case 0x000A: /* Get Derivative-Specific Information */ - - /* iPXE has its own derivative ID, so there is no defined - * output here; just return AL for now */ - ix86->regs.al = BZI_LOADER_TYPE_IPXE; - ix86->flags &= ~CF; - break; - - case 0x000B: /* Get Serial Console Configuration */ - if ( serial_console.base ) { - ix86->regs.dx = ( ( intptr_t ) serial_console.base ); - ix86->regs.cx = serial_console.divisor; - ix86->regs.bx = 0; - ix86->flags &= ~CF; - } - break; - - case 0x000C: /* Perform final cleanup */ - shutdown_boot(); - break; - - case 0x000E: /* Get configuration file name */ - /* FIXME: stub */ - ix86->segs.es = rm_ds; - ix86->regs.bx = ( ( unsigned ) __from_data16 ( syslinux_configuration_file ) ); - ix86->flags &= ~CF; - break; - - case 0x000F: /* Get IPAPPEND strings */ - /* FIXME: stub */ - ix86->regs.cx = 0; - ix86->segs.es = 0; - ix86->regs.bx = 0; - ix86->flags &= ~CF; - break; - - case 0x0010: /* Resolve hostname */ - { - userptr_t hostname_u = real_to_user ( ix86->segs.es, ix86->regs.bx ); - int len = strlen_user ( hostname_u, 0 ); - char hostname[len]; - struct in_addr addr; - - copy_from_user ( hostname, hostname_u, 0, len + 1 ); - - /* TODO: - * "If the hostname does not contain a dot (.), the - * local domain name is automatically appended." - */ - - comboot_resolv ( hostname, &addr ); - - ix86->regs.eax = addr.s_addr; - ix86->flags &= ~CF; - } - break; - - case 0x0011: /* Maximum number of shuffle descriptors */ - ix86->regs.cx = COMBOOT_MAX_SHUFFLE_DESCRIPTORS; - ix86->flags &= ~CF; - break; - - case 0x0012: /* Cleanup, shuffle and boot */ - if ( ix86->regs.cx > COMBOOT_MAX_SHUFFLE_DESCRIPTORS ) - break; - - /* Perform final cleanup */ - shutdown_boot(); - - /* Perform sequence of copies */ - shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx ); - - /* Jump to real-mode entry point */ - __asm__ __volatile__ ( - REAL_CODE ( - "pushw %0\n\t" - "popw %%ds\n\t" - "pushl %1\n\t" - "lret\n\t" - ) - : - : "r" ( ix86->segs.ds ), - "r" ( ix86->regs.ebp ), - "d" ( ix86->regs.ebx ), - "S" ( ix86->regs.esi ) ); - - assert ( 0 ); /* Execution should never reach this point */ - - break; - - case 0x0013: /* Idle loop call */ - step ( ); - ix86->flags &= ~CF; - break; - - case 0x0015: /* Get feature flags */ - ix86->segs.es = rm_ds; - ix86->regs.bx = ( ( unsigned ) __from_data16 ( &comboot_feature_flags ) ); - ix86->regs.cx = 1; /* Number of feature flag bytes */ - ix86->flags &= ~CF; - break; - - case 0x0016: /* Run kernel image */ - { - userptr_t file_u = real_to_user ( ix86->segs.ds, ix86->regs.si ); - userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx ); - int file_len = strlen_user ( file_u, 0 ); - int cmd_len = strlen_user ( cmd_u, 0 ); - char file[file_len + 1]; - char cmd[cmd_len + 1]; - - copy_from_user ( file, file_u, 0, file_len + 1 ); - copy_from_user ( cmd, cmd_u, 0, cmd_len + 1 ); - - DBG ( "COMBOOT: run kernel %s %s\n", file, cmd ); - comboot_fetch_kernel ( file, cmd ); - /* Technically, we should return if we - * couldn't load the kernel, but it's not safe - * to do that since we have just overwritten - * part of the COMBOOT program's memory space. - */ - DBG ( "COMBOOT: exiting to run kernel...\n" ); - rmlongjmp ( comboot_return, COMBOOT_EXIT_RUN_KERNEL ); - } - break; - - case 0x0017: /* Report video mode change */ - comboot_graphics_mode = ix86->regs.bx; - ix86->flags &= ~CF; - break; - - case 0x0018: /* Query custom font */ - /* FIXME: stub */ - ix86->regs.al = 0; - ix86->segs.es = 0; - ix86->regs.bx = 0; - ix86->flags &= ~CF; - break; - - case 0x001B: /* Cleanup, shuffle and boot to real mode */ - if ( ix86->regs.cx > COMBOOT_MAX_SHUFFLE_DESCRIPTORS ) - break; - - /* Perform final cleanup */ - shutdown_boot(); - - /* Perform sequence of copies */ - shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx ); - - /* Copy initial register values to .text16 */ - memcpy_user ( real_to_user ( rm_cs, (unsigned) __from_text16 ( &comboot_initial_regs ) ), 0, - real_to_user ( ix86->segs.ds, ix86->regs.si ), 0, - sizeof(syslinux_rm_regs) ); - - /* Load initial register values */ - __asm__ __volatile__ ( - REAL_CODE ( - /* Point SS:SP at the register value structure */ - "pushw %%cs\n\t" - "popw %%ss\n\t" - "movw $comboot_initial_regs, %%sp\n\t" - - /* Segment registers */ - "popw %%es\n\t" - "popw %%ax\n\t" /* Skip CS */ - "popw %%ds\n\t" - "popw %%ax\n\t" /* Skip SS for now */ - "popw %%fs\n\t" - "popw %%gs\n\t" - - /* GP registers */ - "popl %%eax\n\t" - "popl %%ecx\n\t" - "popl %%edx\n\t" - "popl %%ebx\n\t" - "popl %%ebp\n\t" /* Skip ESP for now */ - "popl %%ebp\n\t" - "popl %%esi\n\t" - "popl %%edi\n\t" - - /* Load correct SS:ESP */ - "movw $(comboot_initial_regs + 6), %%sp\n\t" - "popw %%ss\n\t" - "movl %%cs:(comboot_initial_regs + 28), %%esp\n\t" - - "ljmp *%%cs:(comboot_initial_regs + 44)\n\t" - ) - : : ); - - break; - - case 0x001C: /* Get pointer to auxilliary data vector */ - /* FIXME: stub */ - ix86->regs.cx = 0; /* Size of the ADV */ - ix86->flags &= ~CF; - break; - - case 0x001D: /* Write auxilliary data vector */ - /* FIXME: stub */ - ix86->flags &= ~CF; - break; - - default: - DBG ( "COMBOOT unknown int22 function %04x\n", ix86->regs.ax ); - break; - } -} - -/** - * Hook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h) - */ -void hook_comboot_interrupts ( ) { - - __asm__ __volatile__ ( - TEXT16_CODE ( "\nint20_wrapper:\n\t" - VIRT_CALL ( int20 ) - "clc\n\t" - "call patch_cf\n\t" - "iret\n\t" ) ); - - hook_bios_interrupt ( 0x20, ( intptr_t ) int20_wrapper, &int20_vector ); - - __asm__ __volatile__ ( - TEXT16_CODE ( "\nint21_wrapper:\n\t" - VIRT_CALL ( int21 ) - "clc\n\t" - "call patch_cf\n\t" - "iret\n\t" ) ); - - hook_bios_interrupt ( 0x21, ( intptr_t ) int21_wrapper, &int21_vector ); - - __asm__ __volatile__ ( - TEXT16_CODE ( "\nint22_wrapper:\n\t" - VIRT_CALL ( int22 ) - "clc\n\t" - "call patch_cf\n\t" - "iret\n\t" ) ); - - hook_bios_interrupt ( 0x22, ( intptr_t ) int22_wrapper, &int22_vector ); -} - -/** - * Unhook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h) - */ -void unhook_comboot_interrupts ( ) { - - unhook_bios_interrupt ( 0x20, ( intptr_t ) int20_wrapper, - &int20_vector ); - - unhook_bios_interrupt ( 0x21, ( intptr_t ) int21_wrapper, - &int21_vector ); - - unhook_bios_interrupt ( 0x22, ( intptr_t ) int22_wrapper, - &int22_vector ); -} - -/* Avoid dragging in serial console support unconditionally */ -struct uart serial_console __attribute__ (( weak )); diff --git a/src/arch/i386/interface/syslinux/comboot_resolv.c b/src/arch/i386/interface/syslinux/comboot_resolv.c deleted file mode 100644 index 03bbfd04a..000000000 --- a/src/arch/i386/interface/syslinux/comboot_resolv.c +++ /dev/null @@ -1,61 +0,0 @@ -#include <errno.h> -#include <comboot.h> -#include <ipxe/in.h> -#include <ipxe/list.h> -#include <ipxe/process.h> -#include <ipxe/resolv.h> - -FILE_LICENCE ( GPL2_OR_LATER ); - -struct comboot_resolver { - struct interface intf; - int rc; - struct in_addr addr; -}; - -static void comboot_resolv_close ( struct comboot_resolver *comboot_resolver, - int rc ) { - comboot_resolver->rc = rc; - intf_shutdown ( &comboot_resolver->intf, rc ); -} - -static void comboot_resolv_done ( struct comboot_resolver *comboot_resolver, - struct sockaddr *sa ) { - struct sockaddr_in *sin; - - if ( sa->sa_family == AF_INET ) { - sin = ( ( struct sockaddr_in * ) sa ); - comboot_resolver->addr = sin->sin_addr; - } -} - -static struct interface_operation comboot_resolv_op[] = { - INTF_OP ( intf_close, struct comboot_resolver *, comboot_resolv_close ), - INTF_OP ( resolv_done, struct comboot_resolver *, comboot_resolv_done ), -}; - -static struct interface_descriptor comboot_resolv_desc = - INTF_DESC ( struct comboot_resolver, intf, comboot_resolv_op ); - -static struct comboot_resolver comboot_resolver = { - .intf = INTF_INIT ( comboot_resolv_desc ), -}; - -int comboot_resolv ( const char *name, struct in_addr *address ) { - int rc; - - comboot_resolver.rc = -EINPROGRESS; - comboot_resolver.addr.s_addr = 0; - - if ( ( rc = resolv ( &comboot_resolver.intf, name, NULL ) ) != 0 ) - return rc; - - while ( comboot_resolver.rc == -EINPROGRESS ) - step(); - - if ( ! comboot_resolver.addr.s_addr ) - return -EAFNOSUPPORT; - - *address = comboot_resolver.addr; - return comboot_resolver.rc; -} diff --git a/src/arch/i386/tests/comboot/shuffle-simple.asm b/src/arch/i386/tests/comboot/shuffle-simple.asm deleted file mode 100644 index 8ede8d097..000000000 --- a/src/arch/i386/tests/comboot/shuffle-simple.asm +++ /dev/null @@ -1,40 +0,0 @@ - bits 16 - org 100h - - jmp start - -shuffle_start: - push 0xB800 - pop es - mov cx, 80*24*2 - mov ax, 'AA' - xor di, di - rep stosw -.lbl: jmp .lbl -shuffle_end: - nop -shuffle_len equ (shuffle_end - shuffle_start + 1) - -start: - ; calculate physical address of shuffled part - xor eax, eax - push ds - pop ax - shl eax, 4 - add ax, shuffle_start - mov dword [source], eax - - mov ax, 0012h - mov di, shuffle_descriptors - mov cx, num_shuffle_descriptors - mov ebp, 0x7c00 - int 22h - int3 - -shuffle_descriptors: - dd 0x7C00 -source: dd 0 - dd shuffle_len - -num_shuffle_descriptors equ 1 - diff --git a/src/arch/i386/tests/comboot/version.asm b/src/arch/i386/tests/comboot/version.asm deleted file mode 100644 index 011404239..000000000 --- a/src/arch/i386/tests/comboot/version.asm +++ /dev/null @@ -1,136 +0,0 @@ - bits 16 - org 100h - -_start: - ; first check for SYSLINUX - mov ah, 30h - int 21h - - cmp eax, 59530000h - jne .not_syslinux - cmp ebx, 4c530000h - jne .not_syslinux - cmp ecx, 4e490000h - jne .not_syslinux - cmp edx, 58550000h - jne .not_syslinux - - ; now get syslinux version - mov ax, 0001h - int 22h - - push cx - push dx - push di - push si - push es - - ; print version string - mov dx, str_version - mov ah, 09h - int 21h - - pop es - pop bx - push es - mov ax, 0002h - int 22h - - ; print copyright string - mov dx, str_copyright - mov ah, 09h - int 21h - - pop es - pop bx - mov ax, 0002h - int 22h - - ; print syslinux derivative id - mov dx, str_derivative - mov ah, 09h - int 21h - - pop ax - call print_hex_byte - - ; print version number - mov dx, str_version_num - mov ah, 09h - int 21h - - pop cx - push cx - mov ax, cx - and ax, 0FFh - call print_dec_word - - mov dl, '.' - mov ah, 02h - int 21h - - pop cx - mov ax, cx - shr ax, 8 - call print_dec_word - - ret - - -.not_syslinux: - mov dx, str_not_syslinux - mov ah, 09h - int 21h - ret - -; input: al = byte to print in hex -print_hex_byte: - push ax - shr al, 4 - call print_hex_nybble - pop ax - call print_hex_nybble - ret - -; input: bottom half of al = nybble to print in hex -print_hex_nybble: - push ax - mov bl, al - and bx, 1111b - mov dl, [str_hex + bx] - mov ah, 02h - int 21h - pop ax - ret - -str_hex: db "01234567890abcdef" - -; input: ax = word to print -print_dec_word: - mov cx, 10 - mov word [.count], 0 -.loop: - xor dx, dx - div cx - inc word [.count] - push dx - test ax, ax - jnz .loop - -.print: - pop dx - add dx, '0' - mov ah, 02h - int 21h - dec word [.count] - jnz .print - - ret - -.count: dw 0 - -str_not_syslinux: db "Not SYSLINUX or derivative (running on DOS?)$" -str_version: db "Version: $" -str_copyright: db 10, "Copyright: $" -str_derivative: db 10, "Derivative ID: 0x$" -str_version_num: db 10, "Version number: $" |