Mark Salter | 3c7f255 | 2014-04-15 22:47:52 -0400 | [diff] [blame] | 1 | /* |
| 2 | * EFI entry point. |
| 3 | * |
| 4 | * Copyright (C) 2013, 2014 Red Hat, Inc. |
| 5 | * Author: Mark Salter <msalter@redhat.com> |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License version 2 as |
| 9 | * published by the Free Software Foundation. |
| 10 | * |
| 11 | */ |
| 12 | #include <linux/linkage.h> |
| 13 | #include <linux/init.h> |
| 14 | |
| 15 | #include <asm/assembler.h> |
| 16 | |
| 17 | #define EFI_LOAD_ERROR 0x8000000000000001 |
| 18 | |
| 19 | __INIT |
| 20 | |
| 21 | /* |
| 22 | * We arrive here from the EFI boot manager with: |
| 23 | * |
| 24 | * * CPU in little-endian mode |
| 25 | * * MMU on with identity-mapped RAM |
| 26 | * * Icache and Dcache on |
| 27 | * |
| 28 | * We will most likely be running from some place other than where |
| 29 | * we want to be. The kernel image wants to be placed at TEXT_OFFSET |
| 30 | * from start of RAM. |
| 31 | */ |
| 32 | ENTRY(efi_stub_entry) |
| 33 | /* |
| 34 | * Create a stack frame to save FP/LR with extra space |
| 35 | * for image_addr variable passed to efi_entry(). |
| 36 | */ |
| 37 | stp x29, x30, [sp, #-32]! |
| 38 | |
| 39 | /* |
| 40 | * Call efi_entry to do the real work. |
| 41 | * x0 and x1 are already set up by firmware. Current runtime |
| 42 | * address of image is calculated and passed via *image_addr. |
| 43 | * |
| 44 | * unsigned long efi_entry(void *handle, |
| 45 | * efi_system_table_t *sys_table, |
| 46 | * unsigned long *image_addr) ; |
| 47 | */ |
| 48 | adrp x8, _text |
| 49 | add x8, x8, #:lo12:_text |
| 50 | add x2, sp, 16 |
| 51 | str x8, [x2] |
| 52 | bl efi_entry |
| 53 | cmn x0, #1 |
| 54 | b.eq efi_load_fail |
| 55 | |
| 56 | /* |
| 57 | * efi_entry() will have relocated the kernel image if necessary |
| 58 | * and we return here with device tree address in x0 and the kernel |
| 59 | * entry point stored at *image_addr. Save those values in registers |
| 60 | * which are callee preserved. |
| 61 | */ |
| 62 | mov x20, x0 // DTB address |
| 63 | ldr x0, [sp, #16] // relocated _text address |
| 64 | mov x21, x0 |
| 65 | |
| 66 | /* |
| 67 | * Flush dcache covering current runtime addresses |
| 68 | * of kernel text/data. Then flush all of icache. |
| 69 | */ |
| 70 | adrp x1, _text |
| 71 | add x1, x1, #:lo12:_text |
| 72 | adrp x2, _edata |
| 73 | add x2, x2, #:lo12:_edata |
| 74 | sub x1, x2, x1 |
| 75 | |
| 76 | bl __flush_dcache_area |
| 77 | ic ialluis |
| 78 | |
| 79 | /* Turn off Dcache and MMU */ |
| 80 | mrs x0, CurrentEL |
Marc Zyngier | 974c8e4 | 2014-06-06 14:16:21 +0100 | [diff] [blame] | 81 | cmp x0, #CurrentEL_EL2 |
Mark Salter | 3c7f255 | 2014-04-15 22:47:52 -0400 | [diff] [blame] | 82 | b.ne 1f |
| 83 | mrs x0, sctlr_el2 |
| 84 | bic x0, x0, #1 << 0 // clear SCTLR.M |
| 85 | bic x0, x0, #1 << 2 // clear SCTLR.C |
| 86 | msr sctlr_el2, x0 |
| 87 | isb |
| 88 | b 2f |
| 89 | 1: |
| 90 | mrs x0, sctlr_el1 |
| 91 | bic x0, x0, #1 << 0 // clear SCTLR.M |
| 92 | bic x0, x0, #1 << 2 // clear SCTLR.C |
| 93 | msr sctlr_el1, x0 |
| 94 | isb |
| 95 | 2: |
| 96 | /* Jump to kernel entry point */ |
| 97 | mov x0, x20 |
| 98 | mov x1, xzr |
| 99 | mov x2, xzr |
| 100 | mov x3, xzr |
| 101 | br x21 |
| 102 | |
| 103 | efi_load_fail: |
| 104 | mov x0, #EFI_LOAD_ERROR |
| 105 | ldp x29, x30, [sp], #32 |
| 106 | ret |
| 107 | |
| 108 | ENDPROC(efi_stub_entry) |