diff options
| -rw-r--r-- | arch/powerpc/boot/main.c | 8 | ||||
| -rw-r--r-- | arch/powerpc/boot/opal-calls.S | 13 | ||||
| -rw-r--r-- | arch/powerpc/boot/opal.c | 11 | ||||
| -rw-r--r-- | arch/powerpc/boot/ops.h | 1 |
4 files changed, 31 insertions, 2 deletions
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 57d42d129033..78aaf4ffd7ab 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c | |||
| @@ -232,8 +232,12 @@ void start(void) | |||
| 232 | console_ops.close(); | 232 | console_ops.close(); |
| 233 | 233 | ||
| 234 | kentry = (kernel_entry_t) vmlinux.addr; | 234 | kentry = (kernel_entry_t) vmlinux.addr; |
| 235 | if (ft_addr) | 235 | if (ft_addr) { |
| 236 | kentry(ft_addr, 0, NULL); | 236 | if(platform_ops.kentry) |
| 237 | platform_ops.kentry(ft_addr, vmlinux.addr); | ||
| 238 | else | ||
| 239 | kentry(ft_addr, 0, NULL); | ||
| 240 | } | ||
| 237 | else | 241 | else |
| 238 | kentry((unsigned long)initrd.addr, initrd.size, | 242 | kentry((unsigned long)initrd.addr, initrd.size, |
| 239 | loader_info.promptr); | 243 | loader_info.promptr); |
diff --git a/arch/powerpc/boot/opal-calls.S b/arch/powerpc/boot/opal-calls.S index ff2f1b97bc53..2a99fc9a3ccf 100644 --- a/arch/powerpc/boot/opal-calls.S +++ b/arch/powerpc/boot/opal-calls.S | |||
| @@ -12,6 +12,19 @@ | |||
| 12 | 12 | ||
| 13 | .text | 13 | .text |
| 14 | 14 | ||
| 15 | .globl opal_kentry | ||
| 16 | opal_kentry: | ||
| 17 | /* r3 is the fdt ptr */ | ||
| 18 | mtctr r4 | ||
| 19 | li r4, 0 | ||
| 20 | li r5, 0 | ||
| 21 | li r6, 0 | ||
| 22 | li r7, 0 | ||
| 23 | ld r11,opal@got(r2) | ||
| 24 | ld r8,0(r11) | ||
| 25 | ld r9,8(r11) | ||
| 26 | bctr | ||
| 27 | |||
| 15 | #define OPAL_CALL(name, token) \ | 28 | #define OPAL_CALL(name, token) \ |
| 16 | .globl name; \ | 29 | .globl name; \ |
| 17 | name: \ | 30 | name: \ |
diff --git a/arch/powerpc/boot/opal.c b/arch/powerpc/boot/opal.c index 1f37e1c1d6d8..d7b4fd47eb44 100644 --- a/arch/powerpc/boot/opal.c +++ b/arch/powerpc/boot/opal.c | |||
| @@ -23,14 +23,25 @@ struct opal { | |||
| 23 | 23 | ||
| 24 | static u32 opal_con_id; | 24 | static u32 opal_con_id; |
| 25 | 25 | ||
| 26 | /* see opal-wrappers.S */ | ||
| 26 | int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer); | 27 | int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer); |
| 27 | int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer); | 28 | int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer); |
| 28 | int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length); | 29 | int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length); |
| 29 | int64_t opal_console_flush(uint64_t term_number); | 30 | int64_t opal_console_flush(uint64_t term_number); |
| 30 | int64_t opal_poll_events(uint64_t *outstanding_event_mask); | 31 | int64_t opal_poll_events(uint64_t *outstanding_event_mask); |
| 31 | 32 | ||
| 33 | void opal_kentry(unsigned long fdt_addr, void *vmlinux_addr); | ||
| 34 | |||
| 32 | static int opal_con_open(void) | 35 | static int opal_con_open(void) |
| 33 | { | 36 | { |
| 37 | /* | ||
| 38 | * When OPAL loads the boot kernel it stashes the OPAL base and entry | ||
| 39 | * address in r8 and r9 so the kernel can use the OPAL console | ||
| 40 | * before unflattening the devicetree. While executing the wrapper will | ||
| 41 | * probably trash r8 and r9 so this kentry hook restores them before | ||
| 42 | * entering the decompressed kernel. | ||
| 43 | */ | ||
| 44 | platform_ops.kentry = opal_kentry; | ||
| 34 | return 0; | 45 | return 0; |
| 35 | } | 46 | } |
| 36 | 47 | ||
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 309d1b127e96..fad1862f4b2d 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h | |||
| @@ -30,6 +30,7 @@ struct platform_ops { | |||
| 30 | void * (*realloc)(void *ptr, unsigned long size); | 30 | void * (*realloc)(void *ptr, unsigned long size); |
| 31 | void (*exit)(void); | 31 | void (*exit)(void); |
| 32 | void * (*vmlinux_alloc)(unsigned long size); | 32 | void * (*vmlinux_alloc)(unsigned long size); |
| 33 | void (*kentry)(unsigned long fdt_addr, void *vmlinux_addr); | ||
| 33 | }; | 34 | }; |
| 34 | extern struct platform_ops platform_ops; | 35 | extern struct platform_ops platform_ops; |
| 35 | 36 | ||
