diff --git a/ChangeLog b/ChangeLog index 8fba56c05..d60acab3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2013-12-05 Vladimir Serbinenko + + Handle unaligned .bss on sparc64. + + Current code improperly assumes that both __bss_start and _end are + aligned to 8-bytes. Eliminating this assumption and explicitly align + modules. + 2013-12-04 Vladimir Serbinenko * grub-core/boot/sparc64/ieee1275/boot.S [CDBOOT]: Move scratchpad diff --git a/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S index 9d91fba48..79b6bb325 100644 --- a/grub-core/kern/sparc64/ieee1275/crt0.S +++ b/grub-core/kern/sparc64/ieee1275/crt0.S @@ -36,10 +36,14 @@ codestart: /* Copy the modules past the end of the kernel image. * They are currently sitting in the BSS. */ - sethi %hi(__bss_start), %o2 - or %o2, %lo(__bss_start), %o2 - sethi %hi(_end), %o3 - or %o3, %lo(_end), %o3 + sethi %hi(__bss_start + GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN - 1), %o2 + or %o2, %lo(__bss_start + GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN - 1), %o2 + srl %o2, GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN, %o2 + sll %o2, GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN, %o2 + sethi %hi(_end + GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN - 1), %o3 + or %o3, %lo(_end + GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN - 1), %o3 + srl %o3, GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN, %o3 + sll %o3, GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN, %o3 sethi %hi(grub_total_module_size), %o4 lduw [%o4 + %lo(grub_total_module_size)], %o4 @@ -67,16 +71,34 @@ codestart: /* Now it's safe to clear out the BSS. */ sethi %hi(__bss_start), %o2 or %o2, %lo(__bss_start), %o2 - sethi %hi(_end), %o3 - or %o3, %lo(_end), %o3 +1: stb %g0, [%o2] + add %o2, 1, %o2 + and %o2, 7, %o3 + brnz %o3, 1b + nop + + sethi %hi(_end - 1), %o3 + or %o3, %lo(_end - 1), %o3 + srl %o3, 3, %o3 + sll %o3, 3, %o3 1: stx %g0, [%o2] add %o2, 8, %o2 cmp %o2, %o3 blt,pt %xcc, 1b nop + + sethi %hi(_end), %o3 + or %o3, %lo(_end), %o3 +1: stb %g0, [%o2] + add %o2, 1, %o2 + cmp %o2, %o3 + blt,pt %xcc, 1b + nop + sethi %hi(grub_ieee1275_original_stack), %o2 stx %o1, [%o2 + %lo(grub_ieee1275_original_stack)] sethi %hi(grub_ieee1275_entry_fn), %o2 call grub_main stx %o0, [%o2 + %lo(grub_ieee1275_entry_fn)] 1: ba,a 1b + nop diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 0a7b89a6d..a666e898b 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -111,7 +111,8 @@ #define GRUB_KERNEL_ARM_UBOOT_MOD_GAP 0x0 #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000 -#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN 0x1 +#define GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN 3 +#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN (1 << GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN) #define GRUB_KERNEL_MIPS_LOONGSON_MOD_ALIGN 0x1 #define GRUB_KERNEL_MIPS_ARC_MOD_ALIGN 0x1 diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 5240fe2aa..7d2f0412d 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -1356,6 +1356,11 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size, else *bss_size = 0; + if (image_target->id == IMAGE_SPARC64_AOUT + || image_target->id == IMAGE_SPARC64_RAW + || image_target->id == IMAGE_SPARC64_CDCORE) + *kernel_sz = ALIGN_UP (*kernel_sz, image_target->mod_align); + if (image_target->id == IMAGE_EFI) { symtab_section = NULL; diff --git a/util/mkimage.c b/util/mkimage.c index 9b482712c..11d4a474b 100644 --- a/util/mkimage.c +++ b/util/mkimage.c @@ -383,7 +383,8 @@ static const struct grub_install_image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR + .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR, + .mod_align = GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN, }, { .dirname = "sparc64-ieee1275", @@ -398,7 +399,8 @@ static const struct grub_install_image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR + .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR, + .mod_align = GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN, }, { .dirname = "sparc64-ieee1275", @@ -413,7 +415,8 @@ static const struct grub_install_image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR + .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR, + .mod_align = GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN, }, { .dirname = "ia64-efi",