diff options
Diffstat (limited to 'arch/x86/boot/compressed')
-rw-r--r-- | arch/x86/boot/compressed/.gitignore | 3 | ||||
-rw-r--r-- | arch/x86/boot/compressed/Makefile | 54 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_32.S | 194 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_64.S | 169 | ||||
-rw-r--r-- | arch/x86/boot/compressed/misc.c | 12 | ||||
-rw-r--r-- | arch/x86/boot/compressed/mkpiggy.c | 97 | ||||
-rw-r--r-- | arch/x86/boot/compressed/vmlinux.lds.S (renamed from arch/x86/boot/compressed/vmlinux_64.lds) | 29 | ||||
-rw-r--r-- | arch/x86/boot/compressed/vmlinux.scr | 10 | ||||
-rw-r--r-- | arch/x86/boot/compressed/vmlinux_32.lds | 43 |
9 files changed, 324 insertions, 287 deletions
diff --git a/arch/x86/boot/compressed/.gitignore b/arch/x86/boot/compressed/.gitignore index 63eff3b04d01..4a46fab7162e 100644 --- a/arch/x86/boot/compressed/.gitignore +++ b/arch/x86/boot/compressed/.gitignore | |||
@@ -1,3 +1,6 @@ | |||
1 | relocs | 1 | relocs |
2 | vmlinux.bin.all | 2 | vmlinux.bin.all |
3 | vmlinux.relocs | 3 | vmlinux.relocs |
4 | vmlinux.lds | ||
5 | mkpiggy | ||
6 | piggy.S | ||
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 65551c9f8571..49c8a4c37d7c 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
@@ -19,7 +19,9 @@ KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ | |||
19 | LDFLAGS := -m elf_$(UTS_MACHINE) | 19 | LDFLAGS := -m elf_$(UTS_MACHINE) |
20 | LDFLAGS_vmlinux := -T | 20 | LDFLAGS_vmlinux := -T |
21 | 21 | ||
22 | $(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE | 22 | hostprogs-y := mkpiggy |
23 | |||
24 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE | ||
23 | $(call if_changed,ld) | 25 | $(call if_changed,ld) |
24 | @: | 26 | @: |
25 | 27 | ||
@@ -29,7 +31,7 @@ $(obj)/vmlinux.bin: vmlinux FORCE | |||
29 | 31 | ||
30 | 32 | ||
31 | targets += vmlinux.bin.all vmlinux.relocs relocs | 33 | targets += vmlinux.bin.all vmlinux.relocs relocs |
32 | hostprogs-$(CONFIG_X86_32) += relocs | 34 | hostprogs-$(CONFIG_X86_NEED_RELOCS) += relocs |
33 | 35 | ||
34 | quiet_cmd_relocs = RELOCS $@ | 36 | quiet_cmd_relocs = RELOCS $@ |
35 | cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $< | 37 | cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $< |
@@ -37,46 +39,22 @@ $(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE | |||
37 | $(call if_changed,relocs) | 39 | $(call if_changed,relocs) |
38 | 40 | ||
39 | vmlinux.bin.all-y := $(obj)/vmlinux.bin | 41 | vmlinux.bin.all-y := $(obj)/vmlinux.bin |
40 | vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs | 42 | vmlinux.bin.all-$(CONFIG_X86_NEED_RELOCS) += $(obj)/vmlinux.relocs |
41 | quiet_cmd_relocbin = BUILD $@ | ||
42 | cmd_relocbin = cat $(filter-out FORCE,$^) > $@ | ||
43 | $(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE | ||
44 | $(call if_changed,relocbin) | ||
45 | |||
46 | ifeq ($(CONFIG_X86_32),y) | ||
47 | 43 | ||
48 | ifdef CONFIG_RELOCATABLE | 44 | $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE |
49 | $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE | ||
50 | $(call if_changed,gzip) | ||
51 | $(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin.all FORCE | ||
52 | $(call if_changed,bzip2) | ||
53 | $(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin.all FORCE | ||
54 | $(call if_changed,lzma) | ||
55 | else | ||
56 | $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE | ||
57 | $(call if_changed,gzip) | 45 | $(call if_changed,gzip) |
58 | $(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE | 46 | $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE |
59 | $(call if_changed,bzip2) | 47 | $(call if_changed,bzip2) |
60 | $(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE | 48 | $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE |
61 | $(call if_changed,lzma) | 49 | $(call if_changed,lzma) |
62 | endif | ||
63 | LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T | ||
64 | 50 | ||
65 | else | 51 | suffix-$(CONFIG_KERNEL_GZIP) := gz |
52 | suffix-$(CONFIG_KERNEL_BZIP2) := bz2 | ||
53 | suffix-$(CONFIG_KERNEL_LZMA) := lzma | ||
66 | 54 | ||
67 | $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE | 55 | quiet_cmd_mkpiggy = MKPIGGY $@ |
68 | $(call if_changed,gzip) | 56 | cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false ) |
69 | $(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE | ||
70 | $(call if_changed,bzip2) | ||
71 | $(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE | ||
72 | $(call if_changed,lzma) | ||
73 | |||
74 | LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T | ||
75 | endif | ||
76 | 57 | ||
77 | suffix_$(CONFIG_KERNEL_GZIP) = gz | 58 | targets += piggy.S |
78 | suffix_$(CONFIG_KERNEL_BZIP2) = bz2 | 59 | $(obj)/piggy.S: $(obj)/vmlinux.bin.$(suffix-y) $(obj)/mkpiggy FORCE |
79 | suffix_$(CONFIG_KERNEL_LZMA) = lzma | 60 | $(call if_changed,mkpiggy) |
80 | |||
81 | $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix_y) FORCE | ||
82 | $(call if_changed,ld) | ||
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index 3a8a866fb2e2..75e4f001e706 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S | |||
@@ -12,16 +12,16 @@ | |||
12 | * the page directory. [According to comments etc elsewhere on a compressed | 12 | * the page directory. [According to comments etc elsewhere on a compressed |
13 | * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC] | 13 | * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC] |
14 | * | 14 | * |
15 | * Page 0 is deliberately kept safe, since System Management Mode code in | 15 | * Page 0 is deliberately kept safe, since System Management Mode code in |
16 | * laptops may need to access the BIOS data stored there. This is also | 16 | * laptops may need to access the BIOS data stored there. This is also |
17 | * useful for future device drivers that either access the BIOS via VM86 | 17 | * useful for future device drivers that either access the BIOS via VM86 |
18 | * mode. | 18 | * mode. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 | 22 | * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 |
23 | */ | 23 | */ |
24 | .text | 24 | .text |
25 | 25 | ||
26 | #include <linux/linkage.h> | 26 | #include <linux/linkage.h> |
27 | #include <asm/segment.h> | 27 | #include <asm/segment.h> |
@@ -29,161 +29,151 @@ | |||
29 | #include <asm/boot.h> | 29 | #include <asm/boot.h> |
30 | #include <asm/asm-offsets.h> | 30 | #include <asm/asm-offsets.h> |
31 | 31 | ||
32 | .section ".text.head","ax",@progbits | 32 | .section ".text.head","ax",@progbits |
33 | ENTRY(startup_32) | 33 | ENTRY(startup_32) |
34 | cld | 34 | cld |
35 | /* test KEEP_SEGMENTS flag to see if the bootloader is asking | 35 | /* |
36 | * us to not reload segments */ | 36 | * Test KEEP_SEGMENTS flag to see if the bootloader is asking |
37 | testb $(1<<6), BP_loadflags(%esi) | 37 | * us to not reload segments |
38 | jnz 1f | 38 | */ |
39 | testb $(1<<6), BP_loadflags(%esi) | ||
40 | jnz 1f | ||
39 | 41 | ||
40 | cli | 42 | cli |
41 | movl $(__BOOT_DS),%eax | 43 | movl $__BOOT_DS, %eax |
42 | movl %eax,%ds | 44 | movl %eax, %ds |
43 | movl %eax,%es | 45 | movl %eax, %es |
44 | movl %eax,%fs | 46 | movl %eax, %fs |
45 | movl %eax,%gs | 47 | movl %eax, %gs |
46 | movl %eax,%ss | 48 | movl %eax, %ss |
47 | 1: | 49 | 1: |
48 | 50 | ||
49 | /* Calculate the delta between where we were compiled to run | 51 | /* |
52 | * Calculate the delta between where we were compiled to run | ||
50 | * at and where we were actually loaded at. This can only be done | 53 | * at and where we were actually loaded at. This can only be done |
51 | * with a short local call on x86. Nothing else will tell us what | 54 | * with a short local call on x86. Nothing else will tell us what |
52 | * address we are running at. The reserved chunk of the real-mode | 55 | * address we are running at. The reserved chunk of the real-mode |
53 | * data at 0x1e4 (defined as a scratch field) are used as the stack | 56 | * data at 0x1e4 (defined as a scratch field) are used as the stack |
54 | * for this calculation. Only 4 bytes are needed. | 57 | * for this calculation. Only 4 bytes are needed. |
55 | */ | 58 | */ |
56 | leal (0x1e4+4)(%esi), %esp | 59 | leal (BP_scratch+4)(%esi), %esp |
57 | call 1f | 60 | call 1f |
58 | 1: popl %ebp | 61 | 1: popl %ebp |
59 | subl $1b, %ebp | 62 | subl $1b, %ebp |
60 | 63 | ||
61 | /* %ebp contains the address we are loaded at by the boot loader and %ebx | 64 | /* |
65 | * %ebp contains the address we are loaded at by the boot loader and %ebx | ||
62 | * contains the address where we should move the kernel image temporarily | 66 | * contains the address where we should move the kernel image temporarily |
63 | * for safe in-place decompression. | 67 | * for safe in-place decompression. |
64 | */ | 68 | */ |
65 | 69 | ||
66 | #ifdef CONFIG_RELOCATABLE | 70 | #ifdef CONFIG_RELOCATABLE |
67 | movl %ebp, %ebx | 71 | movl %ebp, %ebx |
68 | addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebx | 72 | movl BP_kernel_alignment(%esi), %eax |
69 | andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx | 73 | decl %eax |
74 | addl %eax, %ebx | ||
75 | notl %eax | ||
76 | andl %eax, %ebx | ||
70 | #else | 77 | #else |
71 | movl $LOAD_PHYSICAL_ADDR, %ebx | 78 | movl $LOAD_PHYSICAL_ADDR, %ebx |
72 | #endif | 79 | #endif |
73 | 80 | ||
74 | /* Replace the compressed data size with the uncompressed size */ | 81 | /* Target address to relocate to for decompression */ |
75 | subl input_len(%ebp), %ebx | 82 | addl $z_extract_offset, %ebx |
76 | movl output_len(%ebp), %eax | 83 | |
77 | addl %eax, %ebx | 84 | /* Set up the stack */ |
78 | /* Add 8 bytes for every 32K input block */ | 85 | leal boot_stack_end(%ebx), %esp |
79 | shrl $12, %eax | 86 | |
80 | addl %eax, %ebx | 87 | /* Zero EFLAGS */ |
81 | /* Add 32K + 18 bytes of extra slack */ | 88 | pushl $0 |
82 | addl $(32768 + 18), %ebx | 89 | popfl |
83 | /* Align on a 4K boundary */ | 90 | |
84 | addl $4095, %ebx | 91 | /* |
85 | andl $~4095, %ebx | 92 | * Copy the compressed kernel to the end of our buffer |
86 | |||
87 | /* Copy the compressed kernel to the end of our buffer | ||
88 | * where decompression in place becomes safe. | 93 | * where decompression in place becomes safe. |
89 | */ | 94 | */ |
90 | pushl %esi | 95 | pushl %esi |
91 | leal _end(%ebp), %esi | 96 | leal (_bss-4)(%ebp), %esi |
92 | leal _end(%ebx), %edi | 97 | leal (_bss-4)(%ebx), %edi |
93 | movl $(_end - startup_32), %ecx | 98 | movl $(_bss - startup_32), %ecx |
99 | shrl $2, %ecx | ||
94 | std | 100 | std |
95 | rep | 101 | rep movsl |
96 | movsb | ||
97 | cld | 102 | cld |
98 | popl %esi | 103 | popl %esi |
99 | |||
100 | /* Compute the kernel start address. | ||
101 | */ | ||
102 | #ifdef CONFIG_RELOCATABLE | ||
103 | addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebp | ||
104 | andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp | ||
105 | #else | ||
106 | movl $LOAD_PHYSICAL_ADDR, %ebp | ||
107 | #endif | ||
108 | 104 | ||
109 | /* | 105 | /* |
110 | * Jump to the relocated address. | 106 | * Jump to the relocated address. |
111 | */ | 107 | */ |
112 | leal relocated(%ebx), %eax | 108 | leal relocated(%ebx), %eax |
113 | jmp *%eax | 109 | jmp *%eax |
114 | ENDPROC(startup_32) | 110 | ENDPROC(startup_32) |
115 | 111 | ||
116 | .section ".text" | 112 | .text |
117 | relocated: | 113 | relocated: |
118 | 114 | ||
119 | /* | 115 | /* |
120 | * Clear BSS | 116 | * Clear BSS (stack is currently empty) |
121 | */ | ||
122 | xorl %eax,%eax | ||
123 | leal _edata(%ebx),%edi | ||
124 | leal _end(%ebx), %ecx | ||
125 | subl %edi,%ecx | ||
126 | cld | ||
127 | rep | ||
128 | stosb | ||
129 | |||
130 | /* | ||
131 | * Setup the stack for the decompressor | ||
132 | */ | 117 | */ |
133 | leal boot_stack_end(%ebx), %esp | 118 | xorl %eax, %eax |
119 | leal _bss(%ebx), %edi | ||
120 | leal _ebss(%ebx), %ecx | ||
121 | subl %edi, %ecx | ||
122 | shrl $2, %ecx | ||
123 | rep stosl | ||
134 | 124 | ||
135 | /* | 125 | /* |
136 | * Do the decompression, and jump to the new kernel.. | 126 | * Do the decompression, and jump to the new kernel.. |
137 | */ | 127 | */ |
138 | movl output_len(%ebx), %eax | 128 | leal z_extract_offset_negative(%ebx), %ebp |
139 | pushl %eax | 129 | /* push arguments for decompress_kernel: */ |
140 | # push arguments for decompress_kernel: | 130 | pushl %ebp /* output address */ |
141 | pushl %ebp # output address | 131 | pushl $z_input_len /* input_len */ |
142 | movl input_len(%ebx), %eax | 132 | leal input_data(%ebx), %eax |
143 | pushl %eax # input_len | 133 | pushl %eax /* input_data */ |
144 | leal input_data(%ebx), %eax | 134 | leal boot_heap(%ebx), %eax |
145 | pushl %eax # input_data | 135 | pushl %eax /* heap area */ |
146 | leal boot_heap(%ebx), %eax | 136 | pushl %esi /* real mode pointer */ |
147 | pushl %eax # heap area | 137 | call decompress_kernel |
148 | pushl %esi # real mode pointer | 138 | addl $20, %esp |
149 | call decompress_kernel | ||
150 | addl $20, %esp | ||
151 | popl %ecx | ||
152 | 139 | ||
153 | #if CONFIG_RELOCATABLE | 140 | #if CONFIG_RELOCATABLE |
154 | /* Find the address of the relocations. | 141 | /* |
142 | * Find the address of the relocations. | ||
155 | */ | 143 | */ |
156 | movl %ebp, %edi | 144 | leal z_output_len(%ebp), %edi |
157 | addl %ecx, %edi | ||
158 | 145 | ||
159 | /* Calculate the delta between where vmlinux was compiled to run | 146 | /* |
147 | * Calculate the delta between where vmlinux was compiled to run | ||
160 | * and where it was actually loaded. | 148 | * and where it was actually loaded. |
161 | */ | 149 | */ |
162 | movl %ebp, %ebx | 150 | movl %ebp, %ebx |
163 | subl $LOAD_PHYSICAL_ADDR, %ebx | 151 | subl $LOAD_PHYSICAL_ADDR, %ebx |
164 | jz 2f /* Nothing to be done if loaded at compiled addr. */ | 152 | jz 2f /* Nothing to be done if loaded at compiled addr. */ |
165 | /* | 153 | /* |
166 | * Process relocations. | 154 | * Process relocations. |
167 | */ | 155 | */ |
168 | 156 | ||
169 | 1: subl $4, %edi | 157 | 1: subl $4, %edi |
170 | movl 0(%edi), %ecx | 158 | movl (%edi), %ecx |
171 | testl %ecx, %ecx | 159 | testl %ecx, %ecx |
172 | jz 2f | 160 | jz 2f |
173 | addl %ebx, -__PAGE_OFFSET(%ebx, %ecx) | 161 | addl %ebx, -__PAGE_OFFSET(%ebx, %ecx) |
174 | jmp 1b | 162 | jmp 1b |
175 | 2: | 163 | 2: |
176 | #endif | 164 | #endif |
177 | 165 | ||
178 | /* | 166 | /* |
179 | * Jump to the decompressed kernel. | 167 | * Jump to the decompressed kernel. |
180 | */ | 168 | */ |
181 | xorl %ebx,%ebx | 169 | xorl %ebx, %ebx |
182 | jmp *%ebp | 170 | jmp *%ebp |
183 | 171 | ||
184 | .bss | 172 | /* |
185 | /* Stack and heap for uncompression */ | 173 | * Stack and heap for uncompression |
186 | .balign 4 | 174 | */ |
175 | .bss | ||
176 | .balign 4 | ||
187 | boot_heap: | 177 | boot_heap: |
188 | .fill BOOT_HEAP_SIZE, 1, 0 | 178 | .fill BOOT_HEAP_SIZE, 1, 0 |
189 | boot_stack: | 179 | boot_stack: |
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index ed4a82948002..f62c284db9eb 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S | |||
@@ -21,8 +21,8 @@ | |||
21 | /* | 21 | /* |
22 | * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 | 22 | * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 |
23 | */ | 23 | */ |
24 | .code32 | 24 | .code32 |
25 | .text | 25 | .text |
26 | 26 | ||
27 | #include <linux/linkage.h> | 27 | #include <linux/linkage.h> |
28 | #include <asm/segment.h> | 28 | #include <asm/segment.h> |
@@ -33,12 +33,14 @@ | |||
33 | #include <asm/processor-flags.h> | 33 | #include <asm/processor-flags.h> |
34 | #include <asm/asm-offsets.h> | 34 | #include <asm/asm-offsets.h> |
35 | 35 | ||
36 | .section ".text.head" | 36 | .section ".text.head" |
37 | .code32 | 37 | .code32 |
38 | ENTRY(startup_32) | 38 | ENTRY(startup_32) |
39 | cld | 39 | cld |
40 | /* test KEEP_SEGMENTS flag to see if the bootloader is asking | 40 | /* |
41 | * us to not reload segments */ | 41 | * Test KEEP_SEGMENTS flag to see if the bootloader is asking |
42 | * us to not reload segments | ||
43 | */ | ||
42 | testb $(1<<6), BP_loadflags(%esi) | 44 | testb $(1<<6), BP_loadflags(%esi) |
43 | jnz 1f | 45 | jnz 1f |
44 | 46 | ||
@@ -49,14 +51,15 @@ ENTRY(startup_32) | |||
49 | movl %eax, %ss | 51 | movl %eax, %ss |
50 | 1: | 52 | 1: |
51 | 53 | ||
52 | /* Calculate the delta between where we were compiled to run | 54 | /* |
55 | * Calculate the delta between where we were compiled to run | ||
53 | * at and where we were actually loaded at. This can only be done | 56 | * at and where we were actually loaded at. This can only be done |
54 | * with a short local call on x86. Nothing else will tell us what | 57 | * with a short local call on x86. Nothing else will tell us what |
55 | * address we are running at. The reserved chunk of the real-mode | 58 | * address we are running at. The reserved chunk of the real-mode |
56 | * data at 0x1e4 (defined as a scratch field) are used as the stack | 59 | * data at 0x1e4 (defined as a scratch field) are used as the stack |
57 | * for this calculation. Only 4 bytes are needed. | 60 | * for this calculation. Only 4 bytes are needed. |
58 | */ | 61 | */ |
59 | leal (0x1e4+4)(%esi), %esp | 62 | leal (BP_scratch+4)(%esi), %esp |
60 | call 1f | 63 | call 1f |
61 | 1: popl %ebp | 64 | 1: popl %ebp |
62 | subl $1b, %ebp | 65 | subl $1b, %ebp |
@@ -70,32 +73,28 @@ ENTRY(startup_32) | |||
70 | testl %eax, %eax | 73 | testl %eax, %eax |
71 | jnz no_longmode | 74 | jnz no_longmode |
72 | 75 | ||
73 | /* Compute the delta between where we were compiled to run at | 76 | /* |
77 | * Compute the delta between where we were compiled to run at | ||
74 | * and where the code will actually run at. | 78 | * and where the code will actually run at. |
75 | */ | 79 | * |
76 | /* %ebp contains the address we are loaded at by the boot loader and %ebx | 80 | * %ebp contains the address we are loaded at by the boot loader and %ebx |
77 | * contains the address where we should move the kernel image temporarily | 81 | * contains the address where we should move the kernel image temporarily |
78 | * for safe in-place decompression. | 82 | * for safe in-place decompression. |
79 | */ | 83 | */ |
80 | 84 | ||
81 | #ifdef CONFIG_RELOCATABLE | 85 | #ifdef CONFIG_RELOCATABLE |
82 | movl %ebp, %ebx | 86 | movl %ebp, %ebx |
83 | addl $(PMD_PAGE_SIZE -1), %ebx | 87 | movl BP_kernel_alignment(%esi), %eax |
84 | andl $PMD_PAGE_MASK, %ebx | 88 | decl %eax |
89 | addl %eax, %ebx | ||
90 | notl %eax | ||
91 | andl %eax, %ebx | ||
85 | #else | 92 | #else |
86 | movl $CONFIG_PHYSICAL_START, %ebx | 93 | movl $LOAD_PHYSICAL_ADDR, %ebx |
87 | #endif | 94 | #endif |
88 | 95 | ||
89 | /* Replace the compressed data size with the uncompressed size */ | 96 | /* Target address to relocate to for decompression */ |
90 | subl input_len(%ebp), %ebx | 97 | addl $z_extract_offset, %ebx |
91 | movl output_len(%ebp), %eax | ||
92 | addl %eax, %ebx | ||
93 | /* Add 8 bytes for every 32K input block */ | ||
94 | shrl $12, %eax | ||
95 | addl %eax, %ebx | ||
96 | /* Add 32K + 18 bytes of extra slack and align on a 4K boundary */ | ||
97 | addl $(32768 + 18 + 4095), %ebx | ||
98 | andl $~4095, %ebx | ||
99 | 98 | ||
100 | /* | 99 | /* |
101 | * Prepare for entering 64 bit mode | 100 | * Prepare for entering 64 bit mode |
@@ -114,7 +113,7 @@ ENTRY(startup_32) | |||
114 | /* | 113 | /* |
115 | * Build early 4G boot pagetable | 114 | * Build early 4G boot pagetable |
116 | */ | 115 | */ |
117 | /* Initialize Page tables to 0*/ | 116 | /* Initialize Page tables to 0 */ |
118 | leal pgtable(%ebx), %edi | 117 | leal pgtable(%ebx), %edi |
119 | xorl %eax, %eax | 118 | xorl %eax, %eax |
120 | movl $((4096*6)/4), %ecx | 119 | movl $((4096*6)/4), %ecx |
@@ -155,7 +154,8 @@ ENTRY(startup_32) | |||
155 | btsl $_EFER_LME, %eax | 154 | btsl $_EFER_LME, %eax |
156 | wrmsr | 155 | wrmsr |
157 | 156 | ||
158 | /* Setup for the jump to 64bit mode | 157 | /* |
158 | * Setup for the jump to 64bit mode | ||
159 | * | 159 | * |
160 | * When the jump is performend we will be in long mode but | 160 | * When the jump is performend we will be in long mode but |
161 | * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1 | 161 | * in 32bit compatibility mode with EFER.LME = 1, CS.L = 0, CS.D = 1 |
@@ -184,7 +184,8 @@ no_longmode: | |||
184 | 184 | ||
185 | #include "../../kernel/verify_cpu_64.S" | 185 | #include "../../kernel/verify_cpu_64.S" |
186 | 186 | ||
187 | /* Be careful here startup_64 needs to be at a predictable | 187 | /* |
188 | * Be careful here startup_64 needs to be at a predictable | ||
188 | * address so I can export it in an ELF header. Bootloaders | 189 | * address so I can export it in an ELF header. Bootloaders |
189 | * should look at the ELF header to find this address, as | 190 | * should look at the ELF header to find this address, as |
190 | * it may change in the future. | 191 | * it may change in the future. |
@@ -192,7 +193,8 @@ no_longmode: | |||
192 | .code64 | 193 | .code64 |
193 | .org 0x200 | 194 | .org 0x200 |
194 | ENTRY(startup_64) | 195 | ENTRY(startup_64) |
195 | /* We come here either from startup_32 or directly from a | 196 | /* |
197 | * We come here either from startup_32 or directly from a | ||
196 | * 64bit bootloader. If we come here from a bootloader we depend on | 198 | * 64bit bootloader. If we come here from a bootloader we depend on |
197 | * an identity mapped page table being provied that maps our | 199 | * an identity mapped page table being provied that maps our |
198 | * entire text+data+bss and hopefully all of memory. | 200 | * entire text+data+bss and hopefully all of memory. |
@@ -209,50 +211,54 @@ ENTRY(startup_64) | |||
209 | movl $0x20, %eax | 211 | movl $0x20, %eax |
210 | ltr %ax | 212 | ltr %ax |
211 | 213 | ||
212 | /* Compute the decompressed kernel start address. It is where | 214 | /* |
215 | * Compute the decompressed kernel start address. It is where | ||
213 | * we were loaded at aligned to a 2M boundary. %rbp contains the | 216 | * we were loaded at aligned to a 2M boundary. %rbp contains the |
214 | * decompressed kernel start address. | 217 | * decompressed kernel start address. |
215 | * | 218 | * |
216 | * If it is a relocatable kernel then decompress and run the kernel | 219 | * If it is a relocatable kernel then decompress and run the kernel |
217 | * from load address aligned to 2MB addr, otherwise decompress and | 220 | * from load address aligned to 2MB addr, otherwise decompress and |
218 | * run the kernel from CONFIG_PHYSICAL_START | 221 | * run the kernel from LOAD_PHYSICAL_ADDR |
222 | * | ||
223 | * We cannot rely on the calculation done in 32-bit mode, since we | ||
224 | * may have been invoked via the 64-bit entry point. | ||
219 | */ | 225 | */ |
220 | 226 | ||
221 | /* Start with the delta to where the kernel will run at. */ | 227 | /* Start with the delta to where the kernel will run at. */ |
222 | #ifdef CONFIG_RELOCATABLE | 228 | #ifdef CONFIG_RELOCATABLE |
223 | leaq startup_32(%rip) /* - $startup_32 */, %rbp | 229 | leaq startup_32(%rip) /* - $startup_32 */, %rbp |
224 | addq $(PMD_PAGE_SIZE - 1), %rbp | 230 | movl BP_kernel_alignment(%rsi), %eax |
225 | andq $PMD_PAGE_MASK, %rbp | 231 | decl %eax |
226 | movq %rbp, %rbx | 232 | addq %rax, %rbp |
233 | notq %rax | ||
234 | andq %rax, %rbp | ||
227 | #else | 235 | #else |
228 | movq $CONFIG_PHYSICAL_START, %rbp | 236 | movq $LOAD_PHYSICAL_ADDR, %rbp |
229 | movq %rbp, %rbx | ||
230 | #endif | 237 | #endif |
231 | 238 | ||
232 | /* Replace the compressed data size with the uncompressed size */ | 239 | /* Target address to relocate to for decompression */ |
233 | movl input_len(%rip), %eax | 240 | leaq z_extract_offset(%rbp), %rbx |
234 | subq %rax, %rbx | 241 | |
235 | movl output_len(%rip), %eax | 242 | /* Set up the stack */ |
236 | addq %rax, %rbx | 243 | leaq boot_stack_end(%rbx), %rsp |
237 | /* Add 8 bytes for every 32K input block */ | 244 | |
238 | shrq $12, %rax | 245 | /* Zero EFLAGS */ |
239 | addq %rax, %rbx | 246 | pushq $0 |
240 | /* Add 32K + 18 bytes of extra slack and align on a 4K boundary */ | 247 | popfq |
241 | addq $(32768 + 18 + 4095), %rbx | 248 | |
242 | andq $~4095, %rbx | 249 | /* |
243 | 250 | * Copy the compressed kernel to the end of our buffer | |
244 | /* Copy the compressed kernel to the end of our buffer | ||
245 | * where decompression in place becomes safe. | 251 | * where decompression in place becomes safe. |
246 | */ | 252 | */ |
247 | leaq _end_before_pgt(%rip), %r8 | 253 | pushq %rsi |
248 | leaq _end_before_pgt(%rbx), %r9 | 254 | leaq (_bss-8)(%rip), %rsi |
249 | movq $_end_before_pgt /* - $startup_32 */, %rcx | 255 | leaq (_bss-8)(%rbx), %rdi |
250 | 1: subq $8, %r8 | 256 | movq $_bss /* - $startup_32 */, %rcx |
251 | subq $8, %r9 | 257 | shrq $3, %rcx |
252 | movq 0(%r8), %rax | 258 | std |
253 | movq %rax, 0(%r9) | 259 | rep movsq |
254 | subq $8, %rcx | 260 | cld |
255 | jnz 1b | 261 | popq %rsi |
256 | 262 | ||
257 | /* | 263 | /* |
258 | * Jump to the relocated address. | 264 | * Jump to the relocated address. |
@@ -260,37 +266,28 @@ ENTRY(startup_64) | |||
260 | leaq relocated(%rbx), %rax | 266 | leaq relocated(%rbx), %rax |
261 | jmp *%rax | 267 | jmp *%rax |
262 | 268 | ||
263 | .section ".text" | 269 | .text |
264 | relocated: | 270 | relocated: |
265 | 271 | ||
266 | /* | 272 | /* |
267 | * Clear BSS | 273 | * Clear BSS (stack is currently empty) |
268 | */ | 274 | */ |
269 | xorq %rax, %rax | 275 | xorl %eax, %eax |
270 | leaq _edata(%rbx), %rdi | 276 | leaq _bss(%rip), %rdi |
271 | leaq _end_before_pgt(%rbx), %rcx | 277 | leaq _ebss(%rip), %rcx |
272 | subq %rdi, %rcx | 278 | subq %rdi, %rcx |
273 | cld | 279 | shrq $3, %rcx |
274 | rep | 280 | rep stosq |
275 | stosb | ||
276 | |||
277 | /* Setup the stack */ | ||
278 | leaq boot_stack_end(%rip), %rsp | ||
279 | |||
280 | /* zero EFLAGS after setting rsp */ | ||
281 | pushq $0 | ||
282 | popfq | ||
283 | 281 | ||
284 | /* | 282 | /* |
285 | * Do the decompression, and jump to the new kernel.. | 283 | * Do the decompression, and jump to the new kernel.. |
286 | */ | 284 | */ |
287 | pushq %rsi # Save the real mode argument | 285 | pushq %rsi /* Save the real mode argument */ |
288 | movq %rsi, %rdi # real mode address | 286 | movq %rsi, %rdi /* real mode address */ |
289 | leaq boot_heap(%rip), %rsi # malloc area for uncompression | 287 | leaq boot_heap(%rip), %rsi /* malloc area for uncompression */ |
290 | leaq input_data(%rip), %rdx # input_data | 288 | leaq input_data(%rip), %rdx /* input_data */ |
291 | movl input_len(%rip), %eax | 289 | movl $z_input_len, %ecx /* input_len */ |
292 | movq %rax, %rcx # input_len | 290 | movq %rbp, %r8 /* output target address */ |
293 | movq %rbp, %r8 # output | ||
294 | call decompress_kernel | 291 | call decompress_kernel |
295 | popq %rsi | 292 | popq %rsi |
296 | 293 | ||
@@ -311,11 +308,21 @@ gdt: | |||
311 | .quad 0x0000000000000000 /* TS continued */ | 308 | .quad 0x0000000000000000 /* TS continued */ |
312 | gdt_end: | 309 | gdt_end: |
313 | 310 | ||
314 | .bss | 311 | /* |
315 | /* Stack and heap for uncompression */ | 312 | * Stack and heap for uncompression |
316 | .balign 4 | 313 | */ |
314 | .bss | ||
315 | .balign 4 | ||
317 | boot_heap: | 316 | boot_heap: |
318 | .fill BOOT_HEAP_SIZE, 1, 0 | 317 | .fill BOOT_HEAP_SIZE, 1, 0 |
319 | boot_stack: | 318 | boot_stack: |
320 | .fill BOOT_STACK_SIZE, 1, 0 | 319 | .fill BOOT_STACK_SIZE, 1, 0 |
321 | boot_stack_end: | 320 | boot_stack_end: |
321 | |||
322 | /* | ||
323 | * Space for page tables (not in .bss so not zeroed) | ||
324 | */ | ||
325 | .section ".pgtable","a",@nobits | ||
326 | .balign 4096 | ||
327 | pgtable: | ||
328 | .fill 6*4096, 1, 0 | ||
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index e45be73684ff..842b2a36174a 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
@@ -325,21 +325,19 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, | |||
325 | free_mem_ptr = heap; /* Heap */ | 325 | free_mem_ptr = heap; /* Heap */ |
326 | free_mem_end_ptr = heap + BOOT_HEAP_SIZE; | 326 | free_mem_end_ptr = heap + BOOT_HEAP_SIZE; |
327 | 327 | ||
328 | if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) | ||
329 | error("Destination address inappropriately aligned"); | ||
328 | #ifdef CONFIG_X86_64 | 330 | #ifdef CONFIG_X86_64 |
329 | if ((unsigned long)output & (__KERNEL_ALIGN - 1)) | 331 | if (heap > 0x3fffffffffffUL) |
330 | error("Destination address not 2M aligned"); | ||
331 | if ((unsigned long)output >= 0xffffffffffUL) | ||
332 | error("Destination address too large"); | 332 | error("Destination address too large"); |
333 | #else | 333 | #else |
334 | if ((u32)output & (CONFIG_PHYSICAL_ALIGN - 1)) | ||
335 | error("Destination address not CONFIG_PHYSICAL_ALIGN aligned"); | ||
336 | if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff)) | 334 | if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff)) |
337 | error("Destination address too large"); | 335 | error("Destination address too large"); |
336 | #endif | ||
338 | #ifndef CONFIG_RELOCATABLE | 337 | #ifndef CONFIG_RELOCATABLE |
339 | if ((u32)output != LOAD_PHYSICAL_ADDR) | 338 | if ((unsigned long)output != LOAD_PHYSICAL_ADDR) |
340 | error("Wrong destination address"); | 339 | error("Wrong destination address"); |
341 | #endif | 340 | #endif |
342 | #endif | ||
343 | 341 | ||
344 | if (!quiet) | 342 | if (!quiet) |
345 | putstr("\nDecompressing Linux... "); | 343 | putstr("\nDecompressing Linux... "); |
diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c new file mode 100644 index 000000000000..bcbd36c41432 --- /dev/null +++ b/arch/x86/boot/compressed/mkpiggy.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* ----------------------------------------------------------------------- * | ||
2 | * | ||
3 | * Copyright (C) 2009 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version | ||
7 | * 2 as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
17 | * 02110-1301, USA. | ||
18 | * | ||
19 | * H. Peter Anvin <hpa@linux.intel.com> | ||
20 | * | ||
21 | * ----------------------------------------------------------------------- */ | ||
22 | |||
23 | /* | ||
24 | * Compute the desired load offset from a compressed program; outputs | ||
25 | * a small assembly wrapper with the appropriate symbols defined. | ||
26 | */ | ||
27 | |||
28 | #include <stdlib.h> | ||
29 | #include <stdio.h> | ||
30 | #include <string.h> | ||
31 | #include <inttypes.h> | ||
32 | |||
33 | static uint32_t getle32(const void *p) | ||
34 | { | ||
35 | const uint8_t *cp = p; | ||
36 | |||
37 | return (uint32_t)cp[0] + ((uint32_t)cp[1] << 8) + | ||
38 | ((uint32_t)cp[2] << 16) + ((uint32_t)cp[3] << 24); | ||
39 | } | ||
40 | |||
41 | int main(int argc, char *argv[]) | ||
42 | { | ||
43 | uint32_t olen; | ||
44 | long ilen; | ||
45 | unsigned long offs; | ||
46 | FILE *f; | ||
47 | |||
48 | if (argc < 2) { | ||
49 | fprintf(stderr, "Usage: %s compressed_file\n", argv[0]); | ||
50 | return 1; | ||
51 | } | ||
52 | |||
53 | /* Get the information for the compressed kernel image first */ | ||
54 | |||
55 | f = fopen(argv[1], "r"); | ||
56 | if (!f) { | ||
57 | perror(argv[1]); | ||
58 | return 1; | ||
59 | } | ||
60 | |||
61 | |||
62 | if (fseek(f, -4L, SEEK_END)) { | ||
63 | perror(argv[1]); | ||
64 | } | ||
65 | fread(&olen, sizeof olen, 1, f); | ||
66 | ilen = ftell(f); | ||
67 | olen = getle32(&olen); | ||
68 | fclose(f); | ||
69 | |||
70 | /* | ||
71 | * Now we have the input (compressed) and output (uncompressed) | ||
72 | * sizes, compute the necessary decompression offset... | ||
73 | */ | ||
74 | |||
75 | offs = (olen > ilen) ? olen - ilen : 0; | ||
76 | offs += olen >> 12; /* Add 8 bytes for each 32K block */ | ||
77 | offs += 32*1024 + 18; /* Add 32K + 18 bytes slack */ | ||
78 | offs = (offs+4095) & ~4095; /* Round to a 4K boundary */ | ||
79 | |||
80 | printf(".section \".rodata.compressed\",\"a\",@progbits\n"); | ||
81 | printf(".globl z_input_len\n"); | ||
82 | printf("z_input_len = %lu\n", ilen); | ||
83 | printf(".globl z_output_len\n"); | ||
84 | printf("z_output_len = %lu\n", (unsigned long)olen); | ||
85 | printf(".globl z_extract_offset\n"); | ||
86 | printf("z_extract_offset = 0x%lx\n", offs); | ||
87 | /* z_extract_offset_negative allows simplification of head_32.S */ | ||
88 | printf(".globl z_extract_offset_negative\n"); | ||
89 | printf("z_extract_offset_negative = -0x%lx\n", offs); | ||
90 | |||
91 | printf(".globl input_data, input_data_end\n"); | ||
92 | printf("input_data:\n"); | ||
93 | printf(".incbin \"%s\"\n", argv[1]); | ||
94 | printf("input_data_end:\n"); | ||
95 | |||
96 | return 0; | ||
97 | } | ||
diff --git a/arch/x86/boot/compressed/vmlinux_64.lds b/arch/x86/boot/compressed/vmlinux.lds.S index bef1ac891bce..cc353e1b3ffd 100644 --- a/arch/x86/boot/compressed/vmlinux_64.lds +++ b/arch/x86/boot/compressed/vmlinux.lds.S | |||
@@ -1,6 +1,17 @@ | |||
1 | OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") | 1 | OUTPUT_FORMAT(CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT, CONFIG_OUTPUT_FORMAT) |
2 | |||
3 | #undef i386 | ||
4 | |||
5 | #include <asm/page_types.h> | ||
6 | |||
7 | #ifdef CONFIG_X86_64 | ||
2 | OUTPUT_ARCH(i386:x86-64) | 8 | OUTPUT_ARCH(i386:x86-64) |
3 | ENTRY(startup_64) | 9 | ENTRY(startup_64) |
10 | #else | ||
11 | OUTPUT_ARCH(i386) | ||
12 | ENTRY(startup_32) | ||
13 | #endif | ||
14 | |||
4 | SECTIONS | 15 | SECTIONS |
5 | { | 16 | { |
6 | /* Be careful parts of head_64.S assume startup_32 is at | 17 | /* Be careful parts of head_64.S assume startup_32 is at |
@@ -33,16 +44,22 @@ SECTIONS | |||
33 | *(.data.*) | 44 | *(.data.*) |
34 | _edata = . ; | 45 | _edata = . ; |
35 | } | 46 | } |
47 | . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); | ||
36 | .bss : { | 48 | .bss : { |
37 | _bss = . ; | 49 | _bss = . ; |
38 | *(.bss) | 50 | *(.bss) |
39 | *(.bss.*) | 51 | *(.bss.*) |
40 | *(COMMON) | 52 | *(COMMON) |
41 | . = ALIGN(8); | 53 | . = ALIGN(8); /* For convenience during zeroing */ |
42 | _end_before_pgt = . ; | ||
43 | . = ALIGN(4096); | ||
44 | pgtable = . ; | ||
45 | . = . + 4096 * 6; | ||
46 | _ebss = .; | 54 | _ebss = .; |
47 | } | 55 | } |
56 | #ifdef CONFIG_X86_64 | ||
57 | . = ALIGN(PAGE_SIZE); | ||
58 | .pgtable : { | ||
59 | _pgtable = . ; | ||
60 | *(.pgtable) | ||
61 | _epgtable = . ; | ||
62 | } | ||
63 | #endif | ||
64 | _end = .; | ||
48 | } | 65 | } |
diff --git a/arch/x86/boot/compressed/vmlinux.scr b/arch/x86/boot/compressed/vmlinux.scr deleted file mode 100644 index f02382ae5c48..000000000000 --- a/arch/x86/boot/compressed/vmlinux.scr +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | SECTIONS | ||
2 | { | ||
3 | .rodata.compressed : { | ||
4 | input_len = .; | ||
5 | LONG(input_data_end - input_data) input_data = .; | ||
6 | *(.data) | ||
7 | output_len = . - 4; | ||
8 | input_data_end = .; | ||
9 | } | ||
10 | } | ||
diff --git a/arch/x86/boot/compressed/vmlinux_32.lds b/arch/x86/boot/compressed/vmlinux_32.lds deleted file mode 100644 index bb3c48379c40..000000000000 --- a/arch/x86/boot/compressed/vmlinux_32.lds +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") | ||
2 | OUTPUT_ARCH(i386) | ||
3 | ENTRY(startup_32) | ||
4 | SECTIONS | ||
5 | { | ||
6 | /* Be careful parts of head_32.S assume startup_32 is at | ||
7 | * address 0. | ||
8 | */ | ||
9 | . = 0; | ||
10 | .text.head : { | ||
11 | _head = . ; | ||
12 | *(.text.head) | ||
13 | _ehead = . ; | ||
14 | } | ||
15 | .rodata.compressed : { | ||
16 | *(.rodata.compressed) | ||
17 | } | ||
18 | .text : { | ||
19 | _text = .; /* Text */ | ||
20 | *(.text) | ||
21 | *(.text.*) | ||
22 | _etext = . ; | ||
23 | } | ||
24 | .rodata : { | ||
25 | _rodata = . ; | ||
26 | *(.rodata) /* read-only data */ | ||
27 | *(.rodata.*) | ||
28 | _erodata = . ; | ||
29 | } | ||
30 | .data : { | ||
31 | _data = . ; | ||
32 | *(.data) | ||
33 | *(.data.*) | ||
34 | _edata = . ; | ||
35 | } | ||
36 | .bss : { | ||
37 | _bss = . ; | ||
38 | *(.bss) | ||
39 | *(.bss.*) | ||
40 | *(COMMON) | ||
41 | _end = . ; | ||
42 | } | ||
43 | } | ||