|  | @@ -35,18 +35,36 @@
 | 
		
	
		
			
			| 35 | 35 |  
 | 
		
	
		
			
			| 36 | 36 |  struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
 | 
		
	
		
			
			| 37 | 37 |  
 | 
		
	
		
			
			|  | 38 | +/**
 | 
		
	
		
			
			|  | 39 | + * bzImage load context
 | 
		
	
		
			
			|  | 40 | + */
 | 
		
	
		
			
			|  | 41 | +struct bzimage_load_context {
 | 
		
	
		
			
			|  | 42 | +	/** Real-mode kernel portion load segment address */
 | 
		
	
		
			
			|  | 43 | +	unsigned int rm_kernel_seg;
 | 
		
	
		
			
			|  | 44 | +	/** Real-mode kernel portion load address */
 | 
		
	
		
			
			|  | 45 | +	userptr_t rm_kernel;
 | 
		
	
		
			
			|  | 46 | +	/** Real-mode kernel portion file size */
 | 
		
	
		
			
			|  | 47 | +	size_t rm_filesz;
 | 
		
	
		
			
			|  | 48 | +	/** Real-mode heap top (offset from rm_kernel) */
 | 
		
	
		
			
			|  | 49 | +	size_t rm_heap;
 | 
		
	
		
			
			|  | 50 | +	/** Command line (offset from rm_kernel) */
 | 
		
	
		
			
			|  | 51 | +	size_t rm_cmdline;
 | 
		
	
		
			
			|  | 52 | +	/** Real-mode kernel portion total memory size */
 | 
		
	
		
			
			|  | 53 | +	size_t rm_memsz;
 | 
		
	
		
			
			|  | 54 | +	/** Non-real-mode kernel portion load address */
 | 
		
	
		
			
			|  | 55 | +	userptr_t pm_kernel;
 | 
		
	
		
			
			|  | 56 | +	/** Non-real-mode kernel portion file and memory size */
 | 
		
	
		
			
			|  | 57 | +	size_t pm_sz;
 | 
		
	
		
			
			|  | 58 | +};
 | 
		
	
		
			
			|  | 59 | +
 | 
		
	
		
			
			| 38 | 60 |  /**
 | 
		
	
		
			
			| 39 | 61 |   * bzImage execution context
 | 
		
	
		
			
			| 40 | 62 |   */
 | 
		
	
		
			
			| 41 |  | -union bzimage_exec_context {
 | 
		
	
		
			
			| 42 |  | -	/** Real-mode parameters */
 | 
		
	
		
			
			| 43 |  | -	struct {
 | 
		
	
		
			
			| 44 |  | -		/** Kernel real-mode data segment */
 | 
		
	
		
			
			| 45 |  | -		uint16_t kernel_seg;
 | 
		
	
		
			
			| 46 |  | -		/** Kernel real-mode stack pointer */
 | 
		
	
		
			
			| 47 |  | -		uint16_t stack;
 | 
		
	
		
			
			| 48 |  | -	} rm;
 | 
		
	
		
			
			| 49 |  | -	unsigned long ul;
 | 
		
	
		
			
			|  | 63 | +struct bzimage_exec_context {
 | 
		
	
		
			
			|  | 64 | +	/** Kernel real-mode data segment */
 | 
		
	
		
			
			|  | 65 | +	uint16_t kernel_seg;
 | 
		
	
		
			
			|  | 66 | +	/** Kernel real-mode stack pointer */
 | 
		
	
		
			
			|  | 67 | +	uint16_t stack;
 | 
		
	
		
			
			| 50 | 68 |  };
 | 
		
	
		
			
			| 51 | 69 |  
 | 
		
	
		
			
			| 52 | 70 |  /**
 | 
		
	
	
		
			
			|  | @@ -56,10 +74,13 @@ union bzimage_exec_context {
 | 
		
	
		
			
			| 56 | 74 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 57 | 75 |   */
 | 
		
	
		
			
			| 58 | 76 |  static int bzimage_exec ( struct image *image ) {
 | 
		
	
		
			
			| 59 |  | -	union bzimage_exec_context context;
 | 
		
	
		
			
			|  | 77 | +	union {
 | 
		
	
		
			
			|  | 78 | +		struct bzimage_exec_context bz;
 | 
		
	
		
			
			|  | 79 | +		unsigned long ul;
 | 
		
	
		
			
			|  | 80 | +	} exec_ctx;
 | 
		
	
		
			
			| 60 | 81 |  
 | 
		
	
		
			
			| 61 | 82 |  	/* Retrieve stored execution context */
 | 
		
	
		
			
			| 62 |  | -	context.ul = image->priv.ul;
 | 
		
	
		
			
			|  | 83 | +	exec_ctx.ul = image->priv.ul;
 | 
		
	
		
			
			| 63 | 84 |  
 | 
		
	
		
			
			| 64 | 85 |  	/* Prepare for exiting */
 | 
		
	
		
			
			| 65 | 86 |  	shutdown();
 | 
		
	
	
		
			
			|  | @@ -74,9 +95,9 @@ static int bzimage_exec ( struct image *image ) {
 | 
		
	
		
			
			| 74 | 95 |  					   "pushw %w2\n\t"
 | 
		
	
		
			
			| 75 | 96 |  					   "pushw $0\n\t"
 | 
		
	
		
			
			| 76 | 97 |  					   "lret\n\t" )
 | 
		
	
		
			
			| 77 |  | -			       : : "r" ( context.rm.kernel_seg ),
 | 
		
	
		
			
			| 78 |  | -			           "r" ( context.rm.stack ),
 | 
		
	
		
			
			| 79 |  | -			           "r" ( context.rm.kernel_seg + 0x20 ) );
 | 
		
	
		
			
			|  | 98 | +			       : : "r" ( exec_ctx.bz.kernel_seg ),
 | 
		
	
		
			
			|  | 99 | +			           "r" ( exec_ctx.bz.stack ),
 | 
		
	
		
			
			|  | 100 | +			           "r" ( exec_ctx.bz.kernel_seg + 0x20 ) );
 | 
		
	
		
			
			| 80 | 101 |  
 | 
		
	
		
			
			| 81 | 102 |  	/* There is no way for the image to return, since we provide
 | 
		
	
		
			
			| 82 | 103 |  	 * no return address.
 | 
		
	
	
		
			
			|  | @@ -87,119 +108,200 @@ static int bzimage_exec ( struct image *image ) {
 | 
		
	
		
			
			| 87 | 108 |  }
 | 
		
	
		
			
			| 88 | 109 |  
 | 
		
	
		
			
			| 89 | 110 |  /**
 | 
		
	
		
			
			| 90 |  | - * Load bzImage image into memory
 | 
		
	
		
			
			|  | 111 | + * Load and parse bzImage header
 | 
		
	
		
			
			| 91 | 112 |   *
 | 
		
	
		
			
			| 92 | 113 |   * @v image		bzImage file
 | 
		
	
		
			
			|  | 114 | + * @v load_ctx		Load context
 | 
		
	
		
			
			|  | 115 | + * @v bzhdr		Buffer for bzImage header
 | 
		
	
		
			
			| 93 | 116 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 94 | 117 |   */
 | 
		
	
		
			
			| 95 |  | -int bzimage_load ( struct image *image ) {
 | 
		
	
		
			
			| 96 |  | -	struct bzimage_header bzhdr;
 | 
		
	
		
			
			| 97 |  | -	union bzimage_exec_context context;
 | 
		
	
		
			
			| 98 |  | -	unsigned int rm_kernel_seg = 0x1000; /* place RM kernel at 1000:0000 */
 | 
		
	
		
			
			| 99 |  | -	userptr_t rm_kernel = real_to_user ( rm_kernel_seg, 0 );
 | 
		
	
		
			
			| 100 |  | -	userptr_t pm_kernel;
 | 
		
	
		
			
			| 101 |  | -	size_t rm_filesz;
 | 
		
	
		
			
			| 102 |  | -	size_t rm_memsz;
 | 
		
	
		
			
			| 103 |  | -	size_t pm_filesz;
 | 
		
	
		
			
			| 104 |  | -	size_t pm_memsz;
 | 
		
	
		
			
			| 105 |  | -	size_t rm_heap_end;
 | 
		
	
		
			
			| 106 |  | -	size_t rm_cmdline;
 | 
		
	
		
			
			| 107 |  | -	int rc;
 | 
		
	
		
			
			|  | 118 | +static int bzimage_load_header ( struct image *image,
 | 
		
	
		
			
			|  | 119 | +				 struct bzimage_load_context *load_ctx,
 | 
		
	
		
			
			|  | 120 | +				 struct bzimage_header *bzhdr ) {
 | 
		
	
		
			
			| 108 | 121 |  
 | 
		
	
		
			
			| 109 | 122 |  	/* Sanity check */
 | 
		
	
		
			
			| 110 |  | -	if ( image->len < ( BZI_HDR_OFFSET + sizeof ( bzhdr ) ) ) {
 | 
		
	
		
			
			|  | 123 | +	if ( image->len < ( BZI_HDR_OFFSET + sizeof ( *bzhdr ) ) ) {
 | 
		
	
		
			
			| 111 | 124 |  		DBGC ( image, "bzImage %p too short for kernel header\n",
 | 
		
	
		
			
			| 112 | 125 |  		       image );
 | 
		
	
		
			
			| 113 | 126 |  		return -ENOEXEC;
 | 
		
	
		
			
			| 114 | 127 |  	}
 | 
		
	
		
			
			| 115 | 128 |  
 | 
		
	
		
			
			| 116 | 129 |  	/* Read and verify header */
 | 
		
	
		
			
			| 117 |  | -	copy_from_user ( &bzhdr, image->data, BZI_HDR_OFFSET,
 | 
		
	
		
			
			| 118 |  | -			 sizeof ( bzhdr ) );
 | 
		
	
		
			
			| 119 |  | -	if ( bzhdr.header != BZI_SIGNATURE ) {
 | 
		
	
		
			
			| 120 |  | -		DBGC ( image, "bzImage %p not a bzImage\n", image );
 | 
		
	
		
			
			|  | 130 | +	copy_from_user ( bzhdr, image->data, BZI_HDR_OFFSET,
 | 
		
	
		
			
			|  | 131 | +			 sizeof ( *bzhdr ) );
 | 
		
	
		
			
			|  | 132 | +	if ( bzhdr->header != BZI_SIGNATURE ) {
 | 
		
	
		
			
			|  | 133 | +		DBGC ( image, "bzImage %p bad signature\n", image );
 | 
		
	
		
			
			| 121 | 134 |  		return -ENOEXEC;
 | 
		
	
		
			
			| 122 | 135 |  	}
 | 
		
	
		
			
			| 123 | 136 |  
 | 
		
	
		
			
			| 124 |  | -	/* This is a bzImage image, valid or otherwise */
 | 
		
	
		
			
			| 125 |  | -	if ( ! image->type )
 | 
		
	
		
			
			| 126 |  | -		image->type = &bzimage_image_type;
 | 
		
	
		
			
			| 127 |  | -
 | 
		
	
		
			
			| 128 | 137 |  	/* We don't support ancient kernels */
 | 
		
	
		
			
			| 129 |  | -	if ( bzhdr.version < 0x0200 ) {
 | 
		
	
		
			
			|  | 138 | +	if ( bzhdr->version < 0x0200 ) {
 | 
		
	
		
			
			| 130 | 139 |  		DBGC ( image, "bzImage %p version %04x not supported\n",
 | 
		
	
		
			
			| 131 |  | -		       image, bzhdr.version );
 | 
		
	
		
			
			|  | 140 | +		       image, bzhdr->version );
 | 
		
	
		
			
			| 132 | 141 |  		return -ENOTSUP;
 | 
		
	
		
			
			| 133 | 142 |  	}
 | 
		
	
		
			
			| 134 |  | -	DBGC ( image, "bzImage %p version %04x\n", image, bzhdr.version );
 | 
		
	
		
			
			| 135 | 143 |  
 | 
		
	
		
			
			| 136 |  | -	/* Check size of base memory portions */
 | 
		
	
		
			
			| 137 |  | -	rm_filesz = ( ( bzhdr.setup_sects ? bzhdr.setup_sects : 4 ) + 1 ) << 9;
 | 
		
	
		
			
			| 138 |  | -	if ( rm_filesz > image->len ) {
 | 
		
	
		
			
			|  | 144 | +	/* Calculate load address and size of real-mode portion */
 | 
		
	
		
			
			|  | 145 | +	load_ctx->rm_kernel_seg = 0x1000; /* place RM kernel at 1000:0000 */
 | 
		
	
		
			
			|  | 146 | +	load_ctx->rm_kernel = real_to_user ( load_ctx->rm_kernel_seg, 0 );
 | 
		
	
		
			
			|  | 147 | +	load_ctx->rm_filesz = load_ctx->rm_memsz =
 | 
		
	
		
			
			|  | 148 | +		( ( bzhdr->setup_sects ? bzhdr->setup_sects : 4 ) + 1 ) << 9;
 | 
		
	
		
			
			|  | 149 | +	if ( load_ctx->rm_filesz > image->len ) {
 | 
		
	
		
			
			| 139 | 150 |  		DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
 | 
		
	
		
			
			| 140 |  | -		       image, rm_filesz );
 | 
		
	
		
			
			|  | 151 | +		       image, load_ctx->rm_filesz );
 | 
		
	
		
			
			| 141 | 152 |  		return -ENOEXEC;
 | 
		
	
		
			
			| 142 | 153 |  	}
 | 
		
	
		
			
			| 143 |  | -	rm_memsz = rm_filesz;
 | 
		
	
		
			
			|  | 154 | +
 | 
		
	
		
			
			|  | 155 | +	/* Calculate load address and size of non-real-mode portion */
 | 
		
	
		
			
			|  | 156 | +	load_ctx->pm_kernel = ( ( bzhdr->loadflags & BZI_LOAD_HIGH ) ?
 | 
		
	
		
			
			|  | 157 | +				phys_to_user ( BZI_LOAD_HIGH_ADDR ) :
 | 
		
	
		
			
			|  | 158 | +				phys_to_user ( BZI_LOAD_LOW_ADDR ) );
 | 
		
	
		
			
			|  | 159 | +	load_ctx->pm_sz = ( image->len - load_ctx->rm_filesz );
 | 
		
	
		
			
			|  | 160 | +
 | 
		
	
		
			
			|  | 161 | +	DBGC ( image, "bzImage %p version %04x RM %#zx bytes PM %#zx bytes\n",
 | 
		
	
		
			
			|  | 162 | +	       image, bzhdr->version, load_ctx->rm_filesz, load_ctx->pm_sz );
 | 
		
	
		
			
			|  | 163 | +	return 0;
 | 
		
	
		
			
			|  | 164 | +}
 | 
		
	
		
			
			|  | 165 | +
 | 
		
	
		
			
			|  | 166 | +/**
 | 
		
	
		
			
			|  | 167 | + * Load real-mode portion of bzImage
 | 
		
	
		
			
			|  | 168 | + *
 | 
		
	
		
			
			|  | 169 | + * @v image		bzImage file
 | 
		
	
		
			
			|  | 170 | + * @v load_ctx		Load context
 | 
		
	
		
			
			|  | 171 | + * @v cmdline		Kernel command line
 | 
		
	
		
			
			|  | 172 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 173 | + */
 | 
		
	
		
			
			|  | 174 | +static int bzimage_load_real ( struct image *image,
 | 
		
	
		
			
			|  | 175 | +			       struct bzimage_load_context *load_ctx,
 | 
		
	
		
			
			|  | 176 | +			       const char *cmdline ) {
 | 
		
	
		
			
			|  | 177 | +	size_t cmdline_len = ( strlen ( cmdline ) + 1 );
 | 
		
	
		
			
			|  | 178 | +	int rc;
 | 
		
	
		
			
			| 144 | 179 |  
 | 
		
	
		
			
			| 145 | 180 |  	/* Allow space for the stack and heap */
 | 
		
	
		
			
			| 146 |  | -	rm_memsz += BZI_STACK_SIZE;
 | 
		
	
		
			
			| 147 |  | -	rm_heap_end = rm_memsz;
 | 
		
	
		
			
			|  | 181 | +	load_ctx->rm_memsz += BZI_STACK_SIZE;
 | 
		
	
		
			
			|  | 182 | +	load_ctx->rm_heap = load_ctx->rm_memsz;
 | 
		
	
		
			
			| 148 | 183 |  
 | 
		
	
		
			
			| 149 | 184 |  	/* Allow space for the command line, if one exists */
 | 
		
	
		
			
			| 150 |  | -	rm_cmdline = rm_memsz;
 | 
		
	
		
			
			| 151 |  | -	if ( image->cmdline )
 | 
		
	
		
			
			| 152 |  | -		rm_memsz += ( strlen ( image->cmdline ) + 1 );
 | 
		
	
		
			
			|  | 185 | +	load_ctx->rm_cmdline = load_ctx->rm_memsz;
 | 
		
	
		
			
			|  | 186 | +	load_ctx->rm_memsz += cmdline_len;
 | 
		
	
		
			
			| 153 | 187 |  
 | 
		
	
		
			
			| 154 | 188 |  	/* Prepare, verify, and load the real-mode segment */
 | 
		
	
		
			
			| 155 |  | -	if ( ( rc = prep_segment ( rm_kernel, rm_filesz, rm_memsz ) ) != 0 ) {
 | 
		
	
		
			
			|  | 189 | +	if ( ( rc = prep_segment ( load_ctx->rm_kernel, load_ctx->rm_filesz,
 | 
		
	
		
			
			|  | 190 | +				   load_ctx->rm_memsz ) ) != 0 ) {
 | 
		
	
		
			
			| 156 | 191 |  		DBGC ( image, "bzImage %p could not prepare RM segment: %s\n",
 | 
		
	
		
			
			| 157 | 192 |  		       image, strerror ( rc ) );
 | 
		
	
		
			
			| 158 | 193 |  		return rc;
 | 
		
	
		
			
			| 159 | 194 |  	}
 | 
		
	
		
			
			| 160 |  | -	memcpy_user ( rm_kernel, 0, image->data, 0, rm_filesz );
 | 
		
	
		
			
			|  | 195 | +	memcpy_user ( load_ctx->rm_kernel, 0, image->data, 0,
 | 
		
	
		
			
			|  | 196 | +		      load_ctx->rm_filesz );
 | 
		
	
		
			
			|  | 197 | +
 | 
		
	
		
			
			|  | 198 | +	/* Copy command line */
 | 
		
	
		
			
			|  | 199 | +	copy_to_user ( load_ctx->rm_kernel, load_ctx->rm_cmdline,
 | 
		
	
		
			
			|  | 200 | +		       cmdline, cmdline_len );
 | 
		
	
		
			
			|  | 201 | +
 | 
		
	
		
			
			|  | 202 | +	return 0;
 | 
		
	
		
			
			|  | 203 | +}
 | 
		
	
		
			
			| 161 | 204 |  
 | 
		
	
		
			
			| 162 |  | -	/* Prepare, verify and load the rest of the kernel */
 | 
		
	
		
			
			| 163 |  | -	pm_kernel = ( ( bzhdr.loadflags & BZI_LOAD_HIGH ) ?
 | 
		
	
		
			
			| 164 |  | -		      phys_to_user ( 0x100000 ) : phys_to_user ( 0x10000 ) );
 | 
		
	
		
			
			| 165 |  | -	pm_filesz = pm_memsz = ( image->len - rm_filesz );
 | 
		
	
		
			
			| 166 |  | -	if ( ( rc = prep_segment ( pm_kernel, pm_filesz, pm_memsz ) ) != 0 ) {
 | 
		
	
		
			
			|  | 205 | +/**
 | 
		
	
		
			
			|  | 206 | + * Load non-real-mode portion of bzImage
 | 
		
	
		
			
			|  | 207 | + *
 | 
		
	
		
			
			|  | 208 | + * @v image		bzImage file
 | 
		
	
		
			
			|  | 209 | + * @v load_ctx		Load context
 | 
		
	
		
			
			|  | 210 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 211 | + */
 | 
		
	
		
			
			|  | 212 | +static int bzimage_load_non_real ( struct image *image,
 | 
		
	
		
			
			|  | 213 | +				   struct bzimage_load_context *load_ctx ) {
 | 
		
	
		
			
			|  | 214 | +	int rc;
 | 
		
	
		
			
			|  | 215 | +
 | 
		
	
		
			
			|  | 216 | +	/* Prepare, verify and load the non-real-mode segment */
 | 
		
	
		
			
			|  | 217 | +	if ( ( rc = prep_segment ( load_ctx->pm_kernel, load_ctx->pm_sz,
 | 
		
	
		
			
			|  | 218 | +				   load_ctx->pm_sz ) ) != 0 ) {
 | 
		
	
		
			
			| 167 | 219 |  		DBGC ( image, "bzImage %p could not prepare PM segment: %s\n",
 | 
		
	
		
			
			| 168 | 220 |  		       image, strerror ( rc ) );
 | 
		
	
		
			
			| 169 | 221 |  		return rc;
 | 
		
	
		
			
			| 170 | 222 |  	}
 | 
		
	
		
			
			| 171 |  | -	memcpy_user ( pm_kernel, 0, image->data, rm_filesz, pm_filesz );
 | 
		
	
		
			
			|  | 223 | +	memcpy_user ( load_ctx->pm_kernel, 0, image->data, load_ctx->rm_filesz,
 | 
		
	
		
			
			|  | 224 | +		      load_ctx->pm_sz );
 | 
		
	
		
			
			|  | 225 | +
 | 
		
	
		
			
			|  | 226 | +	return 0;
 | 
		
	
		
			
			|  | 227 | +}
 | 
		
	
		
			
			| 172 | 228 |  
 | 
		
	
		
			
			| 173 |  | -	/* Copy down the command line, if it exists */
 | 
		
	
		
			
			| 174 |  | -	if ( image->cmdline ) {
 | 
		
	
		
			
			| 175 |  | -		copy_to_user ( rm_kernel, rm_cmdline, image->cmdline,
 | 
		
	
		
			
			| 176 |  | -			       strlen ( image->cmdline ) + 1 );
 | 
		
	
		
			
			| 177 |  | -	}
 | 
		
	
		
			
			|  | 229 | +
 | 
		
	
		
			
			|  | 230 | +/**
 | 
		
	
		
			
			|  | 231 | + * Update and store bzImage header
 | 
		
	
		
			
			|  | 232 | + *
 | 
		
	
		
			
			|  | 233 | + * @v image		bzImage file
 | 
		
	
		
			
			|  | 234 | + * @v load_ctx		Load context
 | 
		
	
		
			
			|  | 235 | + * @v bzhdr		Original bzImage header
 | 
		
	
		
			
			|  | 236 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 237 | + */
 | 
		
	
		
			
			|  | 238 | +static int bzimage_write_header ( struct image *image __unused,
 | 
		
	
		
			
			|  | 239 | +				  struct bzimage_load_context *load_ctx,
 | 
		
	
		
			
			|  | 240 | +				  struct bzimage_header *bzhdr ) {
 | 
		
	
		
			
			|  | 241 | +	struct bzimage_cmdline cmdline;
 | 
		
	
		
			
			| 178 | 242 |  
 | 
		
	
		
			
			| 179 | 243 |  	/* Update the header and copy it into the loaded kernel */
 | 
		
	
		
			
			| 180 |  | -	bzhdr.type_of_loader = BZI_LOADER_TYPE_ETHERBOOT;
 | 
		
	
		
			
			| 181 |  | -	if ( bzhdr.version >= 0x0201 ) {
 | 
		
	
		
			
			| 182 |  | -		bzhdr.heap_end_ptr = ( rm_heap_end - 0x200 );
 | 
		
	
		
			
			| 183 |  | -		bzhdr.loadflags |= BZI_CAN_USE_HEAP;
 | 
		
	
		
			
			|  | 244 | +	bzhdr->type_of_loader = BZI_LOADER_TYPE_ETHERBOOT;
 | 
		
	
		
			
			|  | 245 | +	if ( bzhdr->version >= 0x0201 ) {
 | 
		
	
		
			
			|  | 246 | +		bzhdr->heap_end_ptr = ( load_ctx->rm_heap - 0x200 );
 | 
		
	
		
			
			|  | 247 | +		bzhdr->loadflags |= BZI_CAN_USE_HEAP;
 | 
		
	
		
			
			| 184 | 248 |  	}
 | 
		
	
		
			
			| 185 |  | -	if ( bzhdr.version >= 0x0202 ) {
 | 
		
	
		
			
			| 186 |  | -		bzhdr.cmd_line_ptr = user_to_phys ( rm_kernel, rm_cmdline );
 | 
		
	
		
			
			|  | 249 | +	if ( bzhdr->version >= 0x0202 ) {
 | 
		
	
		
			
			|  | 250 | +		bzhdr->cmd_line_ptr = user_to_phys ( load_ctx->rm_kernel,
 | 
		
	
		
			
			|  | 251 | +						     load_ctx->rm_cmdline );
 | 
		
	
		
			
			| 187 | 252 |  	} else {
 | 
		
	
		
			
			| 188 |  | -		uint16_t cmd_line_magic = BZI_CMD_LINE_MAGIC;
 | 
		
	
		
			
			| 189 |  | -		uint16_t cmd_line_offset = rm_cmdline;
 | 
		
	
		
			
			| 190 |  | -
 | 
		
	
		
			
			| 191 |  | -		put_real ( cmd_line_magic, rm_kernel_seg,
 | 
		
	
		
			
			| 192 |  | -			   BZI_CMD_LINE_MAGIC_OFFSET );
 | 
		
	
		
			
			| 193 |  | -		put_real ( cmd_line_offset, rm_kernel_seg,
 | 
		
	
		
			
			| 194 |  | -			   BZI_CMD_LINE_OFFSET_OFFSET );
 | 
		
	
		
			
			| 195 |  | -		bzhdr.setup_move_size = rm_memsz;
 | 
		
	
		
			
			|  | 253 | +		cmdline.magic = BZI_CMDLINE_MAGIC;
 | 
		
	
		
			
			|  | 254 | +		cmdline.offset = load_ctx->rm_cmdline;
 | 
		
	
		
			
			|  | 255 | +		copy_to_user ( load_ctx->rm_kernel, BZI_CMDLINE_OFFSET,
 | 
		
	
		
			
			|  | 256 | +			       &cmdline, sizeof ( cmdline ) );
 | 
		
	
		
			
			|  | 257 | +		bzhdr->setup_move_size = load_ctx->rm_memsz;
 | 
		
	
		
			
			| 196 | 258 |  	}
 | 
		
	
		
			
			| 197 |  | -	copy_to_user ( rm_kernel, BZI_HDR_OFFSET, &bzhdr, sizeof ( bzhdr ) );
 | 
		
	
		
			
			|  | 259 | +	copy_to_user ( load_ctx->rm_kernel, BZI_HDR_OFFSET,
 | 
		
	
		
			
			|  | 260 | +		       bzhdr, sizeof ( *bzhdr ) );
 | 
		
	
		
			
			|  | 261 | +
 | 
		
	
		
			
			|  | 262 | +	return 0;
 | 
		
	
		
			
			|  | 263 | +}
 | 
		
	
		
			
			|  | 264 | +
 | 
		
	
		
			
			|  | 265 | +/**
 | 
		
	
		
			
			|  | 266 | + * Load bzImage image into memory
 | 
		
	
		
			
			|  | 267 | + *
 | 
		
	
		
			
			|  | 268 | + * @v image		bzImage file
 | 
		
	
		
			
			|  | 269 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 270 | + */
 | 
		
	
		
			
			|  | 271 | +int bzimage_load ( struct image *image ) {
 | 
		
	
		
			
			|  | 272 | +	struct bzimage_header bzhdr;
 | 
		
	
		
			
			|  | 273 | +	struct bzimage_load_context load_ctx;
 | 
		
	
		
			
			|  | 274 | +	union {
 | 
		
	
		
			
			|  | 275 | +		struct bzimage_exec_context bz;
 | 
		
	
		
			
			|  | 276 | +		unsigned long ul;
 | 
		
	
		
			
			|  | 277 | +	} exec_ctx;
 | 
		
	
		
			
			|  | 278 | +	const char *cmdline = ( image->cmdline ? image->cmdline : "" );
 | 
		
	
		
			
			|  | 279 | +	int rc;
 | 
		
	
		
			
			|  | 280 | +
 | 
		
	
		
			
			|  | 281 | +	/* Load and verify header */
 | 
		
	
		
			
			|  | 282 | +	if ( ( rc = bzimage_load_header ( image, &load_ctx, &bzhdr ) ) != 0 )
 | 
		
	
		
			
			|  | 283 | +		return rc;
 | 
		
	
		
			
			|  | 284 | +
 | 
		
	
		
			
			|  | 285 | +	/* This is a bzImage image, valid or otherwise */
 | 
		
	
		
			
			|  | 286 | +	if ( ! image->type )
 | 
		
	
		
			
			|  | 287 | +		image->type = &bzimage_image_type;
 | 
		
	
		
			
			|  | 288 | +
 | 
		
	
		
			
			|  | 289 | +	/* Load real-mode portion */
 | 
		
	
		
			
			|  | 290 | +	if ( ( rc = bzimage_load_real ( image, &load_ctx, cmdline ) ) != 0 )
 | 
		
	
		
			
			|  | 291 | +		return rc;
 | 
		
	
		
			
			|  | 292 | +
 | 
		
	
		
			
			|  | 293 | +	/* Load non-real-mode portion */
 | 
		
	
		
			
			|  | 294 | +	if ( ( rc = bzimage_load_non_real ( image, &load_ctx ) ) != 0 )
 | 
		
	
		
			
			|  | 295 | +		return rc;
 | 
		
	
		
			
			|  | 296 | +
 | 
		
	
		
			
			|  | 297 | +	/* Update and write out header */
 | 
		
	
		
			
			|  | 298 | +	if ( ( rc = bzimage_write_header ( image, &load_ctx, &bzhdr ) ) != 0 )
 | 
		
	
		
			
			|  | 299 | +		return rc;
 | 
		
	
		
			
			| 198 | 300 |  
 | 
		
	
		
			
			| 199 | 301 |  	/* Record execution context in image private data field */
 | 
		
	
		
			
			| 200 |  | -	context.rm.kernel_seg = rm_kernel_seg;
 | 
		
	
		
			
			| 201 |  | -	context.rm.stack = rm_heap_end;
 | 
		
	
		
			
			| 202 |  | -	image->priv.ul = context.ul;
 | 
		
	
		
			
			|  | 302 | +	exec_ctx.bz.kernel_seg = load_ctx.rm_kernel_seg;
 | 
		
	
		
			
			|  | 303 | +	exec_ctx.bz.stack = load_ctx.rm_heap;
 | 
		
	
		
			
			|  | 304 | +	image->priv.ul = exec_ctx.ul;
 | 
		
	
		
			
			| 203 | 305 |  
 | 
		
	
		
			
			| 204 | 306 |  	return 0;
 | 
		
	
		
			
			| 205 | 307 |  }
 |