Can start a Linux kernel directly (albeit with no initrd support)

pull/1/head
Michael Brown 2007-01-14 12:34:35 +00:00
parent 3cbf0db0a3
commit 97a3037f76
1 changed files with 29 additions and 8 deletions

View File

@ -35,6 +35,20 @@
struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ); 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 * Execute bzImage image
* *
@ -42,7 +56,10 @@ struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
* @ret rc Return status code * @ret rc Return status code
*/ */
static int bzimage_exec ( struct image *image ) { 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 */ /* Prepare for exiting */
shutdown(); shutdown();
@ -57,13 +74,14 @@ static int bzimage_exec ( struct image *image ) {
"pushw %w2\n\t" "pushw %w2\n\t"
"pushw $0\n\t" "pushw $0\n\t"
"lret\n\t" ) "lret\n\t" )
: : "r" ( rm_kernel_seg ), : : "r" ( context.rm.kernel_seg ),
"i" ( BZI_STACK_SIZE ), "r" ( context.rm.stack ),
"r" ( rm_kernel_seg + 0x20 ) ); "r" ( context.rm.kernel_seg + 0x20 ) );
/* There is no way for the image to return, since we provide /* There is no way for the image to return, since we provide
* no return address. * no return address.
*/ */
assert ( 0 );
return -ECANCELED; /* -EIMPOSSIBLE */ return -ECANCELED; /* -EIMPOSSIBLE */
} }
@ -76,7 +94,8 @@ static int bzimage_exec ( struct image *image ) {
*/ */
int bzimage_load ( struct image *image ) { int bzimage_load ( struct image *image ) {
struct bzimage_header bzhdr; 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 rm_kernel = real_to_user ( rm_kernel_seg, 0 );
userptr_t pm_kernel; userptr_t pm_kernel;
size_t rm_filesz; size_t rm_filesz;
@ -115,7 +134,7 @@ int bzimage_load ( struct image *image ) {
DBGC ( image, "bzImage %p version %04x\n", image, bzhdr.version ); DBGC ( image, "bzImage %p version %04x\n", image, bzhdr.version );
/* Check size of base memory portions */ /* 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 ) { if ( rm_filesz > image->len ) {
DBGC ( image, "bzImage %p too short for %zd byte of setup\n", DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
image, rm_filesz ); image, rm_filesz );
@ -177,8 +196,10 @@ int bzimage_load ( struct image *image ) {
} }
copy_to_user ( rm_kernel, BZI_HDR_OFFSET, &bzhdr, sizeof ( bzhdr ) ); copy_to_user ( rm_kernel, BZI_HDR_OFFSET, &bzhdr, sizeof ( bzhdr ) );
/* Record segment address in image private data field */ /* Record execution context in image private data field */
image->priv.ul = rm_kernel_seg; context.rm.kernel_seg = rm_kernel_seg;
context.rm.stack = rm_heap_end;
image->priv.ul = context.ul;
return 0; return 0;
} }