|  | @@ -143,7 +143,7 @@ static void multiboot_build_memmap ( struct image *image,
 | 
		
	
		
			
			| 143 | 143 |   * @v image		Image
 | 
		
	
		
			
			| 144 | 144 |   * @ret physaddr	Physical address of command line
 | 
		
	
		
			
			| 145 | 145 |   */
 | 
		
	
		
			
			| 146 |  | -physaddr_t multiboot_add_cmdline ( struct image *image ) {
 | 
		
	
		
			
			|  | 146 | +static physaddr_t multiboot_add_cmdline ( struct image *image ) {
 | 
		
	
		
			
			| 147 | 147 |  	char *mb_cmdline = ( mb_cmdlines + mb_cmdline_offset );
 | 
		
	
		
			
			| 148 | 148 |  	size_t remaining = ( sizeof ( mb_cmdlines ) - mb_cmdline_offset );
 | 
		
	
		
			
			| 149 | 149 |  	char *buf = mb_cmdline;
 | 
		
	
	
		
			
			|  | @@ -174,28 +174,26 @@ physaddr_t multiboot_add_cmdline ( struct image *image ) {
 | 
		
	
		
			
			| 174 | 174 |  }
 | 
		
	
		
			
			| 175 | 175 |  
 | 
		
	
		
			
			| 176 | 176 |  /**
 | 
		
	
		
			
			| 177 |  | - * Build multiboot module list
 | 
		
	
		
			
			|  | 177 | + * Add multiboot modules
 | 
		
	
		
			
			| 178 | 178 |   *
 | 
		
	
		
			
			| 179 | 179 |   * @v image		Multiboot image
 | 
		
	
		
			
			| 180 |  | - * @v modules		Module list to fill, or NULL
 | 
		
	
		
			
			| 181 |  | - * @ret count		Number of modules
 | 
		
	
		
			
			|  | 180 | + * @v start		Start address for modules
 | 
		
	
		
			
			|  | 181 | + * @v mbinfo		Multiboot information structure
 | 
		
	
		
			
			|  | 182 | + * @v modules		Multiboot module list
 | 
		
	
		
			
			|  | 183 | + * @ret rc		Return status code
 | 
		
	
		
			
			| 182 | 184 |   */
 | 
		
	
		
			
			| 183 |  | -static unsigned int
 | 
		
	
		
			
			| 184 |  | -multiboot_build_module_list ( struct image *image,
 | 
		
	
		
			
			| 185 |  | -			      struct multiboot_module *modules,
 | 
		
	
		
			
			| 186 |  | -			      unsigned int limit ) {
 | 
		
	
		
			
			|  | 185 | +static int multiboot_add_modules ( struct image *image, physaddr_t start,
 | 
		
	
		
			
			|  | 186 | +				   struct multiboot_info *mbinfo,
 | 
		
	
		
			
			|  | 187 | +				   struct multiboot_module *modules,
 | 
		
	
		
			
			|  | 188 | +				   unsigned int limit ) {
 | 
		
	
		
			
			| 187 | 189 |  	struct image *module_image;
 | 
		
	
		
			
			| 188 | 190 |  	struct multiboot_module *module;
 | 
		
	
		
			
			| 189 |  | -	unsigned int count = 0;
 | 
		
	
		
			
			| 190 |  | -	unsigned int insert;
 | 
		
	
		
			
			| 191 |  | -	physaddr_t start;
 | 
		
	
		
			
			| 192 |  | -	physaddr_t end;
 | 
		
	
		
			
			| 193 |  | -	unsigned int i;
 | 
		
	
		
			
			|  | 191 | +	int rc;
 | 
		
	
		
			
			| 194 | 192 |  
 | 
		
	
		
			
			| 195 | 193 |  	/* Add each image as a multiboot module */
 | 
		
	
		
			
			| 196 | 194 |  	for_each_image ( module_image ) {
 | 
		
	
		
			
			| 197 | 195 |  
 | 
		
	
		
			
			| 198 |  | -		if ( count >= limit ) {
 | 
		
	
		
			
			|  | 196 | +		if ( mbinfo->mods_count >= limit ) {
 | 
		
	
		
			
			| 199 | 197 |  			DBGC ( image, "MULTIBOOT %p limit of %d modules "
 | 
		
	
		
			
			| 200 | 198 |  			       "reached\n", image, limit );
 | 
		
	
		
			
			| 201 | 199 |  			break;
 | 
		
	
	
		
			
			|  | @@ -205,37 +203,36 @@ multiboot_build_module_list ( struct image *image,
 | 
		
	
		
			
			| 205 | 203 |  		if ( module_image == image )
 | 
		
	
		
			
			| 206 | 204 |  			continue;
 | 
		
	
		
			
			| 207 | 205 |  
 | 
		
	
		
			
			| 208 |  | -		/* At least some OSes expect the multiboot modules to
 | 
		
	
		
			
			| 209 |  | -		 * be in ascending order, so we have to support it.
 | 
		
	
		
			
			| 210 |  | -		 */
 | 
		
	
		
			
			| 211 |  | -		start = user_to_phys ( module_image->data, 0 );
 | 
		
	
		
			
			| 212 |  | -		end = user_to_phys ( module_image->data, module_image->len );
 | 
		
	
		
			
			| 213 |  | -		for ( insert = 0 ; insert < count ; insert++ ) {
 | 
		
	
		
			
			| 214 |  | -			if ( start < modules[insert].mod_start )
 | 
		
	
		
			
			| 215 |  | -				break;
 | 
		
	
		
			
			|  | 206 | +		/* Page-align the module */
 | 
		
	
		
			
			|  | 207 | +		start = ( ( start + 0xfff ) & ~0xfff );
 | 
		
	
		
			
			|  | 208 | +
 | 
		
	
		
			
			|  | 209 | +		/* Prepare segment */
 | 
		
	
		
			
			|  | 210 | +		if ( ( rc = prep_segment ( phys_to_user ( start ),
 | 
		
	
		
			
			|  | 211 | +					   module_image->len,
 | 
		
	
		
			
			|  | 212 | +					   module_image->len ) ) != 0 ) {
 | 
		
	
		
			
			|  | 213 | +			DBGC ( image, "MULTIBOOT %p could not prepare module "
 | 
		
	
		
			
			|  | 214 | +			       "%s: %s\n", image, module_image->name,
 | 
		
	
		
			
			|  | 215 | +			       strerror ( rc ) );
 | 
		
	
		
			
			|  | 216 | +			return rc;
 | 
		
	
		
			
			| 216 | 217 |  		}
 | 
		
	
		
			
			| 217 |  | -		module = &modules[insert];
 | 
		
	
		
			
			| 218 |  | -		memmove ( ( module + 1 ), module,
 | 
		
	
		
			
			| 219 |  | -			  ( ( count - insert ) * sizeof ( *module ) ) );
 | 
		
	
		
			
			|  | 218 | +
 | 
		
	
		
			
			|  | 219 | +		/* Copy module */
 | 
		
	
		
			
			|  | 220 | +		memcpy_user ( phys_to_user ( start ), 0,
 | 
		
	
		
			
			|  | 221 | +			      module_image->data, 0, module_image->len );
 | 
		
	
		
			
			|  | 222 | +
 | 
		
	
		
			
			|  | 223 | +		/* Add module to list */
 | 
		
	
		
			
			|  | 224 | +		module = &modules[mbinfo->mods_count++];
 | 
		
	
		
			
			| 220 | 225 |  		module->mod_start = start;
 | 
		
	
		
			
			| 221 |  | -		module->mod_end = end;
 | 
		
	
		
			
			|  | 226 | +		module->mod_end = ( start + module_image->len );
 | 
		
	
		
			
			| 222 | 227 |  		module->string = multiboot_add_cmdline ( module_image );
 | 
		
	
		
			
			| 223 | 228 |  		module->reserved = 0;
 | 
		
	
		
			
			| 224 |  | -		
 | 
		
	
		
			
			| 225 |  | -		/* We promise to page-align modules */
 | 
		
	
		
			
			| 226 |  | -		assert ( ( module->mod_start & 0xfff ) == 0 );
 | 
		
	
		
			
			| 227 |  | -
 | 
		
	
		
			
			| 228 |  | -		count++;
 | 
		
	
		
			
			| 229 |  | -	}
 | 
		
	
		
			
			| 230 |  | -
 | 
		
	
		
			
			| 231 |  | -	/* Dump module configuration */
 | 
		
	
		
			
			| 232 |  | -	for ( i = 0 ; i < count ; i++ ) {
 | 
		
	
		
			
			| 233 |  | -		DBGC ( image, "MULTIBOOT %p module %d is [%x,%x)\n",
 | 
		
	
		
			
			| 234 |  | -		       image, i, modules[i].mod_start,
 | 
		
	
		
			
			| 235 |  | -		       modules[i].mod_end );
 | 
		
	
		
			
			|  | 229 | +		DBGC ( image, "MULTIBOOT %p module %s is [%x,%x)\n",
 | 
		
	
		
			
			|  | 230 | +		       image, module_image->name, module->mod_start,
 | 
		
	
		
			
			|  | 231 | +		       module->mod_end );
 | 
		
	
		
			
			|  | 232 | +		start += module_image->len;
 | 
		
	
		
			
			| 236 | 233 |  	}
 | 
		
	
		
			
			| 237 | 234 |  
 | 
		
	
		
			
			| 238 |  | -	return count;
 | 
		
	
		
			
			|  | 235 | +	return 0;
 | 
		
	
		
			
			| 239 | 236 |  }
 | 
		
	
		
			
			| 240 | 237 |  
 | 
		
	
		
			
			| 241 | 238 |  /**
 | 
		
	
	
		
			
			|  | @@ -314,11 +311,12 @@ static int multiboot_find_header ( struct image *image,
 | 
		
	
		
			
			| 314 | 311 |   * @v image		Multiboot file
 | 
		
	
		
			
			| 315 | 312 |   * @v hdr		Multiboot header descriptor
 | 
		
	
		
			
			| 316 | 313 |   * @ret entry		Entry point
 | 
		
	
		
			
			|  | 314 | + * @ret max		Maximum used address
 | 
		
	
		
			
			| 317 | 315 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 318 | 316 |   */
 | 
		
	
		
			
			| 319 | 317 |  static int multiboot_load_raw ( struct image *image,
 | 
		
	
		
			
			| 320 | 318 |  				struct multiboot_header_info *hdr,
 | 
		
	
		
			
			| 321 |  | -				physaddr_t *entry ) {
 | 
		
	
		
			
			|  | 319 | +				physaddr_t *entry, physaddr_t *max ) {
 | 
		
	
		
			
			| 322 | 320 |  	size_t offset;
 | 
		
	
		
			
			| 323 | 321 |  	size_t filesz;
 | 
		
	
		
			
			| 324 | 322 |  	size_t memsz;
 | 
		
	
	
		
			
			|  | @@ -349,8 +347,9 @@ static int multiboot_load_raw ( struct image *image,
 | 
		
	
		
			
			| 349 | 347 |  	/* Copy image to segment */
 | 
		
	
		
			
			| 350 | 348 |  	memcpy_user ( buffer, 0, image->data, offset, filesz );
 | 
		
	
		
			
			| 351 | 349 |  
 | 
		
	
		
			
			| 352 |  | -	/* Record execution entry point */
 | 
		
	
		
			
			|  | 350 | +	/* Record execution entry point and maximum used address */
 | 
		
	
		
			
			| 353 | 351 |  	*entry = hdr->mb.entry_addr;
 | 
		
	
		
			
			|  | 352 | +	*max = ( hdr->mb.load_addr + memsz );
 | 
		
	
		
			
			| 354 | 353 |  
 | 
		
	
		
			
			| 355 | 354 |  	return 0;
 | 
		
	
		
			
			| 356 | 355 |  }
 | 
		
	
	
		
			
			|  | @@ -360,13 +359,15 @@ static int multiboot_load_raw ( struct image *image,
 | 
		
	
		
			
			| 360 | 359 |   *
 | 
		
	
		
			
			| 361 | 360 |   * @v image		Multiboot file
 | 
		
	
		
			
			| 362 | 361 |   * @ret entry		Entry point
 | 
		
	
		
			
			|  | 362 | + * @ret max		Maximum used address
 | 
		
	
		
			
			| 363 | 363 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 364 | 364 |   */
 | 
		
	
		
			
			| 365 |  | -static int multiboot_load_elf ( struct image *image, physaddr_t *entry ) {
 | 
		
	
		
			
			|  | 365 | +static int multiboot_load_elf ( struct image *image, physaddr_t *entry,
 | 
		
	
		
			
			|  | 366 | +				physaddr_t *max ) {
 | 
		
	
		
			
			| 366 | 367 |  	int rc;
 | 
		
	
		
			
			| 367 | 368 |  
 | 
		
	
		
			
			| 368 | 369 |  	/* Load ELF image*/
 | 
		
	
		
			
			| 369 |  | -	if ( ( rc = elf_load ( image, entry ) ) != 0 ) {
 | 
		
	
		
			
			|  | 370 | +	if ( ( rc = elf_load ( image, entry, max ) ) != 0 ) {
 | 
		
	
		
			
			| 370 | 371 |  		DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n",
 | 
		
	
		
			
			| 371 | 372 |  		       image, strerror ( rc ) );
 | 
		
	
		
			
			| 372 | 373 |  		return rc;
 | 
		
	
	
		
			
			|  | @@ -384,6 +385,7 @@ static int multiboot_load_elf ( struct image *image, physaddr_t *entry ) {
 | 
		
	
		
			
			| 384 | 385 |  static int multiboot_exec ( struct image *image ) {
 | 
		
	
		
			
			| 385 | 386 |  	struct multiboot_header_info hdr;
 | 
		
	
		
			
			| 386 | 387 |  	physaddr_t entry;
 | 
		
	
		
			
			|  | 388 | +	physaddr_t max;
 | 
		
	
		
			
			| 387 | 389 |  	int rc;
 | 
		
	
		
			
			| 388 | 390 |  
 | 
		
	
		
			
			| 389 | 391 |  	/* Locate multiboot header, if present */
 | 
		
	
	
		
			
			|  | @@ -405,8 +407,8 @@ static int multiboot_exec ( struct image *image ) {
 | 
		
	
		
			
			| 405 | 407 |  	 * the ELF header if present, and Solaris relies on this
 | 
		
	
		
			
			| 406 | 408 |  	 * behaviour.
 | 
		
	
		
			
			| 407 | 409 |  	 */
 | 
		
	
		
			
			| 408 |  | -	if ( ( ( rc = multiboot_load_elf ( image, &entry ) ) != 0 ) &&
 | 
		
	
		
			
			| 409 |  | -	     ( ( rc = multiboot_load_raw ( image, &hdr, &entry ) ) != 0 ) )
 | 
		
	
		
			
			|  | 410 | +	if ( ( ( rc = multiboot_load_elf ( image, &entry, &max ) ) != 0 ) &&
 | 
		
	
		
			
			|  | 411 | +	     ( ( rc = multiboot_load_raw ( image, &hdr, &entry, &max ) ) != 0 ))
 | 
		
	
		
			
			| 410 | 412 |  		return rc;
 | 
		
	
		
			
			| 411 | 413 |  
 | 
		
	
		
			
			| 412 | 414 |  	/* Populate multiboot information structure */
 | 
		
	
	
		
			
			|  | @@ -415,11 +417,13 @@ static int multiboot_exec ( struct image *image ) {
 | 
		
	
		
			
			| 415 | 417 |  			 MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
 | 
		
	
		
			
			| 416 | 418 |  	mb_cmdline_offset = 0;
 | 
		
	
		
			
			| 417 | 419 |  	mbinfo.cmdline = multiboot_add_cmdline ( image );
 | 
		
	
		
			
			| 418 |  | -	mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules,
 | 
		
	
		
			
			| 419 |  | -				( sizeof(mbmodules) / sizeof(mbmodules[0]) ) );
 | 
		
	
		
			
			| 420 | 420 |  	mbinfo.mods_addr = virt_to_phys ( mbmodules );
 | 
		
	
		
			
			| 421 | 421 |  	mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
 | 
		
	
		
			
			| 422 | 422 |  	mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
 | 
		
	
		
			
			|  | 423 | +	if ( ( rc = multiboot_add_modules ( image, max, &mbinfo, mbmodules,
 | 
		
	
		
			
			|  | 424 | +					    ( sizeof ( mbmodules ) /
 | 
		
	
		
			
			|  | 425 | +					      sizeof ( mbmodules[0] ) ) ) ) !=0)
 | 
		
	
		
			
			|  | 426 | +		return rc;
 | 
		
	
		
			
			| 423 | 427 |  
 | 
		
	
		
			
			| 424 | 428 |  	/* Multiboot images may not return and have no callback
 | 
		
	
		
			
			| 425 | 429 |  	 * interface, so shut everything down prior to booting the OS.
 |