From 3197c86ba826bd114f44cc09bb380b4be398ed73 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Sep 2010 10:07:12 +0200 Subject: [PATCH 1/9] Remove dead code in decompressor --- grub-core/kern/i386/pc/lzma_decode.S | 63 ---------------------------- 1 file changed, 63 deletions(-) diff --git a/grub-core/kern/i386/pc/lzma_decode.S b/grub-core/kern/i386/pc/lzma_decode.S index a5a86848a..88c668d5e 100644 --- a/grub-core/kern/i386/pc/lzma_decode.S +++ b/grub-core/kern/i386/pc/lzma_decode.S @@ -77,69 +77,6 @@ #define RepLenCoder (LenCoder + kNumLenProbs) #define Literal (RepLenCoder + kNumLenProbs) - -#if 0 - -DbgOut: - pushf - pushl %ebp - pushl %edi - pushl %esi - pushl %edx - pushl %ecx - pushl %ebx - pushl %eax - - call _DebugPrint - - popl %eax - popl %ebx - popl %ecx - popl %edx - popl %esi - popl %edi - popl %ebp - popf - - ret - - -/* - * int LzmaDecodeProperties(CLzmaProperties *propsRes, - * const unsigned char *propsData, - * int size); - */ - -_LzmaDecodePropertiesA: - movb (%edx), %dl - - xorl %ecx, %ecx -1: - cmpb $45, %dl - jb 2f - incl %ecx - subb $45, %dl - jmp 1b -2: - movl %ecx, 8(%eax) /* pb */ - xorl %ecx, %ecx -1: - cmpb $9, %dl - jb 2f - incl %ecx - subb $9, %dl -2: - movl %ecx, 4(%eax) /* lp */ - movb %dl, %cl - movl %ecx, (%eax) /* lc */ - -#endif - -#ifndef ASM_FILE - xorl %eax, %eax -#endif - ret - #define out_size 8(%ebp) #define now_pos -4(%ebp) From c5b4cd370ee3342d226cd0f4193f2c560f855b2d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Sep 2010 10:14:08 +0200 Subject: [PATCH 2/9] asm part for mips decompressor --- grub-core/Makefile.core.def | 13 ++ grub-core/boot/mips/startup_raw.S | 186 +++++++++++++++++++++++++++++ grub-core/kern/mips/cache.S | 3 + grub-core/kern/mips/cache_flush.S | 4 +- grub-core/kern/mips/startup.S | 148 ++++------------------- grub-core/lib/mips/relocator_asm.S | 7 +- include/grub/offsets.h | 12 +- util/grub-mkimage.c | 51 ++++++-- 8 files changed, 278 insertions(+), 146 deletions(-) create mode 100644 grub-core/boot/mips/startup_raw.S diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 2fca91430..3341cb678 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -275,6 +275,19 @@ image = { enable = i386_pc; }; +image = { + name = decompress; + mips = boot/mips/startup_raw.S; + common = lib/LzmaDec.c; + + mips_cppflags = '-DGRUB_MACHINE_LINK_ADDR=0x80200000'; + + objcopyflags = '-O binary'; + ldflags = '-lgcc -static-libgcc -Wl,-Ttext,0x80100000'; + cflags = '-static-libgcc'; + enable = mips; +}; + image = { name = fwstart; mips_yeeloong = boot/mips/yeeloong/fwstart.S; diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S new file mode 100644 index 000000000..67dc2ec03 --- /dev/null +++ b/grub-core/boot/mips/startup_raw.S @@ -0,0 +1,186 @@ +/* startup.S - Startup code for the MIPS. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +#define BASE_ADDR 8 + +.extern __bss_start +.extern _end + + .globl __start, _start, start + .set noreorder + .set nomacro +__start: +_start: +start: + + bal codestart + nop +base: + . = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE +compressed_size: + .long 0 + . = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE +uncompressed_size: + .long 0 +codestart: + /* Save our base. */ + move $s0, $ra + + /* Parse arguments. Has to be done before relocation. + So need to do it in asm. */ +#if 0 // def GRUB_MACHINE_MIPS_YEELOONG + move $s2, $zero + move $s3, $zero + move $s4, $zero + move $s5, $zero + + /* $a2 has the environment. */ + addiu $t0, $a2, 1 + beq $t0, $zero, argdone + nop + move $t0, $a2 +argcont: + lw $t1, 0($t0) + beq $t1, $zero, argdone + nop +#define DO_PARSE(str, reg) \ + addiu $t2, $s0, (str-base);\ + bal parsestr;\ + beq $v0, $zero, 1f;\ + nop ;\ + b 2f;\ + move reg, $v0; +1: + DO_PARSE (busclockstr, $s2) + DO_PARSE (cpuclockstr, $s3) + DO_PARSE (memsizestr, $s4) + DO_PARSE (highmemsizestr, $s5) +2: + b argcont + addiu $t0, $t0, 4 +parsestr: + move $v0, $zero + move $t3, $t1 +3: + lb $t4, 0($t2) + lb $t5, 0($t3) + addiu $t2, $t2, 1 + addiu $t3, $t3, 1 + beq $t5, $zero, 1f + nop + beq $t5, $t4, 3b + nop + bne $t4, $zero, 1f + nop + + addiu $t3, $t3, 0xffff +digcont: + lb $t5, 0($t3) + /* Substract '0' from digit. */ + addiu $t5, $t5, 0xffd0 + bltz $t5, 1f + nop + addiu $t4, $t5, 0xfff7 + bgtz $t4, 1f + nop + /* Multiply $v0 by 10 with bitshifts. */ + sll $v0, $v0, 1 + sll $t4, $v0, 2 + addu $v0, $v0, $t4 + addu $v0, $v0, $t5 + addiu $t3, $t3, 1 + b digcont + nop +1: + jr $ra + nop +busclockstr: .asciiz "busclock=" +cpuclockstr: .asciiz "cpuclock=" +memsizestr: .asciiz "memsize=" +highmemsizestr: .asciiz "highmemsize=" + .p2align 2 +argdone: +#endif + /* Copy the decompressor. */ + lui $t1, %hi(base) + addiu $t1, $t1, %lo(base) + lui $t3, %hi(__bss_start) + addiu $t3, $t3, %lo(__bss_start) + move $t2, $s0 + +1: + beq $t1, $t3, 2f + lb $t4, 0($t2) + sb $t4, 0($t1) + addiu $t1, $t1, 1 + b 1b + addiu $t2, $t2, 1 +2: + /* Clean out its BSS. */ + lui $t1, %hi(__bss_start) + addiu $t1, $t1, %lo(__bss_start) + lui $t2, %hi(_end) + addiu $t2, $t2, %lo(_end) +1: + beq $t1, $t2, 2f + nop + sb $zero, 0($t1) + b 1b + addiu $t1, $t1, 1 +2: + + /* Decompress the payload. */ + lui $a0, %hi(__bss_start) + addiu $a0, $a0, %lo(__bss_start) + lui $t0, %hi(base) + addiu $t0, $t0, %lo(base) + subu $a0, $a0, $t0 + addu $a0, $a0, $s0 + + lui $a1, %hi(GRUB_MACHINE_LINK_ADDR) + addiu $a1, %lo(GRUB_MACHINE_LINK_ADDR) + lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0) + lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0) + move $s1, $a1 + + /* $a0 contains source compressed address, $a1 is destination, + $a2 is compressed size, $a3 is uncompressed size. + */ + move $s6, $a3 + + lui $sp, %hi(_start) + + bal EXT_C(grub_decompress_core) + addiu $sp, $sp, %lo(_start) + + move $a0, $s1 + move $a1, $s6 + +#include "../../kern/mips/cache_flush.S" + + lui $t1, %hi(GRUB_MACHINE_LINK_ADDR) + addiu $t1, %lo(GRUB_MACHINE_LINK_ADDR) + + jr $t1 + nop diff --git a/grub-core/kern/mips/cache.S b/grub-core/kern/mips/cache.S index 2c35b6da2..02dc3355f 100644 --- a/grub-core/kern/mips/cache.S +++ b/grub-core/kern/mips/cache.S @@ -1,6 +1,9 @@ #include + .set nomacro + .set noreorder + FUNCTION (grub_cpu_flush_cache) FUNCTION (grub_arch_sync_caches) #include "cache_flush.S" diff --git a/grub-core/kern/mips/cache_flush.S b/grub-core/kern/mips/cache_flush.S index 5667ee7b4..11096c035 100644 --- a/grub-core/kern/mips/cache_flush.S +++ b/grub-core/kern/mips/cache_flush.S @@ -9,15 +9,15 @@ subu $t1, $t3, $t2 1: cache 1, 0($t0) - addiu $t0, $t0, 0x1 addiu $t1, $t1, 0xffff bne $t1, $zero, 1b + addiu $t0, $t0, 0x1 sync move $t0, $t2 subu $t1, $t3, $t2 2: cache 0, 0($t0) - addiu $t0, $t0, 0x1 addiu $t1, $t1, 0xffff bne $t1, $zero, 2b + addiu $t0, $t0, 0x1 sync diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 6811353ea..1b27a5b1f 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -22,128 +22,19 @@ #include #include -#define BASE_ADDR 8 - -.extern __bss_start -.extern _end - +#define BASE_ADDR 8 + .globl __start, _start, start + .set noreorder + .set nomacro __start: _start: -start: - bal codestart -base: - . = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE -compressed_size: - .long 0 - . = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE -total_module_size: - .long 0 - . = _start + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE -kernel_image_size: - .long 0 -codestart: - /* Save our base. */ - move $s0, $ra +start: +.extern __bss_start +.extern _end + bal cont + nop - /* Parse arguments. Has to be done before relocation. - So need to do it in asm. */ -#ifdef GRUB_MACHINE_MIPS_YEELOONG - move $s2, $zero - move $s3, $zero - move $s4, $zero - move $s5, $zero - - /* $a2 has the environment. */ - addiu $t0, $a2, 1 - beq $t0, $zero, argdone - move $t0, $a2 -argcont: - lw $t1, 0($t0) - beq $t1, $zero, argdone -#define DO_PARSE(str, reg) \ - addiu $t2, $s0, (str-base);\ - bal parsestr;\ - beq $v0, $zero, 1f;\ - move reg, $v0;\ - b 2f;\ -1: - DO_PARSE (busclockstr, $s2) - DO_PARSE (cpuclockstr, $s3) - DO_PARSE (memsizestr, $s4) - DO_PARSE (highmemsizestr, $s5) -2: - addiu $t0, $t0, 4 - b argcont -parsestr: - move $v0, $zero - move $t3, $t1 -3: - lb $t4, 0($t2) - lb $t5, 0($t3) - addiu $t2, $t2, 1 - addiu $t3, $t3, 1 - beq $t5, $zero, 1f - beq $t5, $t4, 3b - bne $t4, $zero, 1f - - addiu $t3, $t3, 0xffff -digcont: - lb $t5, 0($t3) - /* Substract '0' from digit. */ - addiu $t5, $t5, 0xffd0 - bltz $t5, 1f - addiu $t4, $t5, 0xfff7 - bgtz $t4, 1f - /* Multiply $v0 by 10 with bitshifts. */ - sll $v0, $v0, 1 - sll $t4, $v0, 2 - addu $v0, $v0, $t4 - addu $v0, $v0, $t5 - addiu $t3, $t3, 1 - b digcont -1: - jr $ra -busclockstr: .asciiz "busclock=" -cpuclockstr: .asciiz "cpuclock=" -memsizestr: .asciiz "memsize=" -highmemsizestr: .asciiz "highmemsize=" - .p2align 2 -argdone: -#endif - - /* Decompress the payload. */ - addiu $a0, $s0, GRUB_KERNEL_MACHINE_RAW_SIZE - BASE_ADDR - lui $a1, %hi(compressed) - addiu $a1, %lo(compressed) - lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0) - move $s1, $a1 - - /* $a0 contains source compressed address, $a1 is destination, - $a2 is compressed size. FIXME: put LZMA here. Don't clober $s0, - $s1, $s2, $s3, $s4 and $s5. - On return $v0 contains uncompressed size. - */ - move $v0, $a2 -reloccont: - lb $t4, 0($a0) - sb $t4, 0($a1) - addiu $a1,$a1,1 - addiu $a0,$a0,1 - addiu $a2, 0xffff - bne $a2, $0, reloccont - - move $a0, $s1 - move $a1, $v0 - -#include "cache_flush.S" - - lui $t1, %hi(cont) - addiu $t1, %lo(cont) - - jr $t1 - . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE -compressed: . = _start + GRUB_KERNEL_MACHINE_PREFIX VARIABLE(grub_prefix) @@ -166,6 +57,8 @@ VARIABLE (grub_arch_highmemsize) .long 0 #endif cont: + /* Save our base. */ + move $s0, $ra #ifdef GRUB_MACHINE_MIPS_YEELOONG lui $t1, %hi(grub_arch_busclock) @@ -177,10 +70,8 @@ cont: #endif /* Move the modules out of BSS. */ - lui $t1, %hi(_start) - addiu $t1, %lo(_start) - lw $t2, (GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE - BASE_ADDR)($s0) - addu $t2, $t1, $t2 + lui $t2, %hi(_end) + addiu $t2, %lo(_end) lui $t1, %hi(_end) addiu $t1, %lo(_end) @@ -201,11 +92,11 @@ cont: modulesmovcont: lb $t4, 0($t2) sb $t4, 0($t1) - addiu $t1,$t1,0xffff - addiu $t2,$t2,0xffff - addiu $t3, 0xffff + addiu $t1, $t1, -1 + addiu $t3, $t3, -1 bne $t3, $0, modulesmovcont - + addiu $t2, $t2, -1 + /* Clean BSS. */ lui $t1, %hi(__bss_start) @@ -214,13 +105,14 @@ modulesmovcont: addiu $t2, %lo(_end) bsscont: sb $0,0($t1) - addiu $t1,$t1,1 - sltu $t3,$t1,$t2 + sltu $t3, $t1, $t2 bne $t3, $0, bsscont + addiu $t1, $t1, 1 li $sp, GRUB_MACHINE_MEMORY_STACK_HIGH lui $t1, %hi(grub_main) addiu $t1, %lo(grub_main) jr $t1 + nop diff --git a/grub-core/lib/mips/relocator_asm.S b/grub-core/lib/mips/relocator_asm.S index 3408b59e1..1d142a4f3 100644 --- a/grub-core/lib/mips/relocator_asm.S +++ b/grub-core/lib/mips/relocator_asm.S @@ -20,6 +20,9 @@ .p2align 4 /* force 16-byte alignment */ + .set noreorder + .set nomacro + VARIABLE (grub_relocator_forward_start) move $a0, $9 move $a1, $10 @@ -28,9 +31,9 @@ copycont1: lb $11,0($8) sb $11,0($9) addiu $8, $8, 1 - addiu $9, $9, 1 addiu $10, $10, -1 bne $10, $0, copycont1 + addiu $9, $9, 1 #include "../../kern/mips/cache_flush.S" @@ -49,9 +52,9 @@ copycont2: lb $11,0($8) sb $11,0($9) addiu $8, $8, -1 - addiu $9, $9, -1 addiu $10, $10, -1 bne $10, $0, copycont2 + addiu $9, $9, -1 #include "../../kern/mips/cache_flush.S" diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 47eb6c9bd..8caa27c2f 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -102,13 +102,12 @@ #define GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN 32 -#define GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE 0x200 -#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8 -#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0xc -#define GRUB_KERNEL_MIPS_YEELOONG_KERNEL_IMAGE_SIZE 0x10 +#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8 +#define GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE 0xc -#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE -#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE + 0x48 +#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0x08 +#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX 0x0c +#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END 0x54 /* The offset of GRUB_PREFIX. */ #define GRUB_KERNEL_I386_EFI_PREFIX 0x8 @@ -158,6 +157,7 @@ #define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _TOTAL_MODULE_SIZE) #define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _KERNEL_IMAGE_SIZE) #define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _COMPRESSED_SIZE) +#define GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _UNCOMPRESSED_SIZE) #define GRUB_KERNEL_MACHINE_PREFIX GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _PREFIX) #define GRUB_KERNEL_MACHINE_PREFIX_END GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, MACHINE, _PREFIX_END) diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index d798ad052..ee007a54b 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -248,13 +248,13 @@ struct image_target_desc image_targets[] = .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_YEELOONG_FLASH, - .flags = PLATFORM_FLAGS_NONE, + .flags = PLATFORM_FLAGS_LZMA, .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, - .raw_size = GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE, + .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE, - .compressed_size = GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE, - .kernel_image_size = GRUB_KERNEL_MIPS_YEELOONG_KERNEL_IMAGE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -268,13 +268,13 @@ struct image_target_desc image_targets[] = .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_YEELOONG_ELF, - .flags = PLATFORM_FLAGS_NONE, + .flags = PLATFORM_FLAGS_LZMA, .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, - .raw_size = GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE, + .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE, - .compressed_size = GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE, - .kernel_image_size = GRUB_KERNEL_MIPS_YEELOONG_KERNEL_IMAGE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -680,6 +680,41 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], = grub_host_to_target32 (-2); } + if (image_target->id == IMAGE_YEELOONG_FLASH + || image_target->id == IMAGE_YEELOONG_ELF) + { + char *full_img; + size_t full_size; + char *decompress_path, *decompress_img; + size_t decompress_size; + + decompress_path = grub_util_get_path (dir, "decompress.img"); + decompress_size = grub_util_get_image_size (decompress_path); + decompress_img = grub_util_read_image (decompress_path); + + *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE)) + = grub_host_to_target32 (core_size); + + *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE)) + = grub_host_to_target32 (kernel_size + total_module_size); + + full_size = core_size + decompress_size; + + full_img = xmalloc (full_size); + memset (full_img, 0, full_size); + + memcpy (full_img, decompress_img, decompress_size); + + memcpy (full_img + decompress_size, core_img, core_size); + + memset (full_img + decompress_size + core_size, 0, + full_size - (decompress_size + core_size)); + + free (core_img); + core_img = full_img; + core_size = full_size; + } + switch (image_target->id) { case IMAGE_I386_PC: From f8926c32b4d132a9c2c641a4f331f27b99866f41 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Sep 2010 11:22:52 +0200 Subject: [PATCH 3/9] C part of decompressor --- grub-core/Makefile.core.def | 9 +- grub-core/boot/decompressor.c | 115 ++++++++++++++++++++++++++ grub-core/kern/mips/cache.S | 2 +- grub-core/lib/LzmaDec.c | 40 +++++++-- grub-core/lib/xzembed/xz_dec_bcj.c | 11 ++- grub-core/lib/xzembed/xz_dec_lzma2.c | 28 ++++++- grub-core/lib/xzembed/xz_dec_stream.c | 57 +++++++++++-- include/grub/decompressor.h | 28 +++++++ include/grub/lib/LzmaDec.h | 2 +- 9 files changed, 272 insertions(+), 20 deletions(-) create mode 100644 grub-core/boot/decompressor.c create mode 100644 include/grub/decompressor.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 3341cb678..58fd7cf5d 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -278,9 +278,14 @@ image = { image = { name = decompress; mips = boot/mips/startup_raw.S; - common = lib/LzmaDec.c; + common = boot/decompressor.c; + common = lib/xzembed/xz_dec_bcj.c; + common = lib/xzembed/xz_dec_lzma2.c; + common = lib/xzembed/xz_dec_stream.c; - mips_cppflags = '-DGRUB_MACHINE_LINK_ADDR=0x80200000'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; + + mips_cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000'; objcopyflags = '-O binary'; ldflags = '-lgcc -static-libgcc -Wl,-Ttext,0x80100000'; diff --git a/grub-core/boot/decompressor.c b/grub-core/boot/decompressor.c new file mode 100644 index 000000000..5c16fb932 --- /dev/null +++ b/grub-core/boot/decompressor.c @@ -0,0 +1,115 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +#include "xz.h" +#include "xz_stream.h" + +void * +memset (void *s, int c, grub_size_t len) +{ + grub_uint8_t *ptr; + for (ptr = s; len; ptr++, len--) + *ptr = c; + return s; +} + +void * +grub_memmove (void *dest, const void *src, grub_size_t n) +{ + char *d = (char *) dest; + const char *s = (const char *) src; + + if (d < s) + while (n--) + *d++ = *s++; + else + { + d += n; + s += n; + + while (n--) + *--d = *--s; + } + + return dest; +} + +int +grub_memcmp (const void *s1, const void *s2, grub_size_t n) +{ + const char *t1 = s1; + const char *t2 = s2; + + while (n--) + { + if (*t1 != *t2) + return (int) *t1 - (int) *t2; + + t1++; + t2++; + } + + return 0; +} + +int memcmp (const void *s1, const void *s2, grub_size_t n) + __attribute__ ((alias ("grub_memcmp"))); + +void *memmove (void *dest, const void *src, grub_size_t n) + __attribute__ ((alias ("grub_memmove"))); + +void *memcpy (void *dest, const void *src, grub_size_t n) + __attribute__ ((alias ("grub_memmove"))); + +void +grub_decompress_core (void *src, void *dst, unsigned long srcsize, + unsigned long dstsize) +{ + struct xz_dec *dec; + struct xz_buf buf; + + dec = xz_dec_init (GRUB_DECOMPRESSOR_DICT_SIZE); + + buf.in = src; + buf.in_pos = 0; + buf.in_size = srcsize; + buf.out = dst; + buf.out_pos = 0; + buf.out_size = dstsize; + + while (buf.in_pos != buf.in_size) + { + enum xz_ret xzret; + xzret = xz_dec_run (dec, &buf); + switch (xzret) + { + case XZ_MEMLIMIT_ERROR: + case XZ_FORMAT_ERROR: + case XZ_OPTIONS_ERROR: + case XZ_DATA_ERROR: + case XZ_BUF_ERROR: + return; + default: + break; + } + } +} diff --git a/grub-core/kern/mips/cache.S b/grub-core/kern/mips/cache.S index 02dc3355f..999872f6b 100644 --- a/grub-core/kern/mips/cache.S +++ b/grub-core/kern/mips/cache.S @@ -1,8 +1,8 @@ #include - .set nomacro .set noreorder + .set nomacro FUNCTION (grub_cpu_flush_cache) FUNCTION (grub_arch_sync_caches) diff --git a/grub-core/lib/LzmaDec.c b/grub-core/lib/LzmaDec.c index 62ebee686..4d6890b60 100644 --- a/grub-core/lib/LzmaDec.c +++ b/grub-core/lib/LzmaDec.c @@ -26,7 +26,14 @@ #include -#include +static void +memcpy (void *a_, const void *b_, unsigned s) +{ + char *a = a_; + const char *b = b_; + while (s--) + *a++ = *b++; +} #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) @@ -294,14 +301,14 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte prob = probs + RepLenCoder; } { - unsigned limit, offset; + unsigned limit2, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; - limit = (1 << kLenNumLowBits); + limit2 = (1 << kLenNumLowBits); } else { @@ -312,17 +319,17 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte UPDATE_0(probLen); probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; - limit = (1 << kLenNumMidBits); + limit2 = (1 << kLenNumMidBits); } else { UPDATE_1(probLen); probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; - limit = (1 << kLenNumHighBits); + limit2 = (1 << kLenNumHighBits); } } - TREE_DECODE(probLen, limit, len); + TREE_DECODE(probLen, limit2, len); len += offset; } @@ -718,7 +725,7 @@ static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) p->needFlush = 0; } -void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; @@ -915,6 +922,7 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *sr void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) { + return ; alloc->Free(alloc, p->probs); p->probs = 0; } @@ -957,13 +965,16 @@ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) return SZ_OK; } +static char sal[30000], *sptr = sal; + static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) { UInt32 numProbs = LzmaProps_GetNumProbs(propNew); if (p->probs == 0 || numProbs != p->numProbs) { LzmaDec_FreeProbs(p, alloc); - p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->probs = (CLzmaProb *) sptr; + sptr += sizeof (CLzmaProb); p->numProbs = numProbs; if (p->probs == 0) return SZ_ERROR_MEM; @@ -1033,3 +1044,16 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, LzmaDec_FreeProbs(&p, alloc); return res; } + +void +grub_decompress_core (void *src, void *dst, unsigned long srcsize, unsigned long dstsize); + +void +grub_decompress_core (void *src, void *dst, unsigned long srcsize, unsigned long dstsize) +{ + char *src_ = src, *dst_ = dst; + (void) dstsize; + while (srcsize--) + *dst_++ = *src_++ ^ 0x5a; +} + diff --git a/grub-core/lib/xzembed/xz_dec_bcj.c b/grub-core/lib/xzembed/xz_dec_bcj.c index 7eec9de7d..f517b0acc 100644 --- a/grub-core/lib/xzembed/xz_dec_bcj.c +++ b/grub-core/lib/xzembed/xz_dec_bcj.c @@ -520,9 +520,18 @@ enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, return s->ret; } +#ifdef GRUB_EMBED_DECOMPRESSOR +struct xz_dec_bcj bcj; +#endif + struct xz_dec_bcj * xz_dec_bcj_create(bool single_call) { - struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL); + struct xz_dec_bcj *s; +#ifdef GRUB_EMBED_DECOMPRESSOR + s = &bcj; +#else + s = kmalloc(sizeof(*s), GFP_KERNEL); +#endif if (s != NULL) s->single_call = single_call; diff --git a/grub-core/lib/xzembed/xz_dec_lzma2.c b/grub-core/lib/xzembed/xz_dec_lzma2.c index a0d422697..c55773ce0 100644 --- a/grub-core/lib/xzembed/xz_dec_lzma2.c +++ b/grub-core/lib/xzembed/xz_dec_lzma2.c @@ -1100,10 +1100,17 @@ enum xz_ret xz_dec_lzma2_run( return XZ_OK; } +#ifdef GRUB_EMBED_DECOMPRESSOR +#include +static struct xz_dec_lzma2 lzma2; +static char dict[GRUB_DECOMPRESSOR_DICT_SIZE]; +#endif + struct xz_dec_lzma2 * xz_dec_lzma2_create(uint32_t dict_max) { struct xz_dec_lzma2 *s; +#ifndef GRUB_EMBED_DECOMPRESSOR /* Maximum supported dictionary by this implementation is 3 GiB. */ if (dict_max > ((uint32_t)3 << 30)) return NULL; @@ -1120,6 +1127,17 @@ struct xz_dec_lzma2 * xz_dec_lzma2_create(uint32_t dict_max) } } +#else + if (dict_max > GRUB_DECOMPRESSOR_DICT_SIZE) + return NULL; + + s = &lzma2; + + if (dict_max > 0) { + s->dict.buf = (void *) &dict; + } +#endif + s->dict.allocated = dict_max; return s; @@ -1135,6 +1153,7 @@ enum xz_ret xz_dec_lzma2_reset( s->dict.size = 2 + (props & 1); s->dict.size <<= (props >> 1) + 11; +#ifndef GRUB_EMBED_DECOMPRESSOR if (s->dict.allocated > 0 && s->dict.allocated < s->dict.size) { /* enlarge dictionary buffer */ @@ -1146,7 +1165,10 @@ enum xz_ret xz_dec_lzma2_reset( s->dict.buf = newdict; s->dict.allocated = s->dict.size; } - +#else + if (s->dict.allocated > 0 && s->dict.allocated < s->dict.size) + return XZ_MEMLIMIT_ERROR; +#endif s->dict.end = s->dict.size; s->lzma.len = 0; @@ -1159,10 +1181,12 @@ enum xz_ret xz_dec_lzma2_reset( return XZ_OK; } -void xz_dec_lzma2_end(struct xz_dec_lzma2 *s) +void xz_dec_lzma2_end(struct xz_dec_lzma2 *s __attribute__ ((unused))) { +#ifndef GRUB_EMBED_DECOMPRESSOR if (s->dict.allocated > 0) vfree(s->dict.buf); kfree(s); +#endif } diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c index 273041edb..3bf201d50 100644 --- a/grub-core/lib/xzembed/xz_dec_stream.c +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -31,7 +31,9 @@ struct xz_dec_hash { vli_type unpadded; vli_type uncompressed; +#ifndef GRUB_EMBED_DECOMPRESSOR uint8_t *crc32_context; +#endif }; struct xz_dec { @@ -247,9 +249,11 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) > s->block_header.uncompressed) return XZ_DATA_ERROR; +#ifndef GRUB_EMBED_DECOMPRESSOR if (s->has_crc32) GRUB_MD_CRC32->write(s->crc32_context,b->out + s->out_start, b->out_pos - s->out_start); +#endif if (ret == XZ_STREAM_END) { if (s->block_header.compressed != VLI_UNKNOWN @@ -269,8 +273,10 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) s->block.hash.uncompressed += s->block.uncompressed; +#ifndef GRUB_EMBED_DECOMPRESSOR GRUB_MD_CRC32->write(s->block.hash.crc32_context, (const uint8_t *)&s->block.hash, 2 * sizeof(vli_type)); +#endif ++s->block.count; } @@ -283,7 +289,9 @@ static void index_update(struct xz_dec *s, const struct xz_buf *b) { size_t in_used = b->in_pos - s->in_start; s->index.size += in_used; +#ifndef GRUB_EMBED_DECOMPRESSOR GRUB_MD_CRC32->write(s->crc32_context,b->in + s->in_start, in_used); +#endif } /* @@ -328,8 +336,10 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) case SEQ_INDEX_UNCOMPRESSED: s->index.hash.uncompressed += s->vli; +#ifndef GRUB_EMBED_DECOMPRESSOR GRUB_MD_CRC32->write(s->index.hash.crc32_context, (const uint8_t *)&s->index.hash, 2 * sizeof(vli_type)); +#endif --s->index.count; s->index.sequence = SEQ_INDEX_UNPADDED; @@ -346,24 +356,30 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) */ static enum xz_ret crc32_validate(struct xz_dec *s, struct xz_buf *b) { +#ifndef GRUB_EMBED_DECOMPRESSOR if(s->crc32_temp == 0) { GRUB_MD_CRC32->final(s->crc32_context); s->crc32_temp = get_unaligned_be32(GRUB_MD_CRC32->read(s->crc32_context)); } +#endif do { if (b->in_pos == b->in_size) return XZ_OK; +#ifndef GRUB_EMBED_DECOMPRESSOR if (((s->crc32_temp >> s->pos) & 0xFF) != b->in[b->in_pos++]) return XZ_DATA_ERROR; +#endif s->pos += 8; } while (s->pos < 32); +#ifndef GRUB_EMBED_DECOMPRESSOR GRUB_MD_CRC32->init(s->crc32_context); +#endif s->crc32_temp = 0; s->pos = 0; @@ -376,6 +392,7 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) if (! memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE)) return XZ_FORMAT_ERROR; +#ifndef GRUB_EMBED_DECOMPRESSOR uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; GRUB_MD_CRC32->init(crc32_context); @@ -387,6 +404,7 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) if(resultcrc != readcrc) return XZ_DATA_ERROR; +#endif /* * Decode the Stream Flags field. Of integrity checks, we support @@ -407,6 +425,7 @@ static enum xz_ret dec_stream_footer(struct xz_dec *s) if (! memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE)) return XZ_DATA_ERROR; +#ifndef GRUB_EMBED_DECOMPRESSOR uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; GRUB_MD_CRC32->init(crc32_context); @@ -418,6 +437,7 @@ static enum xz_ret dec_stream_footer(struct xz_dec *s) if(resultcrc != readcrc) return XZ_DATA_ERROR; +#endif /* * Validate Backward Size. Note that we never added the size of the @@ -447,7 +467,7 @@ static enum xz_ret dec_block_header(struct xz_dec *s) * eight bytes so this is safe. */ s->temp.size -= 4; - +#ifndef GRUB_EMBED_DECOMPRESSOR uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; GRUB_MD_CRC32->init(crc32_context); @@ -459,6 +479,7 @@ static enum xz_ret dec_block_header(struct xz_dec *s) if (resultcrc != readcrc) return XZ_DATA_ERROR; +#endif s->temp.pos = 2; @@ -669,6 +690,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) /* Finish the CRC32 value and Index size. */ index_update(s, b); +#ifndef GRUB_EMBED_DECOMPRESSOR /* Compare the hashes to validate the Index field. */ GRUB_MD_CRC32->final(s->block.hash.crc32_context); GRUB_MD_CRC32->final(s->index.hash.crc32_context); @@ -681,6 +703,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) { return XZ_DATA_ERROR; } +#endif s->sequence = SEQ_INDEX_CRC32; @@ -764,12 +787,22 @@ enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b) return ret; } +#ifdef GRUB_EMBED_DECOMPRESSOR +struct xz_dec decoder; +#endif + struct xz_dec * xz_dec_init(uint32_t dict_max) { - struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL); + struct xz_dec *s; +#ifdef GRUB_EMBED_DECOMPRESSOR + s = &decoder; +#else + s = kmalloc(sizeof(*s), GFP_KERNEL); if (s == NULL) return NULL; +#endif +#ifndef GRUB_EMBED_DECOMPRESSOR /* prepare CRC32 calculators */ if(GRUB_MD_CRC32 == NULL) { @@ -803,10 +836,11 @@ struct xz_dec * xz_dec_init(uint32_t dict_max) GRUB_MD_CRC32->init(s->crc32_context); - s->crc32_temp = 0; GRUB_MD_CRC32->init(s->index.hash.crc32_context); GRUB_MD_CRC32->init(s->block.hash.crc32_context); +#endif + s->crc32_temp = 0; s->single_call = dict_max == 0; @@ -828,7 +862,9 @@ error_lzma2: xz_dec_bcj_end(s->bcj); error_bcj: #endif +#ifndef GRUB_EMBED_DECOMPRESSOR kfree(s); +#endif return NULL; } @@ -839,34 +875,45 @@ void xz_dec_reset(struct xz_dec *s) s->pos = 0; { +#ifndef GRUB_EMBED_DECOMPRESSOR uint8_t *t; t = s->block.hash.crc32_context; +#endif memzero(&s->block, sizeof(s->block)); +#ifndef GRUB_EMBED_DECOMPRESSOR s->block.hash.crc32_context = t; t = s->index.hash.crc32_context; +#endif memzero(&s->index, sizeof(s->index)); +#ifndef GRUB_EMBED_DECOMPRESSOR s->index.hash.crc32_context = t; +#endif } s->temp.pos = 0; s->temp.size = STREAM_HEADER_SIZE; +#ifndef GRUB_EMBED_DECOMPRESSOR GRUB_MD_CRC32->init(s->crc32_context); - s->crc32_temp = 0; GRUB_MD_CRC32->init(s->index.hash.crc32_context); GRUB_MD_CRC32->init(s->block.hash.crc32_context); - +#endif + s->crc32_temp = 0; } void xz_dec_end(struct xz_dec *s) { if (s != NULL) { xz_dec_lzma2_end(s->lzma2); +#ifndef GRUB_EMBED_DECOMPRESSOR kfree(s->index.hash.crc32_context); kfree(s->block.hash.crc32_context); kfree(s->crc32_context); +#endif #ifdef XZ_DEC_BCJ xz_dec_bcj_end(s->bcj); #endif +#ifndef GRUB_EMBED_DECOMPRESSOR kfree(s); +#endif } } diff --git a/include/grub/decompressor.h b/include/grub/decompressor.h new file mode 100644 index 000000000..4d99c41f7 --- /dev/null +++ b/include/grub/decompressor.h @@ -0,0 +1,28 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_DECOMPRESSOR_HEADER +#define GRUB_DECOMPRESSOR_HEADER 1 + +void +grub_decompress_core (void *src, void *dst, unsigned long srcsize, + unsigned long dstsize); + +#define GRUB_DECOMPRESSOR_DICT_SIZE (1 << 16) + +#endif diff --git a/include/grub/lib/LzmaDec.h b/include/grub/lib/LzmaDec.h index 1e66b74d7..16914c961 100644 --- a/include/grub/lib/LzmaDec.h +++ b/include/grub/lib/LzmaDec.h @@ -27,7 +27,7 @@ #ifndef __LZMADEC_H #define __LZMADEC_H -#include "Types.h" +#include "LzmaTypes.h" /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, From e0a8ef26e4aebe108caf7fc7c852b81c4f7c9b89 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Sep 2010 19:39:51 +0200 Subject: [PATCH 4/9] MAke a separate scratch for decompressor --- grub-core/boot/decompressor.c | 23 +++++++++++++++++++++++ grub-core/boot/mips/startup_raw.S | 2 +- grub-core/kern/mips/startup.S | 4 ++-- grub-core/lib/xzembed/xz_dec_lzma2.c | 12 +----------- include/grub/decompressor.h | 6 ++++++ 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/grub-core/boot/decompressor.c b/grub-core/boot/decompressor.c index 5c16fb932..604fc754c 100644 --- a/grub-core/boot/decompressor.c +++ b/grub-core/boot/decompressor.c @@ -80,6 +80,27 @@ void *memmove (void *dest, const void *src, grub_size_t n) void *memcpy (void *dest, const void *src, grub_size_t n) __attribute__ ((alias ("grub_memmove"))); +void *grub_decompressor_scratch; + +void +find_scratch (void *src, void *dst, unsigned long srcsize, + unsigned long dstsize) +{ +#ifdef _mips + /* Decoding from ROM. */ + if (((grub_addr_t) src & 0x10000000)) + { + grub_decompressor_scratch = (char *) dst + dstsize; + return; + } +#endif + if ((char *) src + srcsize > (char *) dst + dstsize) + grub_decompressor_scratch = (char *) src + srcsize; + else + grub_decompressor_scratch = (char *) dst + dstsize; + return; +} + void grub_decompress_core (void *src, void *dst, unsigned long srcsize, unsigned long dstsize) @@ -87,6 +108,8 @@ grub_decompress_core (void *src, void *dst, unsigned long srcsize, struct xz_dec *dec; struct xz_buf buf; + find_scratch (src, dst, srcsize, dstsize); + dec = xz_dec_init (GRUB_DECOMPRESSOR_DICT_SIZE); buf.in = src; diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index 67dc2ec03..d810f2fb4 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -49,7 +49,7 @@ codestart: /* Parse arguments. Has to be done before relocation. So need to do it in asm. */ -#if 0 // def GRUB_MACHINE_MIPS_YEELOONG +#ifdef GRUB_MACHINE_MIPS_YEELOONG move $s2, $zero move $s3, $zero move $s4, $zero diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 1b27a5b1f..97145b818 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -109,10 +109,10 @@ bsscont: bne $t3, $0, bsscont addiu $t1, $t1, 1 - li $sp, GRUB_MACHINE_MEMORY_STACK_HIGH lui $t1, %hi(grub_main) addiu $t1, %lo(grub_main) + lui $sp, %hi(GRUB_MACHINE_MEMORY_STACK_HIGH) jr $t1 - nop + addiu $sp, $sp, %lo(GRUB_MACHINE_MEMORY_STACK_HIGH) diff --git a/grub-core/lib/xzembed/xz_dec_lzma2.c b/grub-core/lib/xzembed/xz_dec_lzma2.c index c55773ce0..7899e9e87 100644 --- a/grub-core/lib/xzembed/xz_dec_lzma2.c +++ b/grub-core/lib/xzembed/xz_dec_lzma2.c @@ -1103,7 +1103,6 @@ enum xz_ret xz_dec_lzma2_run( #ifdef GRUB_EMBED_DECOMPRESSOR #include static struct xz_dec_lzma2 lzma2; -static char dict[GRUB_DECOMPRESSOR_DICT_SIZE]; #endif struct xz_dec_lzma2 * xz_dec_lzma2_create(uint32_t dict_max) @@ -1128,14 +1127,8 @@ struct xz_dec_lzma2 * xz_dec_lzma2_create(uint32_t dict_max) } #else - if (dict_max > GRUB_DECOMPRESSOR_DICT_SIZE) - return NULL; - s = &lzma2; - - if (dict_max > 0) { - s->dict.buf = (void *) &dict; - } + s->dict.buf = grub_decompressor_scratch; #endif s->dict.allocated = dict_max; @@ -1165,9 +1158,6 @@ enum xz_ret xz_dec_lzma2_reset( s->dict.buf = newdict; s->dict.allocated = s->dict.size; } -#else - if (s->dict.allocated > 0 && s->dict.allocated < s->dict.size) - return XZ_MEMLIMIT_ERROR; #endif s->dict.end = s->dict.size; diff --git a/include/grub/decompressor.h b/include/grub/decompressor.h index 4d99c41f7..a6eefb01b 100644 --- a/include/grub/decompressor.h +++ b/include/grub/decompressor.h @@ -23,6 +23,12 @@ void grub_decompress_core (void *src, void *dst, unsigned long srcsize, unsigned long dstsize); +void +find_scratch (void *src, void *dst, unsigned long srcsize, + unsigned long dstsize); + #define GRUB_DECOMPRESSOR_DICT_SIZE (1 << 16) +extern void *grub_decompressor_scratch; + #endif From 758194b076cb4f279feceabea2c1b28cd7a16257 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Sep 2010 20:30:28 +0200 Subject: [PATCH 5/9] Allow compression algorithm specification --- grub-core/Makefile.core.def | 18 ++- .../minilib.c} | 39 ------- grub-core/boot/decompressor/none.c | 39 +++++++ grub-core/boot/decompressor/xz.c | 60 ++++++++++ util/grub-mkimage.c | 107 +++++++++++++++--- 5 files changed, 208 insertions(+), 55 deletions(-) rename grub-core/boot/{decompressor.c => decompressor/minilib.c} (76%) create mode 100644 grub-core/boot/decompressor/none.c create mode 100644 grub-core/boot/decompressor/xz.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 58fd7cf5d..48579896c 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -276,9 +276,10 @@ image = { }; image = { - name = decompress; + name = xz_decompress; mips = boot/mips/startup_raw.S; - common = boot/decompressor.c; + common = boot/decompressor/minilib.c; + common = boot/decompressor/xz.c; common = lib/xzembed/xz_dec_bcj.c; common = lib/xzembed/xz_dec_lzma2.c; common = lib/xzembed/xz_dec_stream.c; @@ -293,6 +294,19 @@ image = { enable = mips; }; +image = { + name = none_decompress; + mips = boot/mips/startup_raw.S; + common = boot/decompressor/none.c; + + mips_cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1 -DGRUB_MACHINE_LINK_ADDR=0x80200000'; + + objcopyflags = '-O binary'; + ldflags = '-lgcc -static-libgcc -Wl,-Ttext,0x80100000'; + cflags = '-static-libgcc'; + enable = mips; +}; + image = { name = fwstart; mips_yeeloong = boot/mips/yeeloong/fwstart.S; diff --git a/grub-core/boot/decompressor.c b/grub-core/boot/decompressor/minilib.c similarity index 76% rename from grub-core/boot/decompressor.c rename to grub-core/boot/decompressor/minilib.c index 604fc754c..d1f021933 100644 --- a/grub-core/boot/decompressor.c +++ b/grub-core/boot/decompressor/minilib.c @@ -20,9 +20,6 @@ #include #include -#include "xz.h" -#include "xz_stream.h" - void * memset (void *s, int c, grub_size_t len) { @@ -100,39 +97,3 @@ find_scratch (void *src, void *dst, unsigned long srcsize, grub_decompressor_scratch = (char *) dst + dstsize; return; } - -void -grub_decompress_core (void *src, void *dst, unsigned long srcsize, - unsigned long dstsize) -{ - struct xz_dec *dec; - struct xz_buf buf; - - find_scratch (src, dst, srcsize, dstsize); - - dec = xz_dec_init (GRUB_DECOMPRESSOR_DICT_SIZE); - - buf.in = src; - buf.in_pos = 0; - buf.in_size = srcsize; - buf.out = dst; - buf.out_pos = 0; - buf.out_size = dstsize; - - while (buf.in_pos != buf.in_size) - { - enum xz_ret xzret; - xzret = xz_dec_run (dec, &buf); - switch (xzret) - { - case XZ_MEMLIMIT_ERROR: - case XZ_FORMAT_ERROR: - case XZ_OPTIONS_ERROR: - case XZ_DATA_ERROR: - case XZ_BUF_ERROR: - return; - default: - break; - } - } -} diff --git a/grub-core/boot/decompressor/none.c b/grub-core/boot/decompressor/none.c new file mode 100644 index 000000000..44f56ce90 --- /dev/null +++ b/grub-core/boot/decompressor/none.c @@ -0,0 +1,39 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include + +void +grub_decompress_core (void *src, void *dest, unsigned long n, + unsigned long dstsize __attribute__ ((unused))) +{ + char *d = (char *) dest; + const char *s = (const char *) src; + + if (d < s) + while (n--) + *d++ = *s++; + else + { + d += n; + s += n; + + while (n--) + *--d = *--s; + } +} diff --git a/grub-core/boot/decompressor/xz.c b/grub-core/boot/decompressor/xz.c new file mode 100644 index 000000000..2279118e1 --- /dev/null +++ b/grub-core/boot/decompressor/xz.c @@ -0,0 +1,60 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +#include "xz.h" +#include "xz_stream.h" + +void +grub_decompress_core (void *src, void *dst, unsigned long srcsize, + unsigned long dstsize) +{ + struct xz_dec *dec; + struct xz_buf buf; + + find_scratch (src, dst, srcsize, dstsize); + + dec = xz_dec_init (GRUB_DECOMPRESSOR_DICT_SIZE); + + buf.in = src; + buf.in_pos = 0; + buf.in_size = srcsize; + buf.out = dst; + buf.out_pos = 0; + buf.out_size = dstsize; + + while (buf.in_pos != buf.in_size) + { + enum xz_ret xzret; + xzret = xz_dec_run (dec, &buf); + switch (xzret) + { + case XZ_MEMLIMIT_ERROR: + case XZ_FORMAT_ERROR: + case XZ_OPTIONS_ERROR: + case XZ_DATA_ERROR: + case XZ_BUF_ERROR: + return; + default: + break; + } + } +} diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index ee007a54b..75343ac30 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -46,6 +46,11 @@ #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) #define TARGET_NO_FIELD 0xffffffff + +typedef enum { + COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ +} grub_compression_t; + struct image_target_desc { const char *name; @@ -60,7 +65,8 @@ struct image_target_desc enum { PLATFORM_FLAGS_NONE = 0, - PLATFORM_FLAGS_LZMA = 1 + PLATFORM_FLAGS_LZMA = 1, + PLATFORM_FLAGS_DECOMPRESSORS = 2 } flags; unsigned prefix; unsigned prefix_end; @@ -75,6 +81,7 @@ struct image_target_desc unsigned install_dos_part, install_bsd_part; grub_uint64_t link_addr; unsigned mod_gap, mod_align; + grub_compression_t default_compression; }; struct image_target_desc image_targets[] = @@ -248,7 +255,7 @@ struct image_target_desc image_targets[] = .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_YEELOONG_FLASH, - .flags = PLATFORM_FLAGS_LZMA, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, .raw_size = 0, @@ -261,14 +268,15 @@ struct image_target_desc image_targets[] = .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, .elf_target = EM_MIPS, - .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN + .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, + .default_compression = COMPRESSION_XZ }, { .name = "mipsel-yeeloong-elf", .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_YEELOONG_ELF, - .flags = PLATFORM_FLAGS_LZMA, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, .prefix = GRUB_KERNEL_MIPS_YEELOONG_PREFIX, .prefix_end = GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END, .raw_size = 0, @@ -281,7 +289,8 @@ struct image_target_desc image_targets[] = .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, .elf_target = EM_MIPS, - .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN + .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, + .default_compression = COMPRESSION_NONE }, { .name = "powerpc-ieee1275", @@ -483,7 +492,39 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size, memcpy (*core_img, kernel_img, raw_size); *core_size = kernel_size - raw_size; - if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size, + if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size - raw_size, + (unsigned char *) kernel_img + raw_size, + kernel_size - raw_size, + &props, out_props, &out_props_size, + 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK) + grub_util_error (_("cannot compress the kernel image")); + + *core_size += raw_size; +} + +static void +compress_kernel_xz (char *kernel_img, size_t kernel_size, + char **core_img, size_t *core_size, size_t raw_size) +{ + CLzmaEncProps props; + unsigned char out_props[5]; + size_t out_props_size = 5; + + LzmaEncProps_Init(&props); + props.dictSize = 1 << 16; + props.lc = 3; + props.lp = 0; + props.pb = 2; + props.numThreads = 1; + + if (kernel_size < raw_size) + grub_util_error (_("the core image is too small")); + + *core_img = xmalloc (kernel_size); + memcpy (*core_img, kernel_img, raw_size); + + *core_size = kernel_size - raw_size; + if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size - raw_size, (unsigned char *) kernel_img + raw_size, kernel_size - raw_size, &props, out_props, &out_props_size, @@ -495,7 +536,8 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size, static void compress_kernel (struct image_target_desc *image_target, char *kernel_img, - size_t kernel_size, char **core_img, size_t *core_size) + size_t kernel_size, char **core_img, size_t *core_size, + grub_compression_t comp) { if (image_target->flags & PLATFORM_FLAGS_LZMA) { @@ -504,6 +546,14 @@ compress_kernel (struct image_target_desc *image_target, char *kernel_img, return; } + if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS + && (comp == COMPRESSION_XZ)) + { + compress_kernel_xz (kernel_img, kernel_size, core_img, + core_size, image_target->raw_size); + return; + } + *core_img = xmalloc (kernel_size); memcpy (*core_img, kernel_img, kernel_size); *core_size = kernel_size; @@ -527,7 +577,8 @@ struct fixup_block_list static void generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *memdisk_path, char *config_path, - struct image_target_desc *image_target, int note) + struct image_target_desc *image_target, int note, + grub_compression_t comp) { char *kernel_img, *core_img; size_t kernel_size, total_module_size, core_size, exec_size; @@ -539,6 +590,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], grub_uint64_t start_address; void *rel_section; grub_size_t reloc_size, align; + + if (comp == COMPRESSION_AUTO) + comp = image_target->default_compression; + path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods); kernel_path = grub_util_get_path (dir, "kernel.img"); @@ -655,7 +710,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size); compress_kernel (image_target, kernel_img, kernel_size + total_module_size, - &core_img, &core_size); + &core_img, &core_size, comp); grub_util_info ("the core size is 0x%x", core_size); @@ -680,15 +735,27 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], = grub_host_to_target32 (-2); } - if (image_target->id == IMAGE_YEELOONG_FLASH - || image_target->id == IMAGE_YEELOONG_ELF) + if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) { char *full_img; size_t full_size; char *decompress_path, *decompress_img; size_t decompress_size; + const char *name; + + switch (comp) + { + case COMPRESSION_XZ: + name = "xz_decompress.img"; + break; + case COMPRESSION_NONE: + name = "none_decompress.img"; + break; + default: + grub_util_error ("unknown compression %d\n", comp); + } - decompress_path = grub_util_get_path (dir, "decompress.img"); + decompress_path = grub_util_get_path (dir, name); decompress_size = grub_util_get_image_size (decompress_path); decompress_img = grub_util_read_image (decompress_path); @@ -1253,6 +1320,7 @@ static struct option options[] = {"output", required_argument, 0, 'o'}, {"note", no_argument, 0, 'n'}, {"format", required_argument, 0, 'O'}, + {"compression", required_argument, 0, 'C'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"verbose", no_argument, 0, 'v'}, @@ -1295,6 +1363,7 @@ Make a bootable image of GRUB.\n\ -o, --output=FILE output a generated image to FILE [default=stdout]\n\ -O, --format=FORMAT generate an image in format\n\ available formats: %s\n\ + -C, --compression=(xz|none|auto) choose the compression to use\n\ -h, --help display this message and exit\n\ -V, --version print version information and exit\n\ -v, --verbose print verbose messages\n\ @@ -1321,6 +1390,7 @@ main (int argc, char *argv[]) FILE *fp = stdout; int note = 0; struct image_target_desc *image_target = NULL; + grub_compression_t comp = COMPRESSION_AUTO; set_program_name (argv[0]); @@ -1328,7 +1398,7 @@ main (int argc, char *argv[]) while (1) { - int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:hVvn", options, 0); + int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:C:hVvn", options, 0); if (c == -1) break; @@ -1385,6 +1455,15 @@ main (int argc, char *argv[]) config = xstrdup (optarg); break; + case 'C': + if (grub_strcmp (optarg, "xz") == 0) + comp = COMPRESSION_XZ; + else if (grub_strcmp (optarg, "none") == 0) + comp = COMPRESSION_NONE; + else + grub_util_error ("Unknown compression format %s", optarg); + break; + case 'h': usage (0); break; @@ -1443,7 +1522,7 @@ main (int argc, char *argv[]) generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind, memdisk, config, - image_target, note); + image_target, note, comp); fclose (fp); From 2c44e493c756cb211f2a7f85e048f446773382fd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Sep 2010 21:35:46 +0200 Subject: [PATCH 6/9] Compressor part --- Makefile.util.def | 1 + configure.ac | 6 ++++ util/grub-mkimage.c | 79 ++++++++++++++++++++++++++++++++++----------- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index f56eab339..6ed4ccb65 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -113,6 +113,7 @@ program = { extra_dist = util/grub-mkimagexx.c; ldadd = libgrub.a; + ldadd = '$(LIBLZMA)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; cppflags = '-DGRUB_PKGLIBROOTDIR=\"$(pkglibrootdir)\"'; }; diff --git a/configure.ac b/configure.ac index 10723987b..225e02a0d 100644 --- a/configure.ac +++ b/configure.ac @@ -849,6 +849,12 @@ fi AC_SUBST([LIBDEVMAPPER]) +AC_CHECK_LIB([lzma], [lzma_code], + [LIBLZMA="-llzma" + AC_DEFINE([HAVE_LIBLZMA], [1], + [Define to 1 if you have the LZMA library.])],) +AC_SUBST([LIBLZMA]) + AC_CHECK_LIB([zfs], [libzfs_init], [LIBZFS="-lzfs" AC_DEFINE([HAVE_LIBZFS], [1], diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 75343ac30..8a907b414 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -45,6 +45,10 @@ #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) +#ifdef HAVE_LIBLZMA +#include +#endif + #define TARGET_NO_FIELD 0xffffffff typedef enum { @@ -269,7 +273,11 @@ struct image_target_desc image_targets[] = .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, +#ifdef HAVE_LIBLZMA .default_compression = COMPRESSION_XZ +#else + .default_compression = COMPRESSION_NONE +#endif }, { .name = "mipsel-yeeloong-elf", @@ -492,7 +500,7 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size, memcpy (*core_img, kernel_img, raw_size); *core_size = kernel_size - raw_size; - if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size - raw_size, + if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size, (unsigned char *) kernel_img + raw_size, kernel_size - raw_size, &props, out_props, &out_props_size, @@ -506,30 +514,52 @@ static void compress_kernel_xz (char *kernel_img, size_t kernel_size, char **core_img, size_t *core_size, size_t raw_size) { - CLzmaEncProps props; - unsigned char out_props[5]; - size_t out_props_size = 5; - - LzmaEncProps_Init(&props); - props.dictSize = 1 << 16; - props.lc = 3; - props.lp = 0; - props.pb = 2; - props.numThreads = 1; + lzma_stream strm = LZMA_STREAM_INIT; + lzma_ret xzret; + lzma_options_lzma lzopts = { + .dict_size = 1 << 16, + .preset_dict = NULL, + .preset_dict_size = 0, + .lc = 3, + .lp = 0, + .pb = 2, + .mode = LZMA_MODE_NORMAL, + .nice_len = 64, + .mf = LZMA_MF_BT4, + .depth = 0, + }; + lzma_filter fltrs[] = { + { .id = LZMA_FILTER_LZMA2, .options = &lzopts}, + { .id = LZMA_VLI_UNKNOWN, .options = NULL} + }; if (kernel_size < raw_size) grub_util_error (_("the core image is too small")); + xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE); + if (xzret != LZMA_OK) + grub_util_error (_("cannot compress the kernel image")); + *core_img = xmalloc (kernel_size); memcpy (*core_img, kernel_img, raw_size); *core_size = kernel_size - raw_size; - if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size - raw_size, - (unsigned char *) kernel_img + raw_size, - kernel_size - raw_size, - &props, out_props, &out_props_size, - 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK) - grub_util_error (_("cannot compress the kernel image")); + strm.next_in = (unsigned char *) kernel_img + raw_size; + strm.avail_in = kernel_size - raw_size; + strm.next_out = (unsigned char *) *core_img + raw_size; + strm.avail_out = *core_size; + + while (1) + { + xzret = lzma_code (&strm, LZMA_FINISH); + if (xzret == LZMA_OK) + continue; + if (xzret == LZMA_STREAM_END) + break; + grub_util_error (_("cannot compress the kernel image")); + } + + *core_size -= strm.avail_out; *core_size += raw_size; } @@ -546,6 +576,7 @@ compress_kernel (struct image_target_desc *image_target, char *kernel_img, return; } +#ifdef HAVE_LIBLZMA if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS && (comp == COMPRESSION_XZ)) { @@ -553,6 +584,11 @@ compress_kernel (struct image_target_desc *image_target, char *kernel_img, core_size, image_target->raw_size); return; } +#endif + + if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS + && (comp != COMPRESSION_NONE)) + grub_util_error ("unknown compression %d\n", comp); *core_img = xmalloc (kernel_size); memcpy (*core_img, kernel_img, kernel_size); @@ -1457,7 +1493,14 @@ main (int argc, char *argv[]) case 'C': if (grub_strcmp (optarg, "xz") == 0) - comp = COMPRESSION_XZ; + { +#ifdef HAVE_LIBLZMA + comp = COMPRESSION_XZ; +#else + grub_util_error ("grub-mkimage is compiled without XZ support", + optarg); +#endif + } else if (grub_strcmp (optarg, "none") == 0) comp = COMPRESSION_NONE; else From bf5f1dc6d267a6734cd4ead2cbcf7d200411158c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 22 Sep 2010 00:51:54 +0200 Subject: [PATCH 7/9] Write total module size before compressing --- util/grub-mkimage.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 8a907b414..73713f2bc 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -273,11 +273,7 @@ struct image_target_desc image_targets[] = .link_addr = GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN, -#ifdef HAVE_LIBLZMA - .default_compression = COMPRESSION_XZ -#else .default_compression = COMPRESSION_NONE -#endif }, { .name = "mipsel-yeeloong-elf", @@ -744,13 +740,19 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], offset += config_size; } + if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) + && (image_target->total_module_size != TARGET_NO_FIELD)) + *((grub_uint32_t *) (kernel_img + image_target->total_module_size)) + = grub_host_to_target32 (total_module_size); + grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size); compress_kernel (image_target, kernel_img, kernel_size + total_module_size, &core_img, &core_size, comp); grub_util_info ("the core size is 0x%x", core_size); - if (image_target->total_module_size != TARGET_NO_FIELD) + if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) + && image_target->total_module_size != TARGET_NO_FIELD) *((grub_uint32_t *) (core_img + image_target->total_module_size)) = grub_host_to_target32 (total_module_size); if (image_target->kernel_image_size != TARGET_NO_FIELD) From 67c4bb722d425aacd968d4462ca4aff8beb7b303 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 22 Sep 2010 00:52:33 +0200 Subject: [PATCH 8/9] Align scratch --- grub-core/boot/decompressor/minilib.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/grub-core/boot/decompressor/minilib.c b/grub-core/boot/decompressor/minilib.c index d1f021933..f2a2ef7e5 100644 --- a/grub-core/boot/decompressor/minilib.c +++ b/grub-core/boot/decompressor/minilib.c @@ -87,13 +87,16 @@ find_scratch (void *src, void *dst, unsigned long srcsize, /* Decoding from ROM. */ if (((grub_addr_t) src & 0x10000000)) { - grub_decompressor_scratch = (char *) dst + dstsize; + grub_decompressor_scratch = (void *) ALIGN_UP((grub_addr_t) dst + dstsize, + 256); return; } #endif if ((char *) src + srcsize > (char *) dst + dstsize) - grub_decompressor_scratch = (char *) src + srcsize; + grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) src + srcsize, + 256); else - grub_decompressor_scratch = (char *) dst + dstsize; + grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) dst + dstsize, + 256); return; } From 9a0e5c815e76c48141d1e126682b1473036be669 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 22 Sep 2010 00:53:34 +0200 Subject: [PATCH 9/9] Fix bugs in asm code --- grub-core/boot/mips/startup_raw.S | 7 ++++--- grub-core/kern/mips/startup.S | 34 +++++++++++++++++++------------ 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index d810f2fb4..c41ce8257 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -67,10 +67,11 @@ argcont: #define DO_PARSE(str, reg) \ addiu $t2, $s0, (str-base);\ bal parsestr;\ + nop ;\ beq $v0, $zero, 1f;\ nop ;\ b 2f;\ - move reg, $v0; + move reg, $v0; \ 1: DO_PARSE (busclockstr, $s2) DO_PARSE (cpuclockstr, $s3) @@ -169,10 +170,10 @@ argdone: */ move $s6, $a3 - lui $sp, %hi(_start) + lui $sp, %hi(_start - 256) bal EXT_C(grub_decompress_core) - addiu $sp, $sp, %lo(_start) + addiu $sp, $sp, %lo(_start - 256) move $a0, $s1 move $a1, $s6 diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 97145b818..ae0e0b187 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -35,6 +35,10 @@ start: bal cont nop + . = _start + GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE +total_module_size: + .long 0 + . = _start + GRUB_KERNEL_MACHINE_PREFIX VARIABLE(grub_prefix) @@ -70,13 +74,13 @@ cont: #endif /* Move the modules out of BSS. */ - lui $t2, %hi(_end) - addiu $t2, %lo(_end) + lui $t2, %hi(__bss_start) + addiu $t2, %lo(__bss_start) lui $t1, %hi(_end) addiu $t1, %lo(_end) - addiu $t1, (GRUB_KERNEL_MACHINE_MOD_ALIGN-1) - li $t3, (GRUB_KERNEL_MACHINE_MOD_ALIGN-1) + addiu $t1, (GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) + li $t3, (GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) nor $t3, $t3, $0 and $t1, $t1, $t3 @@ -85,29 +89,33 @@ cont: /* Backward copy. */ add $t1, $t1, $t3 add $t2, $t2, $t3 - addiu $t1, $t1, 0xffff - addiu $t2, $t2, 0xffff + addiu $t1, $t1, -1 + addiu $t2, $t2, -1 /* $t2 is source. $t1 is destination. $t3 is size. */ modulesmovcont: + beq $t3, $0, modulesmovdone + nop lb $t4, 0($t2) sb $t4, 0($t1) + addiu $t2, $t2, -1 addiu $t1, $t1, -1 - addiu $t3, $t3, -1 - bne $t3, $0, modulesmovcont - addiu $t2, $t2, -1 - + b modulesmovcont + addiu $t3, $t3, -1 +modulesmovdone: + /* Clean BSS. */ lui $t1, %hi(__bss_start) - addiu $t1, %lo(__bss_start) + addiu $t1, $t1, %lo(__bss_start) lui $t2, %hi(_end) - addiu $t2, %lo(_end) + addiu $t2, $t2, %lo(_end) bsscont: sb $0,0($t1) + addiu $t1, $t1, 1 sltu $t3, $t1, $t2 bne $t3, $0, bsscont - addiu $t1, $t1, 1 + nop lui $t1, %hi(grub_main) addiu $t1, %lo(grub_main)