diff options
Diffstat (limited to 'arch/x86/boot/compressed/misc.c')
-rw-r--r-- | arch/x86/boot/compressed/misc.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 30dd59a9f0b4..dcc1c536cc21 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
@@ -260,7 +260,7 @@ static void handle_relocations(void *output, unsigned long output_len) | |||
260 | 260 | ||
261 | /* | 261 | /* |
262 | * Process relocations: 32 bit relocations first then 64 bit after. | 262 | * Process relocations: 32 bit relocations first then 64 bit after. |
263 | * Two sets of binary relocations are added to the end of the kernel | 263 | * Three sets of binary relocations are added to the end of the kernel |
264 | * before compression. Each relocation table entry is the kernel | 264 | * before compression. Each relocation table entry is the kernel |
265 | * address of the location which needs to be updated stored as a | 265 | * address of the location which needs to be updated stored as a |
266 | * 32-bit value which is sign extended to 64 bits. | 266 | * 32-bit value which is sign extended to 64 bits. |
@@ -270,6 +270,8 @@ static void handle_relocations(void *output, unsigned long output_len) | |||
270 | * kernel bits... | 270 | * kernel bits... |
271 | * 0 - zero terminator for 64 bit relocations | 271 | * 0 - zero terminator for 64 bit relocations |
272 | * 64 bit relocation repeated | 272 | * 64 bit relocation repeated |
273 | * 0 - zero terminator for inverse 32 bit relocations | ||
274 | * 32 bit inverse relocation repeated | ||
273 | * 0 - zero terminator for 32 bit relocations | 275 | * 0 - zero terminator for 32 bit relocations |
274 | * 32 bit relocation repeated | 276 | * 32 bit relocation repeated |
275 | * | 277 | * |
@@ -286,6 +288,16 @@ static void handle_relocations(void *output, unsigned long output_len) | |||
286 | *(uint32_t *)ptr += delta; | 288 | *(uint32_t *)ptr += delta; |
287 | } | 289 | } |
288 | #ifdef CONFIG_X86_64 | 290 | #ifdef CONFIG_X86_64 |
291 | while (*--reloc) { | ||
292 | long extended = *reloc; | ||
293 | extended += map; | ||
294 | |||
295 | ptr = (unsigned long)extended; | ||
296 | if (ptr < min_addr || ptr > max_addr) | ||
297 | error("inverse 32-bit relocation outside of kernel!\n"); | ||
298 | |||
299 | *(int32_t *)ptr -= delta; | ||
300 | } | ||
289 | for (reloc--; *reloc; reloc--) { | 301 | for (reloc--; *reloc; reloc--) { |
290 | long extended = *reloc; | 302 | long extended = *reloc; |
291 | extended += map; | 303 | extended += map; |