From 97a3037f761dff106342eabf0f456888e0b59f16 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 14 Jan 2007 12:34:35 +0000 Subject: [PATCH] Can start a Linux kernel directly (albeit with no initrd support) --- src/arch/i386/image/bzimage.c | 37 +++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/arch/i386/image/bzimage.c b/src/arch/i386/image/bzimage.c index ff8536f08..48b690461 100644 --- a/src/arch/i386/image/bzimage.c +++ b/src/arch/i386/image/bzimage.c @@ -35,6 +35,20 @@ struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ); +/** + * bzImage execution context + */ +union bzimage_exec_context { + /** Real-mode parameters */ + struct { + /** Kernel real-mode data segment */ + uint16_t kernel_seg; + /** Kernel real-mode stack pointer */ + uint16_t stack; + } rm; + unsigned long ul; +}; + /** * Execute bzImage image * @@ -42,7 +56,10 @@ struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ); * @ret rc Return status code */ static int bzimage_exec ( struct image *image ) { - unsigned long rm_kernel_seg = image->priv.ul; + union bzimage_exec_context context; + + /* Retrieve stored execution context */ + context.ul = image->priv.ul; /* Prepare for exiting */ shutdown(); @@ -57,13 +74,14 @@ static int bzimage_exec ( struct image *image ) { "pushw %w2\n\t" "pushw $0\n\t" "lret\n\t" ) - : : "r" ( rm_kernel_seg ), - "i" ( BZI_STACK_SIZE ), - "r" ( rm_kernel_seg + 0x20 ) ); + : : "r" ( context.rm.kernel_seg ), + "r" ( context.rm.stack ), + "r" ( context.rm.kernel_seg + 0x20 ) ); /* There is no way for the image to return, since we provide * no return address. */ + assert ( 0 ); return -ECANCELED; /* -EIMPOSSIBLE */ } @@ -76,7 +94,8 @@ static int bzimage_exec ( struct image *image ) { */ int bzimage_load ( struct image *image ) { struct bzimage_header bzhdr; - unsigned int rm_kernel_seg = 0x7c0; /* place RM kernel at 07c0:0000 */ + union bzimage_exec_context context; + unsigned int rm_kernel_seg = 0x1000; /* place RM kernel at 1000:0000 */ userptr_t rm_kernel = real_to_user ( rm_kernel_seg, 0 ); userptr_t pm_kernel; size_t rm_filesz; @@ -115,7 +134,7 @@ int bzimage_load ( struct image *image ) { DBGC ( image, "bzImage %p version %04x\n", image, bzhdr.version ); /* Check size of base memory portions */ - rm_filesz = ( ( bzhdr.setup_sects ? bzhdr.setup_sects : 4 ) << 9 ); + rm_filesz = ( ( bzhdr.setup_sects ? bzhdr.setup_sects : 4 ) + 1 ) << 9; if ( rm_filesz > image->len ) { DBGC ( image, "bzImage %p too short for %zd byte of setup\n", image, rm_filesz ); @@ -177,8 +196,10 @@ int bzimage_load ( struct image *image ) { } copy_to_user ( rm_kernel, BZI_HDR_OFFSET, &bzhdr, sizeof ( bzhdr ) ); - /* Record segment address in image private data field */ - image->priv.ul = rm_kernel_seg; + /* Record execution context in image private data field */ + context.rm.kernel_seg = rm_kernel_seg; + context.rm.stack = rm_heap_end; + image->priv.ul = context.ul; return 0; }