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: