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 );
/**
* 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;
}