x86, kaslr: Provide randomness functions
[linux-2.6-block.git] / arch / x86 / boot / compressed / aslr.c
CommitLineData
8ab3820f
KC
1#include "misc.h"
2
3#ifdef CONFIG_RANDOMIZE_BASE
5bfce5ef
KC
4#include <asm/msr.h>
5#include <asm/archrandom.h>
6
7#define I8254_PORT_CONTROL 0x43
8#define I8254_PORT_COUNTER0 0x40
9#define I8254_CMD_READBACK 0xC0
10#define I8254_SELECT_COUNTER0 0x02
11#define I8254_STATUS_NOTREADY 0x40
12static inline u16 i8254(void)
13{
14 u16 status, timer;
15
16 do {
17 outb(I8254_PORT_CONTROL,
18 I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
19 status = inb(I8254_PORT_COUNTER0);
20 timer = inb(I8254_PORT_COUNTER0);
21 timer |= inb(I8254_PORT_COUNTER0) << 8;
22 } while (status & I8254_STATUS_NOTREADY);
23
24 return timer;
25}
26
27static unsigned long get_random_long(void)
28{
29 unsigned long random;
30
31 if (has_cpuflag(X86_FEATURE_RDRAND)) {
32 debug_putstr("KASLR using RDRAND...\n");
33 if (rdrand_long(&random))
34 return random;
35 }
36
37 if (has_cpuflag(X86_FEATURE_TSC)) {
38 uint32_t raw;
39
40 debug_putstr("KASLR using RDTSC...\n");
41 rdtscl(raw);
42
43 /* Only use the low bits of rdtsc. */
44 random = raw & 0xffff;
45 } else {
46 debug_putstr("KASLR using i8254...\n");
47 random = i8254();
48 }
49
50 /* Extend timer bits poorly... */
51 random |= (random << 16);
52#ifdef CONFIG_X86_64
53 random |= (random << 32);
54#endif
55 return random;
56}
8ab3820f
KC
57
58unsigned char *choose_kernel_location(unsigned char *input,
59 unsigned long input_size,
60 unsigned char *output,
61 unsigned long output_size)
62{
63 unsigned long choice = (unsigned long)output;
64
65 if (cmdline_find_option_bool("nokaslr")) {
66 debug_putstr("KASLR disabled...\n");
67 goto out;
68 }
69
70 /* XXX: choose random location. */
71
72out:
73 return (unsigned char *)choice;
74}
75
76#endif /* CONFIG_RANDOMIZE_BASE */