342
371
/* Create cpio header before non-prebuilt images */
343
372
if ( filename && filename[0] ) {
344
size_t name_len = ( strlen ( filename ) + 1 );
346
DBGC ( image, "bzImage %p inserting initrd %p as %s\n",
347
image, initrd, filename );
373
cmdline = strchr ( filename, ' ' );
374
name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) )
375
: strlen ( filename ) ) + 1 /* NUL */ );
348
376
memset ( &cpio, '0', sizeof ( cpio ) );
349
377
memcpy ( cpio.c_magic, CPIO_MAGIC, sizeof ( cpio.c_magic ) );
350
378
cpio_set_field ( cpio.c_mode, 0100644 );
351
379
cpio_set_field ( cpio.c_nlink, 1 );
352
380
cpio_set_field ( cpio.c_filesize, initrd->len );
353
381
cpio_set_field ( cpio.c_namesize, name_len );
383
bzimage_parse_cpio_cmdline ( image, &cpio,
384
( cmdline + 1 /* ' ' */ ));
355
387
copy_to_user ( address, offset, &cpio,
356
388
sizeof ( cpio ) );
358
390
offset += sizeof ( cpio );
392
memset_user ( address, offset, 0, name_len );
360
393
copy_to_user ( address, offset, filename,
394
( name_len - 1 /* NUL (or space) */ ) );
363
396
offset += name_len;
364
397
offset = ( ( offset + 0x03 ) & ~0x03 );
367
400
/* Copy in initrd image body */
369
memcpy_user ( address, offset, initrd->data, 0, initrd->len );
402
memmove_user ( address, offset, initrd->data, 0, initrd->len );
404
DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)"
405
"%s%s\n", image, initrd, user_to_phys ( address, 0 ),
406
user_to_phys ( address, offset ),
407
user_to_phys ( address, ( offset + initrd->len ) ),
408
( filename ? " " : "" ), ( filename ? filename : "" ) );
409
DBGC2_MD5A ( image, user_to_phys ( address, offset ),
410
user_to_virt ( address, offset ), initrd->len );
370
412
offset += initrd->len;
372
DBGC ( image, "bzImage %p has initrd %p at [%lx,%lx)\n",
373
image, initrd, user_to_phys ( address, 0 ),
374
user_to_phys ( address, offset ) );
377
/* Round up to 4-byte boundary */
378
offset = ( ( offset + 0x03 ) & ~0x03 );
414
/* Round up to multiple of INITRD_ALIGN and zero-pad */
415
pad_len = ( ( -offset ) & ( INITRD_ALIGN - 1 ) );
417
memset_user ( address, offset, 0, pad_len );
424
* Check that initrds can be loaded
426
* @v image bzImage image
427
* @v bzimg bzImage context
428
* @ret rc Return status code
430
static int bzimage_check_initrds ( struct image *image,
431
struct bzimage_context *bzimg ) {
432
struct image *initrd;
437
/* Calculate total loaded length of initrds */
438
for_each_image ( initrd ) {
441
if ( initrd == image )
444
/* Calculate length */
445
len += bzimage_load_initrd ( image, initrd, UNULL );
447
DBGC ( image, "bzImage %p initrd %p from [%#08lx,%#08lx)%s%s\n",
448
image, initrd, user_to_phys ( initrd->data, 0 ),
449
user_to_phys ( initrd->data, initrd->len ),
450
( initrd->cmdline ? " " : "" ),
451
( initrd->cmdline ? initrd->cmdline : "" ) );
452
DBGC2_MD5A ( image, user_to_phys ( initrd->data, 0 ),
453
user_to_virt ( initrd->data, 0 ), initrd->len );
456
/* Calculate lowest usable address */
457
bottom = userptr_add ( bzimg->pm_kernel, bzimg->pm_sz );
459
/* Check that total length fits within space available for
460
* reshuffling. This is a conservative check, since CPIO
461
* headers are not present during reshuffling, but this
462
* doesn't hurt and keeps the code simple.
464
if ( ( rc = initrd_reshuffle_check ( len, bottom ) ) != 0 ) {
465
DBGC ( image, "bzImage %p failed reshuffle check: %s\n",
466
image, strerror ( rc ) );
470
/* Check that total length fits within kernel's memory limit */
471
if ( user_to_phys ( bottom, len ) > bzimg->mem_limit ) {
472
DBGC ( image, "bzImage %p not enough space for initrds\n",
383
481
* Load initrds, if any
385
483
* @v image bzImage image
386
484
* @v bzimg bzImage context
387
* @ret rc Return status code
389
static int bzimage_load_initrds ( struct image *image,
390
struct bzimage_context *bzimg ) {
486
static void bzimage_load_initrds ( struct image *image,
487
struct bzimage_context *bzimg ) {
391
488
struct image *initrd;
392
size_t total_len = 0;
396
/* Add up length of all initrd images */
397
for_each_image ( initrd )
398
total_len += bzimage_load_initrd ( image, initrd, UNULL );
400
/* Give up if no initrd images found */
404
/* Find a suitable start address. Try 1MB boundaries,
405
* starting from the downloaded kernel image itself and
406
* working downwards until we hit an available region.
408
for ( address = ( user_to_phys ( image->data, 0 ) & ~0xfffff ) ; ;
409
address -= 0x100000 ) {
410
/* Check that we're not going to overwrite the
411
* kernel itself. This check isn't totally
412
* accurate, but errs on the side of caution.
489
struct image *highest = NULL;
495
/* Reshuffle initrds into desired order */
496
initrd_reshuffle ( userptr_add ( bzimg->pm_kernel, bzimg->pm_sz ) );
498
/* Find highest initrd */
499
for_each_image ( initrd ) {
500
if ( ( highest == NULL ) ||
501
( userptr_sub ( initrd->data, highest->data ) > 0 ) ) {
506
/* Do nothing if there are no initrds */
510
/* Find highest usable address */
511
top = userptr_add ( highest->data,
512
( ( highest->len + INITRD_ALIGN - 1 ) &
513
~( INITRD_ALIGN - 1 ) ) );
514
if ( user_to_phys ( top, 0 ) > bzimg->mem_limit )
515
top = phys_to_user ( bzimg->mem_limit );
516
DBGC ( image, "bzImage %p loading initrds from %#08lx downwards\n",
517
image, user_to_phys ( top, 0 ) );
519
/* Load initrds in order */
520
for_each_image ( initrd ) {
522
/* Calculate cumulative length of following
523
* initrds (including padding).
414
if ( address <= ( BZI_LOAD_HIGH_ADDR + image->len ) ) {
415
DBGC ( image, "bzImage %p could not find a location "
416
"for initrd\n", image );
419
/* Check that we are within the kernel's range */
420
if ( ( address + total_len - 1 ) > bzimg->mem_limit )
422
/* Prepare and verify segment */
423
if ( ( rc = prep_segment ( phys_to_user ( address ), 0,
426
/* Use this address */
430
/* Record initrd location */
431
bzimg->ramdisk_image = address;
432
bzimg->ramdisk_size = total_len;
434
/* Construct initrd */
435
DBGC ( image, "bzImage %p constructing initrd at [%lx,%lx)\n",
436
image, address, ( address + total_len ) );
437
for_each_image ( initrd ) {
438
address += bzimage_load_initrd ( image, initrd,
439
phys_to_user ( address ) );
526
for_each_image ( other ) {
527
if ( other == initrd )
529
len += bzimage_load_initrd ( image, other, UNULL );
532
/* Load initrd at this address */
533
dest = userptr_add ( top, -len );
534
bzimage_load_initrd ( image, initrd, dest );
536
/* Record initrd location */
537
if ( ! bzimg->ramdisk_image ) {
538
bzimg->ramdisk_image = user_to_phys ( dest, 0 );
539
bzimg->ramdisk_size = len;
574
/* Parse command line for bootloader parameters */
575
if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
578
/* Check that initrds can be loaded */
579
if ( ( rc = bzimage_check_initrds ( image, &bzimg ) ) != 0 )
582
/* Remove kernel from image list (without invalidating image pointer) */
583
unregister_image ( image_get ( image ) );
475
585
/* Load segments */
476
586
memcpy_user ( bzimg.rm_kernel, 0, image->data,
477
587
0, bzimg.rm_filesz );
478
588
memcpy_user ( bzimg.pm_kernel, 0, image->data,
479
589
bzimg.rm_filesz, bzimg.pm_sz );
481
/* Update and write out header */
482
bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
484
/* Parse command line for bootloader parameters */
485
if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
488
591
/* Store command line */
489
if ( ( rc = bzimage_set_cmdline ( image, &bzimg, cmdline ) ) != 0 )
592
bzimage_set_cmdline ( image, &bzimg, cmdline );
594
/* Prepare for exiting. Must do this before loading initrds,
595
* since loading the initrds will corrupt the external heap.
492
599
/* Load any initrds */
493
if ( ( rc = bzimage_load_initrds ( image, &bzimg ) ) != 0 )
600
bzimage_load_initrds ( image, &bzimg );
496
602
/* Update kernel header */
497
603
bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
499
/* Prepare for exiting */
502
605
DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 "
503
606
"(stack %04x:%04zx)\n", image, ( bzimg.rm_kernel_seg + 0x20 ),
504
607
bzimg.rm_kernel_seg, bzimg.rm_heap );