Skip to content

Commit c825a9b

Browse files
committedJun 5, 2013
[bzimage] Align initrd images to page boundary
Some versions of Linux apparently complain if initrds are not aligned to a page boundary. Fix by changing INITRD_ALIGN from 4 bytes to 4096 bytes. The amount of padding at the end of each initrd will now often be sufficient to allow the cpio header to be prepended without crossing an alignment boundary. The final location of the initrd may therefore end up being slightly higher than the post-shuffle location. bzimage_load_initrd() must therefore now copy the initrd body prior to copying the cpio header, otherwise the start of the initrd body may be overwritten by the cpio header. (Note that the guarantee that an initrd will never need to overwrite an initrd at a higher location still holds, since the overall length of each initrd cannot decrease as a result of adding a cpio header.) Reported-by: Dave Hansen <dave@sr71.net> Signed-off-by: Michael Brown <mcb30@ipxe.org>
1 parent 0036fdd commit c825a9b

File tree

2 files changed

+16
-19
lines changed

2 files changed

+16
-19
lines changed
 

‎src/arch/i386/image/bzimage.c

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -360,15 +360,15 @@ static size_t bzimage_load_initrd ( struct image *image,
360360
char *filename = initrd->cmdline;
361361
char *cmdline;
362362
struct cpio_header cpio;
363-
size_t offset = 0;
363+
size_t offset;
364364
size_t name_len;
365365
size_t pad_len;
366366

367367
/* Do not include kernel image itself as an initrd */
368368
if ( initrd == image )
369369
return 0;
370370

371-
/* Create cpio header before non-prebuilt images */
371+
/* Create cpio header for non-prebuilt images */
372372
if ( filename && filename[0] ) {
373373
cmdline = strchr ( filename, ' ' );
374374
name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) )
@@ -383,24 +383,20 @@ static size_t bzimage_load_initrd ( struct image *image,
383383
bzimage_parse_cpio_cmdline ( image, &cpio,
384384
( cmdline + 1 /* ' ' */ ));
385385
}
386-
if ( address ) {
387-
copy_to_user ( address, offset, &cpio,
388-
sizeof ( cpio ) );
389-
}
390-
offset += sizeof ( cpio );
391-
if ( address ) {
392-
memset_user ( address, offset, 0, name_len );
393-
copy_to_user ( address, offset, filename,
394-
( name_len - 1 /* NUL (or space) */ ) );
395-
}
396-
offset += name_len;
397-
offset = ( ( offset + 0x03 ) & ~0x03 );
386+
offset = ( ( sizeof ( cpio ) + name_len + 0x03 ) & ~0x03 );
387+
} else {
388+
offset = 0;
398389
}
399390

400-
/* Copy in initrd image body */
401-
if ( address )
402-
memmove_user ( address, offset, initrd->data, 0, initrd->len );
391+
/* Copy in initrd image body (and cpio header if applicable) */
403392
if ( address ) {
393+
memmove_user ( address, offset, initrd->data, 0, initrd->len );
394+
if ( offset ) {
395+
memset_user ( address, 0, 0, offset );
396+
copy_to_user ( address, 0, &cpio, sizeof ( cpio ) );
397+
copy_to_user ( address, sizeof ( cpio ), filename,
398+
( name_len - 1 /* NUL (or space) */ ) );
399+
}
404400
DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)"
405401
"%s%s\n", image, initrd, user_to_phys ( address, 0 ),
406402
user_to_phys ( address, offset ),

‎src/arch/i386/include/initrd.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
1313

1414
/** Minimum alignment for initrds
1515
*
16-
* Chosen to maximise memcpy() speeds
16+
* Some versions of Linux complain about initrds that are not
17+
* page-aligned.
1718
*/
18-
#define INITRD_ALIGN 4
19+
#define INITRD_ALIGN 4096
1920

2021
/** Minimum free space required to reshuffle initrds
2122
*

0 commit comments

Comments
 (0)
Please sign in to comment.