Hi all,
Yesterday and this morning, I had a go at bringing the 32-bit ARM EFI support in line with the current arm64 upstream code. I have reshuffled a lot of Roy's code, mainly so that the remaining delta against the ARM tree is as small as possible, and keeps out of existing early init code as much as possible. I have not reused any of the existing 32-bit runtime services code. I did not use the early ioremap support but instead refactored the existing init code lightly so that we can use two adjacent fixmap slots instead.
This mostly works, but there are (at least) two issues that need resolving: - LPAE support builds but doesn't run - the EFI page tables are clobbered at some point in the execution -> note in the log below that the RTC efi is read successfully once, but later on (when invoked by hwclock from userland), the page table entries have been cleared
I don't intend to burn a lot of time on this but it may be worthwile to run this on a model (with better watchpoint support) to figure out what is going on with the page tables. Not today though ....
Ard Biesheuvel (7): efi: avoid initialized .data in the EFI stub efi: build efi_config_init() only if CONFIG_EARLY_IOREMAP arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM ARM: move fixmap init before memblock init and use static allocation ARM: split off core code from create_mapping() for EFI reuse ARM: add UEFI support
Roy Franz (1): ARM: add strstr and strncmp to compressed string.c
arch/arm/Kconfig | 19 ++ arch/arm/boot/compressed/.gitignore | 2 + arch/arm/boot/compressed/Makefile | 18 +- arch/arm/boot/compressed/efi-header.S | 141 +++++++++++ arch/arm/boot/compressed/efi-stub.c | 89 +++++++ arch/arm/boot/compressed/head.S | 66 ++++- arch/arm/boot/compressed/string.c | 43 ++++ arch/arm/include/asm/efi.h | 135 ++++++++++ arch/arm/include/asm/fixmap.h | 4 + arch/arm/include/asm/mach/map.h | 1 + arch/arm/kernel/setup.c | 5 + arch/arm/mm/mmu.c | 68 +++-- arch/arm64/include/asm/efi.h | 29 +++ arch/arm64/kernel/efi.c | 330 +------------------------ drivers/firmware/efi/Makefile | 4 + drivers/firmware/efi/arm-init.c | 212 ++++++++++++++++ drivers/firmware/efi/arm-runtime.c | 142 +++++++++++ drivers/firmware/efi/efi.c | 2 + drivers/firmware/efi/libstub/efi-stub-helper.c | 8 +- 19 files changed, 952 insertions(+), 366 deletions(-) create mode 100644 arch/arm/boot/compressed/efi-header.S create mode 100644 arch/arm/boot/compressed/efi-stub.c create mode 100644 arch/arm/include/asm/efi.h create mode 100644 drivers/firmware/efi/arm-init.c create mode 100644 drivers/firmware/efi/arm-runtime.c
--
EFI stub: Booting Linux Kernel... EFI stub: Using DTB from configuration table EFI stub: Exiting boot services and installing virtual address map... [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 4.1.0-rc1-00008-gb6fc321f4ca5-dirty (ard@ards-macbook-pro) (gcc version 4.9.1 20140529 (prerelease) (crosstool-NG linaro-1.13.1-4.9-2014.06 - Linaro GCC 4.9-2014.06) ) #124 SMP Wed Apr 29 13:28:54 CEST 2015 [ 0.000000] CPU: ARMv7 Processor [412fc0f1] revision 1 (ARMv7), cr=10c5387d [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache [ 0.000000] Machine model: linux,dummy-virt [ 0.000000] earlycon: no match for ttyAMA0 [ 0.000000] efi: Getting EFI parameters from FDT: [ 0.000000] efi: System Table: 0x000000007fc25010 [ 0.000000] efi: MemMap Address: 0x0000000076b20010 [ 0.000000] efi: MemMap Size: 0x00000540 [ 0.000000] efi: MemMap Desc. Size: 0x00000030 [ 0.000000] efi: MemMap Desc. Version: 0x00000001 [ 0.000000] Processing EFI memory map: [ 0.000000] 0x000040000000-0x0000425f5fff [Loader Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x0000425f6000-0x000047fedfff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x000047fee000-0x000047ffffff [Loader Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000048000000-0x000076b1ffff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x000076b20000-0x000076b21fff [Loader Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000076b22000-0x000077116fff [Loader Code | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000077117000-0x00007711afff [Reserved | | | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007711b000-0x00007711cfff [ACPI Reclaim Memory| | | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007711d000-0x0000771dffff [Runtime Data |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x0000771e0000-0x000079e6bfff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x000079e6c000-0x00007a59cfff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007a59d000-0x00007a63afff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007a63b000-0x00007babbfff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007babc000-0x00007bb0afff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007bb0b000-0x00007bb19fff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007bb1a000-0x00007bb1efff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007bb1f000-0x00007c01ffff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007c020000-0x00007fabefff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fabf000-0x00007fbc7fff [Boot Code | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fbc8000-0x00007fbdbfff [Runtime Code |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007fbdc000-0x00007fc0dfff [Runtime Data |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007fc0e000-0x00007fc0ffff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fc10000-0x00007fc23fff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fc24000-0x00007fc24fff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fc25000-0x00007fc25fff [Runtime Data |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007fc26000-0x00007fffffff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000004000000-0x000007ffffff [Memory Mapped I/O |RUN| | | | | | | |UC] [ 0.000000] 0x000009010000-0x000009010fff [Memory Mapped I/O |RUN| | | | | | | |UC] [ 0.000000] EFI v2.40 by EDK II [ 0.000000] efi: [ 0.000000] cma: Reserved 64 MiB at 0x7b800000 [ 0.000000] Memory policy: Data cache writealloc [ 0.000000] psci: probing for conduit method from DT. [ 0.000000] psci: PSCIv0.2 detected in firmware. [ 0.000000] psci: Using standard PSCI v0.2 function IDs [ 0.000000] PERCPU: Embedded 12 pages/cpu @eefe3000 s16960 r8192 d24000 u49152 [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260624 [ 0.000000] Kernel command line: console=ttyAMA0 uefi_debug root=/dev/vda2 [ 0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes) [ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes) [ 0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes) [ 0.000000] Memory: 958824K/1048576K available (8132K kernel code, 967K rwdata, 3688K rodata, 828K init, 321K bss, 24216K reserved, 65536K cma-reserved, 203708K highmem) [ 0.000000] Virtual kernel memory layout: [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB) [ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB) [ 0.000000] vmalloc : 0xf0000000 - 0xff000000 ( 240 MB) [ 0.000000] lowmem : 0xc0000000 - 0xef800000 ( 760 MB) [ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB) [ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB) [ 0.000000] .text : 0xc0208000 - 0xc0d940e0 (11825 kB) [ 0.000000] .init : 0xc0d95000 - 0xc0e64000 ( 828 kB) [ 0.000000] .data : 0xc0e64000 - 0xc0f55f40 ( 968 kB) [ 0.000000] .bss : 0xc0f58000 - 0xc0fa86d8 ( 322 kB) [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 [ 0.000000] Hierarchical RCU implementation. [ 0.000000] Additional per-CPU info printed with stalls. [ 0.000000] RCU restricting CPUs from NR_CPUS=16 to nr_cpu_ids=1. [ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1 [ 0.000000] NR_IRQS:16 nr_irqs:16 16 [ 0.000000] Architected cp15 timer(s) running at 62.50MHz (virt). [ 0.000000] clocksource arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns [ 0.000118] sched_clock: 56 bits at 62MHz, resolution 16ns, wraps every 4398046511096ns [ 0.000226] Switching to timer-based delay loop, resolution 16ns [ 0.002942] Console: colour dummy device 80x30 [ 0.003398] Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=312500) [ 0.003518] pid_max: default: 32768 minimum: 301 [ 0.006917] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes) [ 0.006955] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes) [ 0.014326] CPU: Testing write buffer coherency: ok [ 0.020134] /cpus/cpu@0 missing clock-frequency property [ 0.020346] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 [ 0.020922] Setting up static identity map for 0x40209000 - 0x40209098 [ 0.028361] Brought up 1 CPUs [ 0.028426] SMP: Total of 1 processors activated (125.00 BogoMIPS). [ 0.028474] CPU: All CPU(s) started in SVC mode. [ 0.036288] devtmpfs: initialized [ 0.040769] VFP support v0.3: implementor 41 architecture 4 part 30 variant f rev 0 [ 0.053306] clocksource jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 9556302231375000 ns [ 0.064590] pinctrl core: initialized pinctrl subsystem [ 0.080529] NET: Registered protocol family 16 [ 0.087570] DMA: preallocated 256 KiB pool for atomic coherent allocations [ 0.091747] cpuidle: using governor ladder [ 0.091877] cpuidle: using governor menu [ 0.091935] Remapping and enabling EFI services. [ 0.092255] EFI remap 0x7711d000 => 4000d000 [ 0.092976] EFI remap 0x7fbc8000 => 400d8000 [ 0.093004] EFI remap 0x7fbdc000 => 400fc000 [ 0.093024] EFI remap 0x7fc25000 => 40135000 [ 0.093039] EFI remap 0x04000000 => 40200000 [ 0.093110] EFI remap 0x09010000 => 44200000 [ 0.113384] No ATAGs? [ 0.113803] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4 watchpoint registers. [ 0.113892] hw-breakpoint: maximum watchpoint size is 8 bytes. [ 0.119299] Serial: AMBA PL011 UART driver [ 0.120749] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 52, base_baud = 0) is a PL011 rev1 [ 0.139298] console [ttyAMA0] enabled [ 0.233516] vgaarb: loaded [ 0.239868] SCSI subsystem initialized [ 0.244809] usbcore: registered new interface driver usbfs [ 0.245706] usbcore: registered new interface driver hub [ 0.246613] usbcore: registered new device driver usb [ 0.253095] media: Linux media interface: v0.10 [ 0.253947] Linux video capture interface: v2.00 [ 0.254678] pps_core: LinuxPPS API ver. 1 registered [ 0.255062] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti giometti@linux.it [ 0.255873] PTP clock support registered [ 0.257389] EDAC MC: Ver: 3.0.0 [ 0.265252] Advanced Linux Sound Architecture Driver Initialized. [ 0.282630] Switched to clocksource arch_sys_counter [ 0.332666] NET: Registered protocol family 2 [ 0.341082] TCP established hash table entries: 8192 (order: 3, 32768 bytes) [ 0.342231] TCP bind hash table entries: 8192 (order: 4, 65536 bytes) [ 0.343018] TCP: Hash tables configured (established 8192 bind 8192) [ 0.344267] UDP hash table entries: 512 (order: 2, 16384 bytes) [ 0.344795] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes) [ 0.347463] NET: Registered protocol family 1 [ 0.352278] RPC: Registered named UNIX socket transport module. [ 0.352676] RPC: Registered udp transport module. [ 0.352960] RPC: Registered tcp transport module. [ 0.353230] RPC: Registered tcp NFSv4.1 backchannel transport module. [ 0.373238] futex hash table entries: 256 (order: 2, 16384 bytes) [ 0.420563] squashfs: version 4.0 (2009/01/31) Phillip Lougher [ 0.425328] NFS: Registering the id_resolver key type [ 0.426767] Key type id_resolver registered [ 0.427035] Key type id_legacy registered [ 0.427812] ntfs: driver 2.1.32 [Flags: R/O]. [ 0.438395] bounce: pool size: 64 pages [ 0.439517] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 248) [ 0.440019] io scheduler noop registered [ 0.440277] io scheduler deadline registered [ 0.441080] io scheduler cfq registered (default) [ 0.463911] PCI host bridge /pcie@10000000 ranges: [ 0.464611] IO 0x3eff0000..0x3effffff -> 0x00000000 [ 0.465131] MEM 0x10000000..0x3efeffff -> 0x10000000 [ 0.468035] pci-host-generic 3f000000.pcie: PCI host bridge to bus 0000:00 [ 0.468773] pci_bus 0000:00: root bus resource [bus 00-0f] [ 0.469124] pci_bus 0000:00: root bus resource [io 0x0000-0xffff] [ 0.469463] pci_bus 0000:00: root bus resource [mem 0x10000000-0x3efeffff] [ 0.472424] pci 0000:00:00.0: IOMMU is currently not supported for PCI [ 0.474335] PCI: bus0: Fast back to back transfers disabled [ 0.632744] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled [ 0.636742] SuperH (H)SCI(F) driver initialized [ 0.638086] msm_serial: driver initialized [ 0.639063] STMicroelectronics ASC driver initialized [ 0.641720] [drm] Initialized drm 1.1.0 20060810 [ 0.659210] loop: module loaded [ 0.674291] vda: vda1 vda2 [ 0.689435] CAN device driver interface [ 0.691055] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.2.15-k [ 0.691280] igb: Copyright (c) 2007-2014 Intel Corporation. [ 0.694341] pegasus: v0.9.3 (2013/04/25), Pegasus/Pegasus II USB Ethernet driver [ 0.694655] usbcore: registered new interface driver pegasus [ 0.694987] usbcore: registered new interface driver asix [ 0.695260] usbcore: registered new interface driver ax88179_178a [ 0.695545] usbcore: registered new interface driver cdc_ether [ 0.695860] usbcore: registered new interface driver smsc75xx [ 0.696165] usbcore: registered new interface driver smsc95xx [ 0.696563] usbcore: registered new interface driver net1080 [ 0.696881] usbcore: registered new interface driver cdc_subset [ 0.697179] usbcore: registered new interface driver zaurus [ 0.697529] usbcore: registered new interface driver cdc_ncm [ 0.701287] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver [ 0.701882] ehci-pci: EHCI PCI platform driver [ 0.702229] ehci-platform: EHCI generic platform driver [ 0.702671] ehci-omap: OMAP-EHCI Host Controller driver [ 0.703101] ehci-orion: EHCI orion driver [ 0.703434] SPEAr-ehci: EHCI SPEAr driver [ 0.703766] ehci-st: EHCI STMicroelectronics driver [ 0.704114] ehci-exynos: EHCI EXYNOS driver [ 0.704610] tegra-ehci: Tegra EHCI driver [ 0.705215] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver [ 0.705714] ohci-pci: OHCI PCI platform driver [ 0.706201] ohci-platform: OHCI generic platform driver [ 0.706838] ohci-omap3: OHCI OMAP3 driver [ 0.707191] SPEAr-ohci: OHCI SPEAr driver [ 0.707534] ohci-st: OHCI STMicroelectronics driver [ 0.708011] usbcore: registered new interface driver usb-storage [ 0.710715] mousedev: PS/2 mouse device common for all mice [ 0.715348] pgd = ee0a8000 [ 0.715530] [40135fa8] *pgd=6eff0801, *pte=7fc2565f, *ppte=7fc2545f [ 0.717378] pgd = c0204000 [ 0.717569] [40135fa8] *pgd=00000000 [ 0.718496] pgd = ee0a8000 [ 0.718662] [40135fa8] *pgd=6eff0801, *pte=7fc2565f, *ppte=7fc2545f [ 0.719064] pgd = c0204000 [ 0.719229] [40135fa8] *pgd=00000000 [ 0.720592] rtc-efi rtc-efi: rtc core: registered rtc-efi as rtc0 [ 0.725523] i2c /dev entries driver [ 0.730382] usbcore: registered new interface driver uvcvideo [ 0.730574] USB Video Class driver (1.1.1) [ 0.730722] gspca_main: v2.14.0 registered [ 0.738884] sdhci: Secure Digital Host Controller Interface driver [ 0.739077] sdhci: Copyright(c) Pierre Ossman [ 0.741055] Synopsys Designware Multimedia Card Interface Driver [ 0.742779] sdhci-pltfm: SDHCI platform and OF driver helper [ 0.745151] ledtrig-cpu: registered to indicate activity on CPUs [ 0.745887] usbcore: registered new interface driver usbhid [ 0.746056] usbhid: USB HID core driver [ 0.752141] usbcore: registered new interface driver snd-usb-audio [ 0.757717] NET: Registered protocol family 17 [ 0.757962] can: controller area network core (rev 20120528 abi 9) [ 0.758407] NET: Registered protocol family 29 [ 0.758597] can: raw protocol (rev 20120528) [ 0.758793] can: broadcast manager protocol (rev 20120528 t) [ 0.759009] can: netlink gateway (rev 20130117) max_hops=1 [ 0.760727] Key type dns_resolver registered [ 0.761485] ThumbEE CPU extension supported. [ 0.761804] Registering SWP/SWPB emulation handler [ 0.769849] pgd = ee0a8000 [ 0.770038] [40135fa8] *pgd=6eff0801, *pte=7fc2565f, *ppte=7fc2545f [ 0.771889] rtc-efi rtc-efi: setting system clock to 2015-04-29 11:29:27 UTC (1430306967) [ 0.773564] ALSA device list: [ 0.773716] No soundcards found. [ 0.776119] uart-pl011 9000000.pl011: no DMA platform data [ 0.780952] EXT4-fs (vda2): couldn't mount as ext3 due to feature incompatibilities [ 0.782820] EXT4-fs (vda2): couldn't mount as ext2 due to feature incompatibilities [ 0.785690] EXT4-fs (vda2): INFO: recovery required on readonly filesystem [ 0.785914] EXT4-fs (vda2): write access will be enabled during recovery [ 0.818639] EXT4-fs (vda2): recovery complete [ 0.823286] EXT4-fs (vda2): mounted filesystem with ordered data mode. Opts: (null) [ 0.824828] VFS: Mounted root (ext4 filesystem) readonly on device 254:2. [ 0.829458] devtmpfs: mounted [ 0.850536] Freeing unused kernel memory: 828K (c0d95000 - c0e64000) INIT: version 2.88 booting Error opening /dev/fb0: No such file or directory Starting udev [ 2.201880] udevd[65]: starting version 182 [ 9.722297] FAT-fs (vda1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck. [ 9.968052] EXT4-fs (vda2): re-mounted. Opts: data=ordered [ 10.346751] random: dd urandom read with 9 bits of entropy available Populating dev cache [ 13.790965] pgd = ee0a8000 [ 13.791126] [40135fa8] *pgd=6eff0801, *pte=00000000, *ppte=00000000 [ 13.791581] Unable to handle kernel paging request at virtual address 40135fa8 [ 13.791820] pgd = ed170000 [ 13.791925] [40135fa8] *pgd=00000000 [ 13.792281] Internal error: Oops: 7 [#1] SMP ARM [ 13.792553] Modules linked in: [ 13.792879] CPU: 0 PID: 308 Comm: hwclock Not tainted 4.1.0-rc1-00008-gb6fc321f4ca5-dirty #124 [ 13.793144] Hardware name: Generic DT based system [ 13.793355] task: ed03d300 ti: ed252000 task.ti: ed252000 [ 13.793607] PC is at virt_efi_get_time+0x4c/0x88 [ 13.793794] LR is at broadcast_tlb_a15_erratum+0x1c/0x3c [ 13.793985] pc : [<c0851a58>] lr : [<c0216ca8>] psr: 60060093 [ 13.793985] sp : ed253e68 ip : 00000000 fp : 00000000 [ 13.794328] r10: 00000000 r9 : ed252000 r8 : ed253e84 [ 13.794508] r7 : 40060013 r6 : ed253e90 r5 : c0f9be08 r4 : c0f9be04 [ 13.794718] r3 : 40135f90 r2 : 00000000 r1 : ed253e84 r0 : ed253e90 [ 13.794982] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user [ 13.795221] Control: 10c5387d Table: 6e0a806a DAC: 00000015 [ 13.795425] Process hwclock (pid: 308, stack limit = 0xed252220) [ 13.795646] Stack: (0xed253e68 to 0xed254000) [ 13.795903] 3e60: ed253ed4 c0f0a158 ee389800 bed83c34 c0ab1b20 c07baadc [ 13.796169] 3e80: ee002d00 ed08ef00 ed253ef0 c03154a4 ed253eac ed0c3080 00000000 ed0c9a50 [ 13.796426] 3ea0: ed253fb0 ee389994 ed253ed4 c07b6d68 ee389800 ee389998 ed253ed4 c07b6dbc [ 13.796684] 3ec0: ee389800 80247009 ee389998 c07b8048 ed0e0000 00000000 00000000 00000000 [ 13.796937] 3ee0: 00000000 00000000 00000000 00000000 00000000 00000000 b37f1802 00000004 [ 13.797191] 3f00: ed14e540 000a7cf8 00000000 ed8256e8 ee38abe8 00000101 00000004 0000004a [ 13.797446] 3f20: ee38abe8 bed83c34 ed08ef00 00000003 bed83c34 c0318944 00000000 00000000 [ 13.797701] 3f40: 00020000 00000003 00000003 ed08ef00 ed0e0000 ee38abe8 ed08ef08 00000020 [ 13.797953] 3f60: 00000000 c03075fc 00000000 00000000 00000000 ed08ef00 00000003 ed08ef00 [ 13.798209] 3f80: 80247009 bed83c34 ed252000 c0318b6c 00094500 00000003 00000002 00000036 [ 13.798464] 3fa0: c0210784 c0210600 00094500 00000003 00000003 80247009 bed83c34 00094500 [ 13.798720] 3fc0: 00094500 00000003 00000002 00000036 00000000 00000000 000a7cf8 00000000 [ 13.798984] 3fe0: b6e2e8a0 bed83bfc 00019538 b6e2e8ac 60060010 00000003 6f7fd821 6f7fdc21 [ 13.799397] [<c0851a58>] (virt_efi_get_time) from [<c07baadc>] (efi_read_time+0x28/0x74) [ 13.799709] [<c07baadc>] (efi_read_time) from [<c07b6d68>] (__rtc_read_time.isra.3+0x48/0x6c) [ 13.799986] [<c07b6d68>] (__rtc_read_time.isra.3) from [<c07b6dbc>] (rtc_read_time+0x30/0x44) [ 13.800237] [<c07b6dbc>] (rtc_read_time) from [<c07b8048>] (rtc_dev_ioctl+0x328/0x5b0) [ 13.800481] [<c07b8048>] (rtc_dev_ioctl) from [<c0318944>] (do_vfs_ioctl+0x418/0x60c) [ 13.800755] [<c0318944>] (do_vfs_ioctl) from [<c0318b6c>] (SyS_ioctl+0x34/0x5c) [ 13.800991] [<c0318b6c>] (SyS_ioctl) from [<c0210600>] (ret_fast_syscall+0x0/0x34) [ 13.801370] Code: e1a01008 e5933000 e1a00006 e5933038 (e5933018) [ 13.801783] ---[ end trace d5b7f564e6da9c28 ]---
In preparation of adding ARM support, this refactors the nochunk EFI param so that it does not populate the .data section, since that gets discarded on ARM.
Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- drivers/firmware/efi/libstub/efi-stub-helper.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index f07d4a67fa76..15c8b27121fd 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -30,7 +30,7 @@ */ #define EFI_READ_CHUNK_SIZE (1024 * 1024)
-static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; +bool __nochunk;
/* * Allow the platform to override the allocation granularity: this allows @@ -335,7 +335,7 @@ efi_status_t efi_parse_options(char *cmdline) while (*str) { if (!strncmp(str, "nochunk", 7)) { str += strlen("nochunk"); - __chunk_size = -1UL; + __nochunk = true; }
/* Group words together, delimited by "," */ @@ -490,8 +490,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, size = files[j].size; while (size) { unsigned long chunksize; - if (size > __chunk_size) - chunksize = __chunk_size; + if (!__nochunk && size > EFI_READ_CHUNK_SIZE) + chunksize = EFI_READ_CHUNK_SIZE; else chunksize = size;
On 29 April 2015 at 12:48, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
In preparation of adding ARM support, this refactors the nochunk EFI param so that it does not populate the .data section, since that gets discarded on ARM.
Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org
drivers/firmware/efi/libstub/efi-stub-helper.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index f07d4a67fa76..15c8b27121fd 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -30,7 +30,7 @@ */ #define EFI_READ_CHUNK_SIZE (1024 * 1024)
-static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; +bool __nochunk;
/*
- Allow the platform to override the allocation granularity: this allows
@@ -335,7 +335,7 @@ efi_status_t efi_parse_options(char *cmdline) while (*str) { if (!strncmp(str, "nochunk", 7)) { str += strlen("nochunk");
__chunk_size = -1UL;
__nochunk = true; } /* Group words together, delimited by "," */
@@ -490,8 +490,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, size = files[j].size; while (size) { unsigned long chunksize;
if (size > __chunk_size)
chunksize = __chunk_size;
if (!__nochunk && size > EFI_READ_CHUNK_SIZE)
chunksize = EFI_READ_CHUNK_SIZE; else chunksize = size;
-- 1.9.1
I have no issues with this patch, but I have a question: Can we assume that we never will need to have initialised data in the stub? If so, we should try to get that formally stated somewhere, or this will happen again.
If not, I did something fairly ugly (but functional) when I came across this issue last time I looked at bringing the old code up to date; I added a __stubdata storage type qualifier that was empty on all other archs and created a .stubdata section for this variable on ARM.
/ Leif
On 29 April 2015 at 14:49, Leif Lindholm leif.lindholm@linaro.org wrote:
On 29 April 2015 at 12:48, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
In preparation of adding ARM support, this refactors the nochunk EFI param so that it does not populate the .data section, since that gets discarded on ARM.
Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org
drivers/firmware/efi/libstub/efi-stub-helper.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index f07d4a67fa76..15c8b27121fd 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -30,7 +30,7 @@ */ #define EFI_READ_CHUNK_SIZE (1024 * 1024)
-static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; +bool __nochunk;
/*
- Allow the platform to override the allocation granularity: this allows
@@ -335,7 +335,7 @@ efi_status_t efi_parse_options(char *cmdline) while (*str) { if (!strncmp(str, "nochunk", 7)) { str += strlen("nochunk");
__chunk_size = -1UL;
__nochunk = true; } /* Group words together, delimited by "," */
@@ -490,8 +490,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, size = files[j].size; while (size) { unsigned long chunksize;
if (size > __chunk_size)
chunksize = __chunk_size;
if (!__nochunk && size > EFI_READ_CHUNK_SIZE)
chunksize = EFI_READ_CHUNK_SIZE; else chunksize = size;
-- 1.9.1
I have no issues with this patch, but I have a question: Can we assume that we never will need to have initialised data in the stub? If so, we should try to get that formally stated somewhere, or this will happen again.
Indeed. There was a similar issue with linux_banner, although that seems to have resolved itself.
Actually, when using 'hidden' visibility, there are no GOT related issues anymore since all global references will be PC relative. Only, Russell and his toolchain museum are never going to go for that :-(
If not, I did something fairly ugly (but functional) when I came across this issue last time I looked at bringing the old code up to date; I added a __stubdata storage type qualifier that was empty on all other archs and created a .stubdata section for this variable on ARM.
Yes, I noticed that. My pov is that if we are going to support .data, we could just as well put it in .data and not abuse .piggydata for that.
On 29 April 2015 at 14:04, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
I have no issues with this patch, but I have a question: Can we assume that we never will need to have initialised data in the stub? If so, we should try to get that formally stated somewhere, or this will happen again.
Indeed. There was a similar issue with linux_banner, although that seems to have resolved itself.
Actually, when using 'hidden' visibility, there are no GOT related issues anymore since all global references will be PC relative. Only, Russell and his toolchain museum are never going to go for that :-(
If not, I did something fairly ugly (but functional) when I came across this issue last time I looked at bringing the old code up to date; I added a __stubdata storage type qualifier that was empty on all other archs and created a .stubdata section for this variable on ARM.
Yes, I noticed that. My pov is that if we are going to support .data, we could just as well put it in .data and not abuse .piggydata for that.
Yeah, only the comment in the linker script looks very explicit and not very likely to change.
/ Leif
On Wed, Apr 29, 2015 at 6:27 AM, Leif Lindholm leif.lindholm@linaro.org wrote:
On 29 April 2015 at 14:04, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
I have no issues with this patch, but I have a question: Can we assume that we never will need to have initialised data in the stub? If so, we should try to get that formally stated somewhere, or this will happen again.
Indeed. There was a similar issue with linux_banner, although that seems to have resolved itself.
Actually, when using 'hidden' visibility, there are no GOT related issues anymore since all global references will be PC relative. Only, Russell and his toolchain museum are never going to go for that :-(
The whole "don't use global data" thing was done to avoid having to do GOT fixups, and before the code sharing with ARM64. I do wonder about how well this will work in the long term when sharing code with x86/ARM64.
If not, I did something fairly ugly (but functional) when I came across this issue last time I looked at bringing the old code up to date; I added a __stubdata storage type qualifier that was empty on all other archs and created a .stubdata section for this variable on ARM.
Yes, I noticed that. My pov is that if we are going to support .data, we could just as well put it in .data and not abuse .piggydata for that.
Yeah, only the comment in the linker script looks very explicit and not very likely to change.
/ Leif
On 29 April 2015 at 20:58, Roy Franz roy.franz@linaro.org wrote:
On Wed, Apr 29, 2015 at 6:27 AM, Leif Lindholm leif.lindholm@linaro.org wrote:
On 29 April 2015 at 14:04, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
I have no issues with this patch, but I have a question: Can we assume that we never will need to have initialised data in the stub? If so, we should try to get that formally stated somewhere, or this will happen again.
Indeed. There was a similar issue with linux_banner, although that seems to have resolved itself.
Actually, when using 'hidden' visibility, there are no GOT related issues anymore since all global references will be PC relative. Only, Russell and his toolchain museum are never going to go for that :-(
The whole "don't use global data" thing was done to avoid having to do GOT fixups, and before the code sharing with ARM64. I do wonder about how well this will work in the long term when sharing code with x86/ARM64.
In this particular case, perhaps we should make the chunking feature x86-only.
But in general, we should perhaps require a minimal version of the toolchain, and use hidden visibility judiciously
If not, I did something fairly ugly (but functional) when I came across this issue last time I looked at bringing the old code up to date; I added a __stubdata storage type qualifier that was empty on all other archs and created a .stubdata section for this variable on ARM.
Yes, I noticed that. My pov is that if we are going to support .data, we could just as well put it in .data and not abuse .piggydata for that.
Yeah, only the comment in the linker script looks very explicit and not very likely to change.
/ Leif
In preparation of adding ARM support, avoid compiling the efi_config_init() function, which ARM and arm64 do not use, and which can only be built if early ioremap() is supported, which is not the case on ARM.
Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- drivers/firmware/efi/efi.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 3061bb8629dc..03a6b313568c 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -336,6 +336,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, return 0; }
+#ifdef CONFIG_GENERIC_EARLY_IOREMAP int __init efi_config_init(efi_config_table_type_t *arch_tables) { void *config_tables; @@ -362,6 +363,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) early_memunmap(config_tables, efi.systab->nr_tables * sz); return ret; } +#endif
#ifdef CONFIG_EFI_VARS_MODULE static int __init efi_load_efivars(void)
This splits off the early EFI init and runtime code that - discovers the EFI params and the memory map from the FDT, and installs the memblocks and config tables. - prepares and installs the EFI page tables so that UEFI Runtime Services can be invoked at the virtual address installed by the stub.
This will allow it to be reused for 32-bit ARM.
Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- arch/arm64/kernel/efi.c | 330 +------------------------------------ drivers/firmware/efi/Makefile | 4 + drivers/firmware/efi/arm-init.c | 203 +++++++++++++++++++++++ drivers/firmware/efi/arm-runtime.c | 150 +++++++++++++++++ 4 files changed, 358 insertions(+), 329 deletions(-) create mode 100644 drivers/firmware/efi/arm-init.c create mode 100644 drivers/firmware/efi/arm-runtime.c
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index ab21e0d58278..bd3b2f5adf0c 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -11,315 +11,11 @@ * */
-#include <linux/atomic.h> #include <linux/dmi.h> #include <linux/efi.h> -#include <linux/export.h> -#include <linux/memblock.h> -#include <linux/mm_types.h> -#include <linux/bootmem.h> -#include <linux/of.h> -#include <linux/of_fdt.h> -#include <linux/preempt.h> -#include <linux/rbtree.h> -#include <linux/rwsem.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/spinlock.h> +#include <linux/init.h>
-#include <asm/cacheflush.h> #include <asm/efi.h> -#include <asm/tlbflush.h> -#include <asm/mmu_context.h> -#include <asm/mmu.h> -#include <asm/pgtable.h> - -struct efi_memory_map memmap; - -static u64 efi_system_table; - -static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss; - -static struct mm_struct efi_mm = { - .mm_rb = RB_ROOT, - .pgd = efi_pgd, - .mm_users = ATOMIC_INIT(2), - .mm_count = ATOMIC_INIT(1), - .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem), - .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock), - .mmlist = LIST_HEAD_INIT(efi_mm.mmlist), - INIT_MM_CONTEXT(efi_mm) -}; - -static int uefi_debug __initdata; -static int __init uefi_debug_setup(char *str) -{ - uefi_debug = 1; - - return 0; -} -early_param("uefi_debug", uefi_debug_setup); - -static int __init is_normal_ram(efi_memory_desc_t *md) -{ - if (md->attribute & EFI_MEMORY_WB) - return 1; - return 0; -} - -/* - * Translate a EFI virtual address into a physical address: this is necessary, - * as some data members of the EFI system table are virtually remapped after - * SetVirtualAddressMap() has been called. - */ -static phys_addr_t efi_to_phys(unsigned long addr) -{ - efi_memory_desc_t *md; - - for_each_efi_memory_desc(&memmap, md) { - if (!(md->attribute & EFI_MEMORY_RUNTIME)) - continue; - if (md->virt_addr == 0) - /* no virtual mapping has been installed by the stub */ - break; - if (md->virt_addr <= addr && - (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT)) - return md->phys_addr + addr - md->virt_addr; - } - return addr; -} - -static int __init uefi_init(void) -{ - efi_char16_t *c16; - void *config_tables; - u64 table_size; - char vendor[100] = "unknown"; - int i, retval; - - efi.systab = early_memremap(efi_system_table, - sizeof(efi_system_table_t)); - if (efi.systab == NULL) { - pr_warn("Unable to map EFI system table.\n"); - return -ENOMEM; - } - - set_bit(EFI_BOOT, &efi.flags); - set_bit(EFI_64BIT, &efi.flags); - - /* - * Verify the EFI Table - */ - if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) { - pr_err("System table signature incorrect\n"); - retval = -EINVAL; - goto out; - } - if ((efi.systab->hdr.revision >> 16) < 2) - pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n", - efi.systab->hdr.revision >> 16, - efi.systab->hdr.revision & 0xffff); - - /* Show what we know for posterity */ - c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor), - sizeof(vendor)); - if (c16) { - for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i) - vendor[i] = c16[i]; - vendor[i] = '\0'; - early_memunmap(c16, sizeof(vendor)); - } - - pr_info("EFI v%u.%.02u by %s\n", - efi.systab->hdr.revision >> 16, - efi.systab->hdr.revision & 0xffff, vendor); - - table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables; - config_tables = early_memremap(efi_to_phys(efi.systab->tables), - table_size); - - retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, - sizeof(efi_config_table_64_t), NULL); - - early_memunmap(config_tables, table_size); -out: - early_memunmap(efi.systab, sizeof(efi_system_table_t)); - return retval; -} - -/* - * Return true for RAM regions we want to permanently reserve. - */ -static __init int is_reserve_region(efi_memory_desc_t *md) -{ - switch (md->type) { - case EFI_LOADER_CODE: - case EFI_LOADER_DATA: - case EFI_BOOT_SERVICES_CODE: - case EFI_BOOT_SERVICES_DATA: - case EFI_CONVENTIONAL_MEMORY: - return 0; - default: - break; - } - return is_normal_ram(md); -} - -static __init void reserve_regions(void) -{ - efi_memory_desc_t *md; - u64 paddr, npages, size; - - if (uefi_debug) - pr_info("Processing EFI memory map:\n"); - - for_each_efi_memory_desc(&memmap, md) { - paddr = md->phys_addr; - npages = md->num_pages; - - if (uefi_debug) { - char buf[64]; - - pr_info(" 0x%012llx-0x%012llx %s", - paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1, - efi_md_typeattr_format(buf, sizeof(buf), md)); - } - - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - - if (is_normal_ram(md)) - early_init_dt_add_memory_arch(paddr, size); - - if (is_reserve_region(md)) { - memblock_reserve(paddr, size); - if (uefi_debug) - pr_cont("*"); - } - - if (uefi_debug) - pr_cont("\n"); - } - - set_bit(EFI_MEMMAP, &efi.flags); -} - -void __init efi_init(void) -{ - struct efi_fdt_params params; - - /* Grab UEFI information placed in FDT by stub */ - if (!efi_get_fdt_params(¶ms, uefi_debug)) - return; - - efi_system_table = params.system_table; - - memblock_reserve(params.mmap & PAGE_MASK, - PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK))); - memmap.phys_map = (void *)params.mmap; - memmap.map = early_memremap(params.mmap, params.mmap_size); - memmap.map_end = memmap.map + params.mmap_size; - memmap.desc_size = params.desc_size; - memmap.desc_version = params.desc_ver; - - if (uefi_init() < 0) - return; - - reserve_regions(); - early_memunmap(memmap.map, params.mmap_size); -} - -static bool __init efi_virtmap_init(void) -{ - efi_memory_desc_t *md; - - for_each_efi_memory_desc(&memmap, md) { - u64 paddr, npages, size; - pgprot_t prot; - - if (!(md->attribute & EFI_MEMORY_RUNTIME)) - continue; - if (md->virt_addr == 0) - return false; - - paddr = md->phys_addr; - npages = md->num_pages; - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - - pr_info(" EFI remap 0x%016llx => %p\n", - md->phys_addr, (void *)md->virt_addr); - - /* - * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be - * executable, everything else can be mapped with the XN bits - * set. - */ - if (!is_normal_ram(md)) - prot = __pgprot(PROT_DEVICE_nGnRE); - else if (md->type == EFI_RUNTIME_SERVICES_CODE) - prot = PAGE_KERNEL_EXEC; - else - prot = PAGE_KERNEL; - - create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot); - } - return true; -} - -/* - * Enable the UEFI Runtime Services if all prerequisites are in place, i.e., - * non-early mapping of the UEFI system table and virtual mappings for all - * EFI_MEMORY_RUNTIME regions. - */ -static int __init arm64_enable_runtime_services(void) -{ - u64 mapsize; - - if (!efi_enabled(EFI_BOOT)) { - pr_info("EFI services will not be available.\n"); - return -1; - } - - if (efi_runtime_disabled()) { - pr_info("EFI runtime services will be disabled.\n"); - return -1; - } - - pr_info("Remapping and enabling EFI services.\n"); - - mapsize = memmap.map_end - memmap.map; - memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map, - mapsize); - if (!memmap.map) { - pr_err("Failed to remap EFI memory map\n"); - return -1; - } - memmap.map_end = memmap.map + mapsize; - efi.memmap = &memmap; - - efi.systab = (__force void *)ioremap_cache(efi_system_table, - sizeof(efi_system_table_t)); - if (!efi.systab) { - pr_err("Failed to remap EFI System Table\n"); - return -1; - } - set_bit(EFI_SYSTEM_TABLES, &efi.flags); - - if (!efi_virtmap_init()) { - pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); - return -1; - } - - /* Set up runtime services function pointers */ - efi_native_runtime_setup(); - set_bit(EFI_RUNTIME_SERVICES, &efi.flags); - - efi.runtime_version = efi.systab->hdr.revision; - - return 0; -} -early_initcall(arm64_enable_runtime_services);
static int __init arm64_dmi_init(void) { @@ -335,30 +31,6 @@ static int __init arm64_dmi_init(void) } core_initcall(arm64_dmi_init);
-static void efi_set_pgd(struct mm_struct *mm) -{ - if (mm == &init_mm) - cpu_set_reserved_ttbr0(); - else - cpu_switch_mm(mm->pgd, mm); - - flush_tlb_all(); - if (icache_is_aivivt()) - __flush_icache_all(); -} - -void efi_virtmap_load(void) -{ - preempt_disable(); - efi_set_pgd(&efi_mm); -} - -void efi_virtmap_unload(void) -{ - efi_set_pgd(current->active_mm); - preempt_enable(); -} - /* * UpdateCapsule() depends on the system being shutdown via * ResetSystem(). diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index d8be608a9f3b..ab847e0c81fe 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -8,3 +8,7 @@ obj-$(CONFIG_UEFI_CPER) += cper.o obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o obj-$(CONFIG_EFI_STUB) += libstub/ + +ifneq ($(CONFIG_ARM64)$(CONFIG_ARM),nn) +obj-$(CONFIG_EFI) += arm-init.o arm-runtime.o +endif diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c new file mode 100644 index 000000000000..12e666ac6a34 --- /dev/null +++ b/drivers/firmware/efi/arm-init.c @@ -0,0 +1,203 @@ +/* + * Extensible Firmware Interface + * + * Based on Extensible Firmware Interface Specification version 2.4 + * + * Copyright (C) 2013 - 2015 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/efi.h> +#include <linux/init.h> +#include <linux/memblock.h> +#include <linux/mm_types.h> +#include <linux/of.h> +#include <linux/of_fdt.h> + +#include <asm/efi.h> + +struct efi_memory_map memmap; + +u64 efi_system_table; + +static int uefi_debug __initdata; +static int __init uefi_debug_setup(char *str) +{ + uefi_debug = 1; + + return 0; +} +early_param("uefi_debug", uefi_debug_setup); + +static int __init is_normal_ram(efi_memory_desc_t *md) +{ + if (md->attribute & EFI_MEMORY_WB) + return 1; + return 0; +} + +/* + * Translate a EFI virtual address into a physical address: this is necessary, + * as some data members of the EFI system table are virtually remapped after + * SetVirtualAddressMap() has been called. + */ +static phys_addr_t efi_to_phys(unsigned long addr) +{ + efi_memory_desc_t *md; + + for_each_efi_memory_desc(&memmap, md) { + if (!(md->attribute & EFI_MEMORY_RUNTIME)) + continue; + if (md->virt_addr == 0) + /* no virtual mapping has been installed by the stub */ + break; + if (md->virt_addr <= addr && + (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT)) + return md->phys_addr + addr - md->virt_addr; + } + return addr; +} + +static int __init uefi_init(void) +{ + efi_char16_t *c16; + void *config_tables; + u64 table_size; + char vendor[100] = "unknown"; + int i, retval; + + efi.systab = early_memremap(efi_system_table, + sizeof(efi_system_table_t)); + if (efi.systab == NULL) { + pr_warn("Unable to map EFI system table.\n"); + return -ENOMEM; + } + + set_bit(EFI_BOOT, &efi.flags); + set_bit(EFI_64BIT, &efi.flags); + + /* + * Verify the EFI Table + */ + if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) { + pr_err("System table signature incorrect\n"); + retval = -EINVAL; + goto out; + } + if ((efi.systab->hdr.revision >> 16) < 2) + pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n", + efi.systab->hdr.revision >> 16, + efi.systab->hdr.revision & 0xffff); + + /* Show what we know for posterity */ + c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor), + sizeof(vendor)); + if (c16) { + for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i) + vendor[i] = c16[i]; + vendor[i] = '\0'; + early_memunmap(c16, sizeof(vendor)); + } + + pr_info("EFI v%u.%.02u by %s\n", + efi.systab->hdr.revision >> 16, + efi.systab->hdr.revision & 0xffff, vendor); + + table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables; + config_tables = early_memremap(efi_to_phys(efi.systab->tables), + table_size); + + retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, + sizeof(efi_config_table_64_t), NULL); + + early_memunmap(config_tables, table_size); +out: + early_memunmap(efi.systab, sizeof(efi_system_table_t)); + return retval; +} + +/* + * Return true for RAM regions we want to permanently reserve. + */ +static __init int is_reserve_region(efi_memory_desc_t *md) +{ + switch (md->type) { + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + case EFI_CONVENTIONAL_MEMORY: + return 0; + default: + break; + } + return is_normal_ram(md); +} + +static __init void reserve_regions(void) +{ + efi_memory_desc_t *md; + u64 paddr, npages, size; + + if (uefi_debug) + pr_info("Processing EFI memory map:\n"); + + for_each_efi_memory_desc(&memmap, md) { + paddr = md->phys_addr; + npages = md->num_pages; + + if (uefi_debug) { + char buf[64]; + + pr_info(" 0x%012llx-0x%012llx %s", + paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1, + efi_md_typeattr_format(buf, sizeof(buf), md)); + } + + memrange_efi_to_native(&paddr, &npages); + size = npages << PAGE_SHIFT; + + if (is_normal_ram(md)) + early_init_dt_add_memory_arch(paddr, size); + + if (is_reserve_region(md)) { + memblock_reserve(paddr, size); + if (uefi_debug) + pr_cont("*"); + } + + if (uefi_debug) + pr_cont("\n"); + } + + set_bit(EFI_MEMMAP, &efi.flags); +} + +void __init efi_init(void) +{ + struct efi_fdt_params params; + + /* Grab UEFI information placed in FDT by stub */ + if (!efi_get_fdt_params(¶ms, uefi_debug)) + return; + + efi_system_table = params.system_table; + + memblock_reserve(params.mmap & PAGE_MASK, + PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK))); + memmap.phys_map = (void *)params.mmap; + memmap.map = early_memremap(params.mmap, params.mmap_size); + memmap.map_end = memmap.map + params.mmap_size; + memmap.desc_size = params.desc_size; + memmap.desc_version = params.desc_ver; + + if (uefi_init() < 0) + return; + + reserve_regions(); + early_memunmap(memmap.map, params.mmap_size); +} diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c new file mode 100644 index 000000000000..a8243018dfec --- /dev/null +++ b/drivers/firmware/efi/arm-runtime.c @@ -0,0 +1,150 @@ +/* + * Extensible Firmware Interface + * + * Based on Extensible Firmware Interface Specification version 2.4 + * + * Copyright (C) 2013, 2014 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/efi.h> +#include <linux/memblock.h> +#include <linux/mm_types.h> +#include <linux/preempt.h> +#include <linux/rbtree.h> +#include <linux/rwsem.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#include <asm/cacheflush.h> +#include <asm/efi.h> +#include <asm/tlbflush.h> +#include <asm/mmu_context.h> +#include <asm/mmu.h> +#include <asm/pgtable.h> + +static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss; + +static struct mm_struct efi_mm = { + .mm_rb = RB_ROOT, + .pgd = efi_pgd, + .mm_users = ATOMIC_INIT(2), + .mm_count = ATOMIC_INIT(1), + .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem), + .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock), + .mmlist = LIST_HEAD_INIT(efi_mm.mmlist), + INIT_MM_CONTEXT(efi_mm) +}; + +static bool __init efi_virtmap_init(void) +{ + efi_memory_desc_t *md; + + for_each_efi_memory_desc(&memmap, md) { + u64 paddr, npages, size; + pgprot_t prot; + + if (!(md->attribute & EFI_MEMORY_RUNTIME)) + continue; + if (md->virt_addr == 0) + return false; + + paddr = md->phys_addr; + npages = md->num_pages; + memrange_efi_to_native(&paddr, &npages); + size = npages << PAGE_SHIFT; + + pr_info(" EFI remap 0x%016llx => %p\n", + md->phys_addr, (void *)md->virt_addr); + + /* + * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be + * executable, everything else can be mapped with the XN bits + * set. + */ + if (md->type == EFI_MEMORY_MAPPED_IO) + prot = __pgprot(PROT_DEVICE_nGnRE); + else if (md->type == EFI_RUNTIME_SERVICES_CODE) + prot = PAGE_KERNEL_EXEC; + else + prot = PAGE_KERNEL; + + create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot); + } + return true; +} + +/* + * Enable the UEFI Runtime Services if all prerequisites are in place, i.e., + * non-early mapping of the UEFI system table and virtual mappings for all + * EFI_MEMORY_RUNTIME regions. + */ +static int __init arm64_enable_runtime_services(void) +{ + u64 mapsize; + + if (!efi_enabled(EFI_BOOT)) { + pr_info("EFI services will not be available.\n"); + return -1; + } + + if (efi_runtime_disabled()) { + pr_info("EFI runtime services will be disabled.\n"); + return -1; + } + + pr_info("Remapping and enabling EFI services.\n"); + + mapsize = memmap.map_end - memmap.map; + memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map, + mapsize); + if (!memmap.map) { + pr_err("Failed to remap EFI memory map\n"); + return -1; + } + memmap.map_end = memmap.map + mapsize; + efi.memmap = &memmap; + + if (!efi_virtmap_init()) { + pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); + return -1; + } + + /* Set up runtime services function pointers */ + efi_native_runtime_setup(); + set_bit(EFI_RUNTIME_SERVICES, &efi.flags); + + efi.runtime_version = efi.systab->hdr.revision; + + return 0; +} +early_initcall(arm64_enable_runtime_services); + +static void efi_set_pgd(struct mm_struct *mm) +{ + if (mm == &init_mm) + cpu_set_reserved_ttbr0(); + else + cpu_switch_mm(mm->pgd, mm); + + flush_tlb_all(); + if (icache_is_aivivt()) + __flush_icache_all(); +} + +void efi_virtmap_load(void) +{ + preempt_disable(); + efi_set_pgd(&efi_mm); +} + +void efi_virtmap_unload(void) +{ + efi_set_pgd(current->active_mm); + preempt_enable(); +}
This refactors the EFI init and runtime code that is now shared between arm64 and ARM so that: - 64-bit specific types and flags are made build-time conditional - the code sequences that use early memremap/memunmap are reshuffled so that they can be implemented using fixmap on ARM - take a copy of the EFI system table rather than keep it mapped.
This allows the same code to be built and run for arm64 and ARM.
Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- arch/arm64/include/asm/efi.h | 29 +++++++++++++++ drivers/firmware/efi/arm-init.c | 73 +++++++++++++++++++++----------------- drivers/firmware/efi/arm-runtime.c | 46 ++++++++++-------------- 3 files changed, 89 insertions(+), 59 deletions(-)
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index ef572206f1c3..c822af4a8ff8 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -1,8 +1,11 @@ #ifndef _ASM_EFI_H #define _ASM_EFI_H
+#include <asm/early_ioremap.h> #include <asm/io.h> +#include <asm/mmu_context.h> #include <asm/neon.h> +#include <asm/tlbflush.h>
#ifdef CONFIG_EFI extern void efi_init(void); @@ -10,6 +13,20 @@ extern void efi_init(void); #define efi_init() #endif
+typedef pgprot_t __arm_efi_prot_t; + +#define __EFI_DEVICE __pgprot(PROT_DEVICE_nGnRE) +#define __EFI_MEMORY_RW PAGE_KERNEL +#define __EFI_MEMORY_RWX PAGE_KERNEL_EXEC + +#define __arm_efi_early_memremap early_memremap +#define __arm_efi_early_memunmap early_memunmap + +#define __arm_efi_memremap ioremap_cache +#define __arm_efi_memunmap iounmap + +#define create_efi_mapping create_pgd_mapping + #define efi_call_virt(f, ...) \ ({ \ efi_##f##_t *__f; \ @@ -63,6 +80,18 @@ extern void efi_init(void); * Services are enabled and the EFI_RUNTIME_SERVICES bit set. */
+static inline void efi_set_pgd(struct mm_struct *mm) +{ + if (mm == &init_mm) + cpu_set_reserved_ttbr0(); + else + cpu_switch_mm(mm->pgd, mm); + + flush_tlb_all(); + if (icache_is_aivivt()) + __flush_icache_all(); +} + void efi_virtmap_load(void); void efi_virtmap_unload(void);
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 12e666ac6a34..b28d020a97c2 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -62,62 +62,51 @@ static phys_addr_t efi_to_phys(unsigned long addr) return addr; }
-static int __init uefi_init(void) +static void __init uefi_init(phys_addr_t fw_vendor, phys_addr_t tables) { + const int sizeof_config_table = IS_ENABLED(CONFIG_64BIT) ? + sizeof(efi_config_table_64_t) : + sizeof(efi_config_table_32_t); efi_char16_t *c16; void *config_tables; - u64 table_size; + int table_size; char vendor[100] = "unknown"; int i, retval;
- efi.systab = early_memremap(efi_system_table, - sizeof(efi_system_table_t)); - if (efi.systab == NULL) { - pr_warn("Unable to map EFI system table.\n"); - return -ENOMEM; - } - - set_bit(EFI_BOOT, &efi.flags); - set_bit(EFI_64BIT, &efi.flags); - /* * Verify the EFI Table */ if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) { pr_err("System table signature incorrect\n"); - retval = -EINVAL; - goto out; + return; } + set_bit(EFI_SYSTEM_TABLES, &efi.flags); + if ((efi.systab->hdr.revision >> 16) < 2) pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n", efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff);
/* Show what we know for posterity */ - c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor), - sizeof(vendor)); + c16 = __arm_efi_early_memremap(fw_vendor, sizeof(vendor)); if (c16) { for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i) vendor[i] = c16[i]; vendor[i] = '\0'; - early_memunmap(c16, sizeof(vendor)); + __arm_efi_early_memunmap(c16, sizeof(vendor)); }
pr_info("EFI v%u.%.02u by %s\n", efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
- table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables; - config_tables = early_memremap(efi_to_phys(efi.systab->tables), - table_size); + table_size = sizeof_config_table * efi.systab->nr_tables; + config_tables = __arm_efi_early_memremap(tables, table_size);
retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, - sizeof(efi_config_table_64_t), NULL); + sizeof_config_table, NULL);
- early_memunmap(config_tables, table_size); -out: - early_memunmap(efi.systab, sizeof(efi_system_table_t)); - return retval; + __arm_efi_early_memunmap(config_tables, table_size); }
/* @@ -179,25 +168,45 @@ static __init void reserve_regions(void)
void __init efi_init(void) { + static efi_system_table_t cached_efi_systab; struct efi_fdt_params params; + efi_system_table_t *efi_systab; + phys_addr_t fw_vendor, tables;
/* Grab UEFI information placed in FDT by stub */ if (!efi_get_fdt_params(¶ms, uefi_debug)) return;
- efi_system_table = params.system_table; + set_bit(EFI_BOOT, &efi.flags); + if (IS_ENABLED(CONFIG_64BIT)) + set_bit(EFI_64BIT, &efi.flags); + + efi_systab = __arm_efi_early_memremap(params.system_table, + sizeof(efi_system_table_t)); + if (efi_systab == NULL) { + pr_warn("Unable to map EFI system table.\n"); + return; + } + + cached_efi_systab = *efi_systab; + efi.systab = &cached_efi_systab; + + __arm_efi_early_memunmap(efi_systab, sizeof(efi_system_table_t));
memblock_reserve(params.mmap & PAGE_MASK, PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK))); - memmap.phys_map = (void *)params.mmap; - memmap.map = early_memremap(params.mmap, params.mmap_size); + memmap.phys_map = (void *)(unsigned long)params.mmap; + memmap.map = __arm_efi_early_memremap(params.mmap, params.mmap_size); memmap.map_end = memmap.map + params.mmap_size; memmap.desc_size = params.desc_size; memmap.desc_version = params.desc_ver;
- if (uefi_init() < 0) - return; - reserve_regions(); - early_memunmap(memmap.map, params.mmap_size); + + fw_vendor = efi_to_phys(efi.systab->fw_vendor); + tables = efi_to_phys(efi.systab->tables); + + __arm_efi_early_memunmap(memmap.map, params.mmap_size); + + uefi_init(fw_vendor, tables); } diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index a8243018dfec..de5086fc44e1 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -23,16 +23,17 @@
#include <asm/cacheflush.h> #include <asm/efi.h> -#include <asm/tlbflush.h> -#include <asm/mmu_context.h> +#include <asm/io.h> #include <asm/mmu.h> +#include <asm/pgalloc.h> #include <asm/pgtable.h>
-static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss; +#ifndef INIT_MM_CONTEXT +#define INIT_MM_CONTEXT(name) +#endif
static struct mm_struct efi_mm = { .mm_rb = RB_ROOT, - .pgd = efi_pgd, .mm_users = ATOMIC_INIT(2), .mm_count = ATOMIC_INIT(1), .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem), @@ -45,9 +46,11 @@ static bool __init efi_virtmap_init(void) { efi_memory_desc_t *md;
+ efi_mm.pgd = pgd_alloc(&efi_mm); + for_each_efi_memory_desc(&memmap, md) { u64 paddr, npages, size; - pgprot_t prot; + __arm_efi_prot_t prot;
if (!(md->attribute & EFI_MEMORY_RUNTIME)) continue; @@ -59,8 +62,8 @@ static bool __init efi_virtmap_init(void) memrange_efi_to_native(&paddr, &npages); size = npages << PAGE_SHIFT;
- pr_info(" EFI remap 0x%016llx => %p\n", - md->phys_addr, (void *)md->virt_addr); + pr_info(" EFI remap %pa => %p\n", + &md->phys_addr, (void *)(unsigned long)md->virt_addr);
/* * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be @@ -68,13 +71,13 @@ static bool __init efi_virtmap_init(void) * set. */ if (md->type == EFI_MEMORY_MAPPED_IO) - prot = __pgprot(PROT_DEVICE_nGnRE); + prot = __EFI_DEVICE; else if (md->type == EFI_RUNTIME_SERVICES_CODE) - prot = PAGE_KERNEL_EXEC; + prot = __EFI_MEMORY_RWX; else - prot = PAGE_KERNEL; + prot = __EFI_MEMORY_RW;
- create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot); + create_efi_mapping(&efi_mm, paddr, md->virt_addr, size, prot); } return true; } @@ -84,7 +87,7 @@ static bool __init efi_virtmap_init(void) * non-early mapping of the UEFI system table and virtual mappings for all * EFI_MEMORY_RUNTIME regions. */ -static int __init arm64_enable_runtime_services(void) +static int __init arm_enable_runtime_services(void) { u64 mapsize;
@@ -101,8 +104,8 @@ static int __init arm64_enable_runtime_services(void) pr_info("Remapping and enabling EFI services.\n");
mapsize = memmap.map_end - memmap.map; - memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map, - mapsize); + memmap.map = (__force void *)__arm_efi_memremap( + (phys_addr_t)(unsigned long)memmap.phys_map, mapsize); if (!memmap.map) { pr_err("Failed to remap EFI memory map\n"); return -1; @@ -114,6 +117,7 @@ static int __init arm64_enable_runtime_services(void) pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); return -1; } + __arm_efi_memunmap(memmap.map);
/* Set up runtime services function pointers */ efi_native_runtime_setup(); @@ -123,19 +127,7 @@ static int __init arm64_enable_runtime_services(void)
return 0; } -early_initcall(arm64_enable_runtime_services); - -static void efi_set_pgd(struct mm_struct *mm) -{ - if (mm == &init_mm) - cpu_set_reserved_ttbr0(); - else - cpu_switch_mm(mm->pgd, mm); - - flush_tlb_all(); - if (icache_is_aivivt()) - __flush_icache_all(); -} +early_initcall(arm_enable_runtime_services);
void efi_virtmap_load(void) {
In preparation of adding EFI support, this moves the population of the fixmap region to an earlier stage so that it can be used by the EFI init code to discover the system's memory.
Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- arch/arm/kernel/setup.c | 2 ++ arch/arm/mm/mmu.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 6c777e908a24..a88d377848f2 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -80,6 +80,7 @@ extern void early_paging_init(const struct machine_desc *, extern void sanity_check_meminfo(void); extern enum reboot_mode reboot_mode; extern void setup_dma_zone(const struct machine_desc *desc); +extern void early_fixmap_init(void);
unsigned int processor_id; EXPORT_SYMBOL(processor_id); @@ -938,6 +939,7 @@ void __init setup_arch(char **cmdline_p)
early_paging_init(mdesc, lookup_processor_type(read_cpuid_id())); setup_dma_zone(mdesc); + early_fixmap_init(); sanity_check_meminfo(); arm_memblock_init(mdesc);
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4e6ef896c619..8bb55c99dbfa 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1321,9 +1321,17 @@ static void __init kmap_init(void) pkmap_page_table = early_pte_alloc(pmd_off_k(PKMAP_BASE), PKMAP_BASE, _PAGE_KERNEL_TABLE); #endif +} + +void __init early_fixmap_init(void) +{ + static u8 fixmap_pte[PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE] __page_aligned_bss; + pmd_t *pmd = pmd_off_k(FIXADDR_START);
- early_pte_alloc(pmd_off_k(FIXADDR_START), FIXADDR_START, - _PAGE_KERNEL_TABLE); + if (pmd_none(*pmd)) + __pmd_populate(pmd, __pa(fixmap_pte), _PAGE_KERNEL_TABLE); + + BUG_ON(pmd_bad(*pmd)); }
static void __init map_lowmem(void)
This splits off the core code from create_mapping() so that we can reuse it for populating the UEFI Runtime Services page tables.
Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- arch/arm/include/asm/mach/map.h | 1 + arch/arm/mm/mmu.c | 56 +++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 25 deletions(-)
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h index f98c7f32c9c8..39fbe558f6a9 100644 --- a/arch/arm/include/asm/mach/map.h +++ b/arch/arm/include/asm/mach/map.h @@ -42,6 +42,7 @@ enum { extern void iotable_init(struct map_desc *, int); extern void vm_reserve_area_early(unsigned long addr, unsigned long size, void *caller); +extern void __create_mapping(struct mm_struct *mm, struct map_desc *md);
#ifdef CONFIG_DEBUG_LL extern void debug_ll_addr(unsigned long *paddr, unsigned long *vaddr); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 8bb55c99dbfa..e3495b1acb8d 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -776,7 +776,8 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, }
#ifndef CONFIG_ARM_LPAE -static void __init create_36bit_mapping(struct map_desc *md, +static void __init create_36bit_mapping(struct mm_struct *mm, + struct map_desc *md, const struct mem_type *type) { unsigned long addr, length, end; @@ -817,7 +818,7 @@ static void __init create_36bit_mapping(struct map_desc *md, */ phys |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
- pgd = pgd_offset_k(addr); + pgd = pgd_offset(mm, addr); end = addr + length; do { pud_t *pud = pud_offset(pgd, addr); @@ -834,33 +835,13 @@ static void __init create_36bit_mapping(struct map_desc *md, } #endif /* !CONFIG_ARM_LPAE */
-/* - * Create the page directory entries and any necessary - * page tables for the mapping specified by `md'. We - * are able to cope here with varying sizes and address - * offsets, and we take full advantage of sections and - * supersections. - */ -static void __init create_mapping(struct map_desc *md) +void __init __create_mapping(struct mm_struct *mm, struct map_desc *md) { unsigned long addr, length, end; phys_addr_t phys; const struct mem_type *type; pgd_t *pgd;
- if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { - pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n", - (long long)__pfn_to_phys((u64)md->pfn), md->virtual); - return; - } - - if ((md->type == MT_DEVICE || md->type == MT_ROM) && - md->virtual >= PAGE_OFFSET && - (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { - pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n", - (long long)__pfn_to_phys((u64)md->pfn), md->virtual); - } - type = &mem_types[md->type];
#ifndef CONFIG_ARM_LPAE @@ -868,7 +849,7 @@ static void __init create_mapping(struct map_desc *md) * Catch 36-bit addresses */ if (md->pfn >= 0x100000) { - create_36bit_mapping(md, type); + create_36bit_mapping(mm, md, type); return; } #endif @@ -883,7 +864,7 @@ static void __init create_mapping(struct map_desc *md) return; }
- pgd = pgd_offset_k(addr); + pgd = pgd_offset(mm, addr); end = addr + length; do { unsigned long next = pgd_addr_end(addr, end); @@ -896,6 +877,31 @@ static void __init create_mapping(struct map_desc *md) }
/* + * Create the page directory entries and any necessary + * page tables for the mapping specified by `md'. We + * are able to cope here with varying sizes and address + * offsets, and we take full advantage of sections and + * supersections. + */ +static void __init create_mapping(struct map_desc *md) +{ + if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { + pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n", + (long long)__pfn_to_phys((u64)md->pfn), md->virtual); + return; + } + + if ((md->type == MT_DEVICE || md->type == MT_ROM) && + md->virtual >= PAGE_OFFSET && + (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) { + pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n", + (long long)__pfn_to_phys((u64)md->pfn), md->virtual); + } + + __create_mapping(&init_mm, md); +} + +/* * Create the architecture specific mappings */ void __init iotable_init(struct map_desc *io_desc, int nr)
From: Roy Franz roy.franz@linaro.org
The shared efi-stub-helper.c functions require additional string helper functions compared to the base zImage. This patch adds strstr() and strncmp() implementations to the string.c file for the decompressor, with the implementation copied from lib/string.c.
Signed-off-by: Roy Franz roy.franz@linaro.org [Added strncmp, commit message update.] Signed-off-by: Leif Lindholm leif.lindholm@linaro.org Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- arch/arm/boot/compressed/string.c | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c index 36e53ef9200f..11392787086c 100644 --- a/arch/arm/boot/compressed/string.c +++ b/arch/arm/boot/compressed/string.c @@ -93,6 +93,28 @@ int strcmp(const char *cs, const char *ct) return res; }
+/** + * strncmp - Compare two length-limited strings + * @cs: One string + * @ct: Another string + * @count: The maximum number of bytes to compare + */ +int strncmp(const char *cs, const char *ct, size_t count) +{ + unsigned char c1, c2; + + while (count) { + c1 = *cs++; + c2 = *ct++; + if (c1 != c2) + return c1 < c2 ? -1 : 1; + if (!c1) + break; + count--; + } + return 0; +} + void *memchr(const void *s, int c, size_t count) { const unsigned char *p = s; @@ -111,6 +133,27 @@ char *strchr(const char *s, int c) return (char *)s; }
+/** + * strstr - Find the first substring in a %NUL terminated string + * @s1: The string to be searched + * @s2: The string to search for + */ +char *strstr(const char *s1, const char *s2) +{ + size_t l1, l2; + + l2 = strlen(s2); + if (!l2) + return (char *)s1; + l1 = strlen(s1); + while (l1 >= l2) { + l1--; + if (!memcmp(s1, s2, l2)) + return (char *)s1; + s1++; + } + return NULL; +} #undef memset
void *memset(void *s, int c, size_t count)
This patch adds EFI support for the ARM Linux kernel.
The EFI stub operates similarly to the x86 and arm64 stubs: it is a shim between the EFI firmware and the normal zImage entry point, and sets up the environment that the zImage is expecting. This includes optionally loading the initrd and device tree from the system partition based on the kernel command line.
Signed-off-by: Roy Franz roy.franz@linaro.org Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- arch/arm/Kconfig | 19 +++++ arch/arm/boot/compressed/.gitignore | 2 + arch/arm/boot/compressed/Makefile | 18 +++-- arch/arm/boot/compressed/efi-header.S | 141 ++++++++++++++++++++++++++++++++++ arch/arm/boot/compressed/efi-stub.c | 89 +++++++++++++++++++++ arch/arm/boot/compressed/head.S | 66 +++++++++++++++- arch/arm/include/asm/efi.h | 135 ++++++++++++++++++++++++++++++++ arch/arm/include/asm/fixmap.h | 4 + arch/arm/kernel/setup.c | 3 + 9 files changed, 471 insertions(+), 6 deletions(-) create mode 100644 arch/arm/boot/compressed/efi-header.S create mode 100644 arch/arm/boot/compressed/efi-stub.c create mode 100644 arch/arm/include/asm/efi.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 45df48ba0b12..44ed539d2799 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1990,6 +1990,25 @@ config AUTO_ZRELADDR 0xf8000000. This assumes the zImage being placed in the first 128MB from start of memory.
+config EFI_STUB + bool + +config EFI + bool "UEFI runtime service support" + depends on OF && !CPU_BIG_ENDIAN && HIGHMEM + select UCS2_STRING + select EFI_PARAMS_FROM_FDT + select EFI_STUB + select EFI_ARMSTUB + select EFI_RUNTIME_WRAPPERS + ---help--- + This option provides support for runtime services provided + by UEFI firmware (such as non-volatile variables, realtime + clock, and platform reset). A UEFI stub is also provided to + allow the kernel to be booted as an EFI application. This + is only useful for kernels that may run on systems that have + UEFI firmware. + endmenu
menu "CPU Power Management" diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index 0714e0334e33..cc3487ec5b4d 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -14,8 +14,10 @@ vmlinux.lds # borrowed libfdt files fdt.c fdt.h +fdt_empty_tree.c fdt_ro.c fdt_rw.c +fdt_sw.c fdt_wip.c libfdt.h libfdt_internal.h diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 6e1fb2b2ecc7..48cd1fb8bdb2 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -76,9 +76,9 @@ suffix_$(CONFIG_KERNEL_LZMA) = lzma suffix_$(CONFIG_KERNEL_XZ) = xzkern suffix_$(CONFIG_KERNEL_LZ4) = lz4
-# Borrowed libfdt files for the ATAG compatibility mode +# Borrowed libfdt files for the ATAG compatibility mode and EFI stub support
-libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c +libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c libfdt_hdrs := fdt.h libfdt.h libfdt_internal.h
libfdt_objs := $(addsuffix .o, $(basename $(libfdt))) @@ -86,11 +86,19 @@ libfdt_objs := $(addsuffix .o, $(basename $(libfdt))) $(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/% $(call cmd,shipped)
-$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \ +$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o efi-stub.o): \ $(addprefix $(obj)/,$(libfdt_hdrs))
-ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y) -OBJS += $(libfdt_objs) atags_to_fdt.o +fdt-obj-$(CONFIG_ARM_ATAG_DTB_COMPAT) += atags_to_fdt.o +fdt-obj-$(CONFIG_EFI) += efi-stub.o efi-banner.o \ + ../../../../drivers/firmware/efi/libstub/lib.a + +$(obj)/efi-banner.o: OBJCOPYFLAGS=-j .rodata +$(obj)/efi-banner.o: $(objtree)/init/version.o FORCE + $(call if_changed,objcopy) + +ifneq ($(fdt-obj-y),) +OBJS += $(libfdt_objs) $(fdt-obj-y) endif
targets := vmlinux vmlinux.lds \ diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S new file mode 100644 index 000000000000..da25dbd4d77e --- /dev/null +++ b/arch/arm/boot/compressed/efi-header.S @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2013-2015 Linaro Ltd + * Authors: Roy Franz roy.franz@linaro.org + * Ard Biesheuvel ard.biesheuvel@linaro.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifdef CONFIG_EFI +#define NOP __efi_nop +#endif + + .macro __efi_nop + @ This is almost but not quite a NOP, since it does clobber the + @ condition flags. But is the best we can do for EFI, since PE/COFF + @ expects the magic string "MZ" at offset 0, while the ARM/Linux boot + @ protocol expects an executable instruction there. + .inst 0xe1005a4d @ tst r0, sp, asr #20 + .endm + + .macro __EFI_HEADER +#ifdef CONFIG_EFI + .set start_offset, __efi_start - start + .org 0x3c + @ + @ The PE header can be anywhere in the file, but for + @ simplicity we keep it together with the MSDOS header + @ The offset to the PE/COFF header needs to be at offset + @ 0x3C in the MSDOS header. + @ The only 2 fields of the MSDOS header that are used are this + @ PE/COFF offset, and the "MZ" bytes at offset 0x0. + @ + .long pe_header - start @ Offset to the PE header. + + .align 3 +pe_header: + .ascii "PE" + .short 0 + +coff_header: + .short 0x01c2 @ ARM or Thumb + .short 2 @ nr_sections + .long 0 @ TimeDateStamp + .long 0 @ PointerToSymbolTable + .long 1 @ NumberOfSymbols + .short section_table - optional_header @ SizeOfOptionalHeader + .short 0x306 @ Characteristics. + @ IMAGE_FILE_32BIT_MACHINE | + @ IMAGE_FILE_DEBUG_STRIPPED | + @ IMAGE_FILE_EXECUTABLE_IMAGE | + @ IMAGE_FILE_LINE_NUMS_STRIPPED + +optional_header: + .short 0x10b @ PE32 format + .byte 0x02 @ MajorLinkerVersion + .byte 0x14 @ MinorLinkerVersion + + .long _end - __efi_start @ SizeOfCode + + .long 0 @ SizeOfInitializedData + .long 0 @ SizeOfUninitializedData + + .long efi_stub_entry - start @ AddressOfEntryPoint + .long start_offset @ BaseOfCode + .long 0 @ data + +extra_header_fields: + .long 0 @ ImageBase + .long 0x200 @ SectionAlignment + .long 0x200 @ FileAlignment + .short 0 @ MajorOperatingSystemVersion + .short 0 @ MinorOperatingSystemVersion + .short 0 @ MajorImageVersion + .short 0 @ MinorImageVersion + .short 0 @ MajorSubsystemVersion + .short 0 @ MinorSubsystemVersion + .long 0 @ Win32VersionValue + + .long _end - start @ SizeOfImage + + @ Everything before the entry point is considered part of the header + .long start_offset @ SizeOfHeaders + .long 0 @ CheckSum + .short 0xa @ Subsystem (EFI application) + .short 0 @ DllCharacteristics + .long 0 @ SizeOfStackReserve + .long 0 @ SizeOfStackCommit + .long 0 @ SizeOfHeapReserve + .long 0 @ SizeOfHeapCommit + .long 0 @ LoaderFlags + .long 0x6 @ NumberOfRvaAndSizes + + .quad 0 @ ExportTable + .quad 0 @ ImportTable + .quad 0 @ ResourceTable + .quad 0 @ ExceptionTable + .quad 0 @ CertificationTable + .quad 0 @ BaseRelocationTable + # Section table +section_table: + + # + # The EFI application loader requires a relocation section + # because EFI applications must be relocatable. This is a + # dummy section as far as we are concerned. + # + .ascii ".reloc" + .byte 0 + .byte 0 @ end of 0 padding of section name + .long 0 + .long 0 + .long 0 @ SizeOfRawData + .long 0 @ PointerToRawData + .long 0 @ PointerToRelocations + .long 0 @ PointerToLineNumbers + .short 0 @ NumberOfRelocations + .short 0 @ NumberOfLineNumbers + .long 0x42100040 @ Characteristics (section flags) + + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 @ end of 0 padding of section name + .long _end - __efi_start @ VirtualSize + .long __efi_start @ VirtualAddress + .long _edata - __efi_start @ SizeOfRawData + .long __efi_start @ PointerToRawData + + .long 0 @ PointerToRelocations (0 for executables) + .long 0 @ PointerToLineNumbers (0 for executables) + .short 0 @ NumberOfRelocations (0 for executables) + .short 0 @ NumberOfLineNumbers (0 for executables) + .long 0xe0500020 @ Characteristics (section flags) + + .align 9 +__efi_start: +#endif + .endm diff --git a/arch/arm/boot/compressed/efi-stub.c b/arch/arm/boot/compressed/efi-stub.c new file mode 100644 index 000000000000..34b76f7742f9 --- /dev/null +++ b/arch/arm/boot/compressed/efi-stub.c @@ -0,0 +1,89 @@ +/* + * linux/arch/arm/boot/compressed/efi-stub.c + * + * Copyright (C) 2013 Linaro Ltd; roy.franz@linaro.org + * + * This file implements the EFI boot stub for the ARM kernel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include <linux/efi.h> +#include <asm/efi.h> + +efi_status_t handle_kernel_image(efi_system_table_t *sys_table, + unsigned long *image_addr, + unsigned long *image_size, + unsigned long *reserve_addr, + unsigned long *reserve_size, + unsigned long dram_base, + efi_loaded_image_t *image) +{ + unsigned long nr_pages; + efi_status_t status; + /* Use alloc_addr to tranlsate between types */ + efi_physical_addr_t alloc_addr; + + /* + * Verify that the DRAM base address is compatible the the ARM + * boot protocol, which determines the base of DRAM by masking + * off the low 24 bits of the address at which the zImage is + * loaded. These assumptions are made by the decompressor, + * before any memory map is available. + */ + dram_base = round_up(dram_base, SZ_128M); + + /* + * Reserve memory for the uncompressed kernel image. This is + * all that prevents any future allocations from conflicting + * with the kernel. Since we can't tell from the compressed + * image how much DRAM the kernel actually uses (due to BSS + * size uncertainty) we allocate the maximum possible size. + * Do this very early, as prints can cause memory allocations + * that may conflict with this. + */ + alloc_addr = dram_base; + *reserve_size = MAX_UNCOMP_KERNEL_SIZE; + nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; + status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS, + EFI_LOADER_DATA, + nr_pages, &alloc_addr); + if (status != EFI_SUCCESS) { + *reserve_size = 0; + pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n"); + return status; + } + *reserve_addr = alloc_addr; + + /* + * Relocate the zImage, if required. ARM doesn't have a + * preferred address, so we set it to 0, as we want to allocate + * as low in memory as possible. + */ + *image_size = image->image_size; + status = efi_relocate_kernel(sys_table, image_addr, *image_size, + *image_size, 0, 0); + if (status != EFI_SUCCESS) { + pr_efi_err(sys_table, "Failed to relocate kernel.\n"); + efi_free(sys_table, *reserve_size, *reserve_addr); + *reserve_size = 0; + return status; + } + + /* + * Check to see if we were able to allocate memory low enough + * in memory. The kernel determines the base of DRAM from the + * address at which the zImage is loaded. + */ + if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) { + pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n"); + efi_free(sys_table, *reserve_size, *reserve_addr); + *reserve_size = 0; + efi_free(sys_table, *image_size, *image_addr); + *image_size = 0; + return EFI_LOAD_ERROR; + } + return EFI_SUCCESS; +} diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 2c45b5709fa4..3e8315b703d2 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -12,6 +12,16 @@ #include <asm/assembler.h> #include <asm/v7m.h>
+#include "efi-header.S" + +#ifndef NOP +#define NOP __nop +#endif + + .macro __nop + mov r0, r0 + .endm + AR_CLASS( .arch armv7-a ) M_CLASS( .arch armv7-m )
@@ -126,7 +136,7 @@ start: .type start,#function .rept 7 - mov r0, r0 + NOP .endr ARM( mov r0, r0 ) ARM( b 1f ) @@ -138,6 +148,8 @@ start: .word _magic_end @ zImage end address .word 0x04030201 @ endianness flag
+ __EFI_HEADER + THUMB( .thumb ) 1: ARM_BE8( setend be ) @ go BE8 if compiled for BE8 @@ -1353,6 +1365,58 @@ __enter_kernel:
reloc_code_end:
+#ifdef CONFIG_EFI + AR_CLASS( .arm ) + .align 2 +ENTRY(efi_stub_entry) + @ Save lr on stack for possible return to EFI firmware. + @ Don't care about fp, but need 64 bit alignment.... + stmfd sp!, {fp, lr} + + @ allocate space on stack for passing current zImage address + @ and for the EFI stub to return of new entry point of + @ zImage, as EFI stub may copy the kernel. Pointer address + @ is passed in r2. r0 and r1 are passed through from the + @ EFI firmware to efi_entry + adr r3, _start + ldr r2, [r3] + add r3, r2, r3 + str r3, [sp, #-8]! + mov r2, sp @ pass pointer in r2 + bl efi_entry + ldr r3, [sp], #8 @ get new zImage address from stack + + @ Check for error return from EFI stub. r0 has FDT address + @ or error code. + cmn r0, #1 + beq efi_load_fail + + @ Save return values of efi_entry + stmfd sp!, {r0, r3} + bl cache_clean_flush + bl cache_off + ldmfd sp!, {r2, lr} + + @ Set parameters for booting zImage according to boot protocol + @ put FDT address in r2, it was returned by efi_entry() + @ r1 is the machine type, and r0 needs to be 0 + mov r0, #0 + mov r1, #0xFFFFFFFF + + @ Branch to (possibly) relocated zImage that is in lr + ldr ip, =start_offset + add lr, lr, ip + ret lr + +efi_load_fail: + @ Return EFI_LOAD_ERROR to EFI firmware on error. + ldr r0, =0x80000001 + ldmfd sp!, {fp, pc} +ENDPROC(efi_stub_entry) + +_start: .long start - . +#endif + .align .section ".stack", "aw", %nobits .L_user_stack: .space 4096 diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h new file mode 100644 index 000000000000..feeea7836d62 --- /dev/null +++ b/arch/arm/include/asm/efi.h @@ -0,0 +1,135 @@ +#ifndef _ASM_ARM_EFI_H +#define _ASM_ARM_EFI_H + +#include <asm/cacheflush.h> +#include <asm/cachetype.h> +#include <asm/fixmap.h> +#include <asm/highmem.h> +#include <asm/mach/map.h> +#include <asm/mmu_context.h> +#include <asm/pgtable.h> + +#ifdef CONFIG_EFI +extern void efi_init(void); + +typedef enum { + __EFI_DEVICE = MT_DEVICE, + __EFI_MEMORY_RW = MT_MEMORY_RW, + __EFI_MEMORY_RWX = MT_MEMORY_RWX, +} __arm_efi_prot_t; + +static inline void *__arm_efi_early_memremap(phys_addr_t pa, int size) +{ + u32 footprint = (pa & ~PAGE_MASK) + size; + pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY); + + /* + * Use two adjacent fixmap entries to create a mapping for + * [pa, pa + size>. This gives us between 4 KB and 8 KB of + * virtual space, depending on the alignment of pa. + */ + if (footprint > 2 * PAGE_SIZE) + return NULL; + + __set_fixmap(FIX_EFI_EARLY0, pa, prot); + + if (footprint > PAGE_SIZE) + __set_fixmap(FIX_EFI_EARLY1, pa + PAGE_SIZE, prot); + + return (void *)fix_to_virt(FIX_EFI_EARLY0) + (pa & ~PAGE_MASK); +} + +static inline void __arm_efi_early_memunmap(void *va, int size) +{ + __set_fixmap(FIX_EFI_EARLY0, 0, 0); + __set_fixmap(FIX_EFI_EARLY1, 0, 0); +} + +static inline void *__arm_efi_memremap(phys_addr_t phys_addr, size_t size) +{ + return kmap_atomic(phys_to_page(phys_addr)) + (phys_addr & ~PAGE_MASK); +} + +static inline void __arm_efi_memunmap(void *vaddr) +{ + __kunmap_atomic(vaddr); +} + +static inline void create_efi_mapping(struct mm_struct *mm, phys_addr_t phys, + unsigned long virt, phys_addr_t size, + __arm_efi_prot_t type) +{ + struct map_desc md = { + .virtual = virt, + .pfn = __phys_to_pfn(phys), + .length = size, + .type = (unsigned int)type, + }; + __create_mapping(mm, &md); +} + +#else +#define efi_init() +#endif /* CONFIG_EFI */ + +#define efi_call_virt(f, ...) \ +({ \ + efi_##f##_t *__f; \ + efi_status_t __s; \ + \ + efi_virtmap_load(); \ + __f = efi.systab->runtime->f; \ + __s = __f(__VA_ARGS__); \ + efi_virtmap_unload(); \ + __s; \ +}) + +#define __efi_call_virt(f, ...) \ +({ \ + efi_##f##_t *__f; \ + \ + efi_virtmap_load(); \ + __f = efi.systab->runtime->f; \ + __f(__VA_ARGS__); \ + efi_virtmap_unload(); \ +}) + +static inline void efi_set_pgd(struct mm_struct *mm) +{ + if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq)) + __check_vmalloc_seq(mm); + + cpu_switch_mm(mm->pgd, mm); + + flush_tlb_all(); + if (icache_is_vivt_asid_tagged()) + __flush_icache_all(); +} + +void efi_virtmap_load(void); +void efi_virtmap_unload(void); + +/* arch specific definitions used by the stub code */ + +#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) + +/* + * A reasonable upper bound for the uncompressed kernel size is 32 MBytes, + * so we will reserve that amount of memory. We have no easy way to tell what + * the actuall size of code + data the uncompressed kernel will use. + * If this is insufficient, the decompressor will relocate itself out of the + * way before performing the decompression. + */ +#define MAX_UNCOMP_KERNEL_SIZE SZ_32M + +/* + * The kernel zImage should preferably be located between 32 MB and 128 MB + * from the base of DRAM. The min address leaves space for a maximal size + * uncompressed image, and the max address is due to how the zImage decompressor + * picks a destination address. + */ +#define ZIMAGE_OFFSET_LIMIT SZ_128M +#define MIN_ZIMAGE_OFFSET MAX_UNCOMP_KERNEL_SIZE +#define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT + +#endif /* _ASM_ARM_EFI_H */ diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index 0415eae1df27..6580a225b91c 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h @@ -15,6 +15,10 @@ enum fixed_addresses { FIX_TEXT_POKE0, FIX_TEXT_POKE1,
+ /* reuse the poke0/poke1 fixmap slots for the early EFI init code */ + FIX_EFI_EARLY0 = FIX_TEXT_POKE0, + FIX_EFI_EARLY1 = FIX_TEXT_POKE1, + __end_of_fixed_addresses };
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index a88d377848f2..d10ddff8269f 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <linux/efi.h> #include <linux/export.h> #include <linux/kernel.h> #include <linux/stddef.h> @@ -36,6 +37,7 @@ #include <asm/cp15.h> #include <asm/cpu.h> #include <asm/cputype.h> +#include <asm/efi.h> #include <asm/elf.h> #include <asm/procinfo.h> #include <asm/psci.h> @@ -940,6 +942,7 @@ void __init setup_arch(char **cmdline_p) early_paging_init(mdesc, lookup_processor_type(read_cpuid_id())); setup_dma_zone(mdesc); early_fixmap_init(); + efi_init(); sanity_check_meminfo(); arm_memblock_init(mdesc);
On 29 April 2015 at 12:48, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
Yesterday and this morning, I had a go at bringing the 32-bit ARM EFI support in line with the current arm64 upstream code. I have reshuffled a lot of Roy's code, mainly so that the remaining delta against the ARM tree is as small as possible, and keeps out of existing early init code as much as possible. I have not reused any of the existing 32-bit runtime services code. I did not use the early ioremap support but instead refactored the existing init code lightly so that we can use two adjacent fixmap slots instead.
This mostly works, but there are (at least) two issues that need resolving:
- LPAE support builds but doesn't run
- the EFI page tables are clobbered at some point in the execution -> note in the log below that the RTC efi is read successfully once, but later on (when invoked by hwclock from userland), the page table entries have been cleared
I don't intend to burn a lot of time on this but it may be worthwile to run this on a model (with better watchpoint support) to figure out what is going on with the page tables. Not today though ....
Awesome stuff.
One comment though - more of the init code could be shared across all architectures, rather than just between arm/arm64. Especially the "check system table and print version/vendor string" bit. (I just never got around to doing that.)
Ard Biesheuvel (7): efi: avoid initialized .data in the EFI stub efi: build efi_config_init() only if CONFIG_EARLY_IOREMAP arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM ARM: move fixmap init before memblock init and use static allocation ARM: split off core code from create_mapping() for EFI reuse ARM: add UEFI support
Roy Franz (1): ARM: add strstr and strncmp to compressed string.c
arch/arm/Kconfig | 19 ++ arch/arm/boot/compressed/.gitignore | 2 + arch/arm/boot/compressed/Makefile | 18 +- arch/arm/boot/compressed/efi-header.S | 141 +++++++++++ arch/arm/boot/compressed/efi-stub.c | 89 +++++++ arch/arm/boot/compressed/head.S | 66 ++++- arch/arm/boot/compressed/string.c | 43 ++++ arch/arm/include/asm/efi.h | 135 ++++++++++ arch/arm/include/asm/fixmap.h | 4 + arch/arm/include/asm/mach/map.h | 1 + arch/arm/kernel/setup.c | 5 + arch/arm/mm/mmu.c | 68 +++-- arch/arm64/include/asm/efi.h | 29 +++ arch/arm64/kernel/efi.c | 330 +------------------------ drivers/firmware/efi/Makefile | 4 + drivers/firmware/efi/arm-init.c | 212 ++++++++++++++++ drivers/firmware/efi/arm-runtime.c | 142 +++++++++++ drivers/firmware/efi/efi.c | 2 + drivers/firmware/efi/libstub/efi-stub-helper.c | 8 +- 19 files changed, 952 insertions(+), 366 deletions(-) create mode 100644 arch/arm/boot/compressed/efi-header.S create mode 100644 arch/arm/boot/compressed/efi-stub.c create mode 100644 arch/arm/include/asm/efi.h create mode 100644 drivers/firmware/efi/arm-init.c create mode 100644 drivers/firmware/efi/arm-runtime.c
--
EFI stub: Booting Linux Kernel... EFI stub: Using DTB from configuration table EFI stub: Exiting boot services and installing virtual address map... [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 4.1.0-rc1-00008-gb6fc321f4ca5-dirty (ard@ards-macbook-pro) (gcc version 4.9.1 20140529 (prerelease) (crosstool-NG linaro-1.13.1-4.9-2014.06 - Linaro GCC 4.9-2014.06) ) #124 SMP Wed Apr 29 13:28:54 CEST 2015 [ 0.000000] CPU: ARMv7 Processor [412fc0f1] revision 1 (ARMv7), cr=10c5387d [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache [ 0.000000] Machine model: linux,dummy-virt [ 0.000000] earlycon: no match for ttyAMA0 [ 0.000000] efi: Getting EFI parameters from FDT: [ 0.000000] efi: System Table: 0x000000007fc25010 [ 0.000000] efi: MemMap Address: 0x0000000076b20010 [ 0.000000] efi: MemMap Size: 0x00000540 [ 0.000000] efi: MemMap Desc. Size: 0x00000030 [ 0.000000] efi: MemMap Desc. Version: 0x00000001 [ 0.000000] Processing EFI memory map: [ 0.000000] 0x000040000000-0x0000425f5fff [Loader Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x0000425f6000-0x000047fedfff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x000047fee000-0x000047ffffff [Loader Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000048000000-0x000076b1ffff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x000076b20000-0x000076b21fff [Loader Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000076b22000-0x000077116fff [Loader Code | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000077117000-0x00007711afff [Reserved | | | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007711b000-0x00007711cfff [ACPI Reclaim Memory| | | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007711d000-0x0000771dffff [Runtime Data |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x0000771e0000-0x000079e6bfff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x000079e6c000-0x00007a59cfff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007a59d000-0x00007a63afff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007a63b000-0x00007babbfff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007babc000-0x00007bb0afff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007bb0b000-0x00007bb19fff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007bb1a000-0x00007bb1efff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007bb1f000-0x00007c01ffff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007c020000-0x00007fabefff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fabf000-0x00007fbc7fff [Boot Code | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fbc8000-0x00007fbdbfff [Runtime Code |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007fbdc000-0x00007fc0dfff [Runtime Data |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007fc0e000-0x00007fc0ffff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fc10000-0x00007fc23fff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fc24000-0x00007fc24fff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fc25000-0x00007fc25fff [Runtime Data |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007fc26000-0x00007fffffff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000004000000-0x000007ffffff [Memory Mapped I/O |RUN| | | | | | | |UC] [ 0.000000] 0x000009010000-0x000009010fff [Memory Mapped I/O |RUN| | | | | | | |UC] [ 0.000000] EFI v2.40 by EDK II [ 0.000000] efi: [ 0.000000] cma: Reserved 64 MiB at 0x7b800000 [ 0.000000] Memory policy: Data cache writealloc [ 0.000000] psci: probing for conduit method from DT. [ 0.000000] psci: PSCIv0.2 detected in firmware. [ 0.000000] psci: Using standard PSCI v0.2 function IDs [ 0.000000] PERCPU: Embedded 12 pages/cpu @eefe3000 s16960 r8192 d24000 u49152 [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260624 [ 0.000000] Kernel command line: console=ttyAMA0 uefi_debug root=/dev/vda2 [ 0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes) [ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes) [ 0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes) [ 0.000000] Memory: 958824K/1048576K available (8132K kernel code, 967K rwdata, 3688K rodata, 828K init, 321K bss, 24216K reserved, 65536K cma-reserved, 203708K highmem) [ 0.000000] Virtual kernel memory layout: [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB) [ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB) [ 0.000000] vmalloc : 0xf0000000 - 0xff000000 ( 240 MB) [ 0.000000] lowmem : 0xc0000000 - 0xef800000 ( 760 MB) [ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB) [ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB) [ 0.000000] .text : 0xc0208000 - 0xc0d940e0 (11825 kB) [ 0.000000] .init : 0xc0d95000 - 0xc0e64000 ( 828 kB) [ 0.000000] .data : 0xc0e64000 - 0xc0f55f40 ( 968 kB) [ 0.000000] .bss : 0xc0f58000 - 0xc0fa86d8 ( 322 kB) [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 [ 0.000000] Hierarchical RCU implementation. [ 0.000000] Additional per-CPU info printed with stalls. [ 0.000000] RCU restricting CPUs from NR_CPUS=16 to nr_cpu_ids=1. [ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1 [ 0.000000] NR_IRQS:16 nr_irqs:16 16 [ 0.000000] Architected cp15 timer(s) running at 62.50MHz (virt). [ 0.000000] clocksource arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns [ 0.000118] sched_clock: 56 bits at 62MHz, resolution 16ns, wraps every 4398046511096ns [ 0.000226] Switching to timer-based delay loop, resolution 16ns [ 0.002942] Console: colour dummy device 80x30 [ 0.003398] Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=312500) [ 0.003518] pid_max: default: 32768 minimum: 301 [ 0.006917] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes) [ 0.006955] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes) [ 0.014326] CPU: Testing write buffer coherency: ok [ 0.020134] /cpus/cpu@0 missing clock-frequency property [ 0.020346] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 [ 0.020922] Setting up static identity map for 0x40209000 - 0x40209098 [ 0.028361] Brought up 1 CPUs [ 0.028426] SMP: Total of 1 processors activated (125.00 BogoMIPS). [ 0.028474] CPU: All CPU(s) started in SVC mode. [ 0.036288] devtmpfs: initialized [ 0.040769] VFP support v0.3: implementor 41 architecture 4 part 30 variant f rev 0 [ 0.053306] clocksource jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 9556302231375000 ns [ 0.064590] pinctrl core: initialized pinctrl subsystem [ 0.080529] NET: Registered protocol family 16 [ 0.087570] DMA: preallocated 256 KiB pool for atomic coherent allocations [ 0.091747] cpuidle: using governor ladder [ 0.091877] cpuidle: using governor menu [ 0.091935] Remapping and enabling EFI services. [ 0.092255] EFI remap 0x7711d000 => 4000d000 [ 0.092976] EFI remap 0x7fbc8000 => 400d8000 [ 0.093004] EFI remap 0x7fbdc000 => 400fc000 [ 0.093024] EFI remap 0x7fc25000 => 40135000 [ 0.093039] EFI remap 0x04000000 => 40200000 [ 0.093110] EFI remap 0x09010000 => 44200000 [ 0.113384] No ATAGs? [ 0.113803] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4 watchpoint registers. [ 0.113892] hw-breakpoint: maximum watchpoint size is 8 bytes. [ 0.119299] Serial: AMBA PL011 UART driver [ 0.120749] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 52, base_baud = 0) is a PL011 rev1 [ 0.139298] console [ttyAMA0] enabled [ 0.233516] vgaarb: loaded [ 0.239868] SCSI subsystem initialized [ 0.244809] usbcore: registered new interface driver usbfs [ 0.245706] usbcore: registered new interface driver hub [ 0.246613] usbcore: registered new device driver usb [ 0.253095] media: Linux media interface: v0.10 [ 0.253947] Linux video capture interface: v2.00 [ 0.254678] pps_core: LinuxPPS API ver. 1 registered [ 0.255062] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti giometti@linux.it [ 0.255873] PTP clock support registered [ 0.257389] EDAC MC: Ver: 3.0.0 [ 0.265252] Advanced Linux Sound Architecture Driver Initialized. [ 0.282630] Switched to clocksource arch_sys_counter [ 0.332666] NET: Registered protocol family 2 [ 0.341082] TCP established hash table entries: 8192 (order: 3, 32768 bytes) [ 0.342231] TCP bind hash table entries: 8192 (order: 4, 65536 bytes) [ 0.343018] TCP: Hash tables configured (established 8192 bind 8192) [ 0.344267] UDP hash table entries: 512 (order: 2, 16384 bytes) [ 0.344795] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes) [ 0.347463] NET: Registered protocol family 1 [ 0.352278] RPC: Registered named UNIX socket transport module. [ 0.352676] RPC: Registered udp transport module. [ 0.352960] RPC: Registered tcp transport module. [ 0.353230] RPC: Registered tcp NFSv4.1 backchannel transport module. [ 0.373238] futex hash table entries: 256 (order: 2, 16384 bytes) [ 0.420563] squashfs: version 4.0 (2009/01/31) Phillip Lougher [ 0.425328] NFS: Registering the id_resolver key type [ 0.426767] Key type id_resolver registered [ 0.427035] Key type id_legacy registered [ 0.427812] ntfs: driver 2.1.32 [Flags: R/O]. [ 0.438395] bounce: pool size: 64 pages [ 0.439517] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 248) [ 0.440019] io scheduler noop registered [ 0.440277] io scheduler deadline registered [ 0.441080] io scheduler cfq registered (default) [ 0.463911] PCI host bridge /pcie@10000000 ranges: [ 0.464611] IO 0x3eff0000..0x3effffff -> 0x00000000 [ 0.465131] MEM 0x10000000..0x3efeffff -> 0x10000000 [ 0.468035] pci-host-generic 3f000000.pcie: PCI host bridge to bus 0000:00 [ 0.468773] pci_bus 0000:00: root bus resource [bus 00-0f] [ 0.469124] pci_bus 0000:00: root bus resource [io 0x0000-0xffff] [ 0.469463] pci_bus 0000:00: root bus resource [mem 0x10000000-0x3efeffff] [ 0.472424] pci 0000:00:00.0: IOMMU is currently not supported for PCI [ 0.474335] PCI: bus0: Fast back to back transfers disabled [ 0.632744] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled [ 0.636742] SuperH (H)SCI(F) driver initialized [ 0.638086] msm_serial: driver initialized [ 0.639063] STMicroelectronics ASC driver initialized [ 0.641720] [drm] Initialized drm 1.1.0 20060810 [ 0.659210] loop: module loaded [ 0.674291] vda: vda1 vda2 [ 0.689435] CAN device driver interface [ 0.691055] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.2.15-k [ 0.691280] igb: Copyright (c) 2007-2014 Intel Corporation. [ 0.694341] pegasus: v0.9.3 (2013/04/25), Pegasus/Pegasus II USB Ethernet driver [ 0.694655] usbcore: registered new interface driver pegasus [ 0.694987] usbcore: registered new interface driver asix [ 0.695260] usbcore: registered new interface driver ax88179_178a [ 0.695545] usbcore: registered new interface driver cdc_ether [ 0.695860] usbcore: registered new interface driver smsc75xx [ 0.696165] usbcore: registered new interface driver smsc95xx [ 0.696563] usbcore: registered new interface driver net1080 [ 0.696881] usbcore: registered new interface driver cdc_subset [ 0.697179] usbcore: registered new interface driver zaurus [ 0.697529] usbcore: registered new interface driver cdc_ncm [ 0.701287] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver [ 0.701882] ehci-pci: EHCI PCI platform driver [ 0.702229] ehci-platform: EHCI generic platform driver [ 0.702671] ehci-omap: OMAP-EHCI Host Controller driver [ 0.703101] ehci-orion: EHCI orion driver [ 0.703434] SPEAr-ehci: EHCI SPEAr driver [ 0.703766] ehci-st: EHCI STMicroelectronics driver [ 0.704114] ehci-exynos: EHCI EXYNOS driver [ 0.704610] tegra-ehci: Tegra EHCI driver [ 0.705215] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver [ 0.705714] ohci-pci: OHCI PCI platform driver [ 0.706201] ohci-platform: OHCI generic platform driver [ 0.706838] ohci-omap3: OHCI OMAP3 driver [ 0.707191] SPEAr-ohci: OHCI SPEAr driver [ 0.707534] ohci-st: OHCI STMicroelectronics driver [ 0.708011] usbcore: registered new interface driver usb-storage [ 0.710715] mousedev: PS/2 mouse device common for all mice [ 0.715348] pgd = ee0a8000 [ 0.715530] [40135fa8] *pgd=6eff0801, *pte=7fc2565f, *ppte=7fc2545f [ 0.717378] pgd = c0204000 [ 0.717569] [40135fa8] *pgd=00000000 [ 0.718496] pgd = ee0a8000 [ 0.718662] [40135fa8] *pgd=6eff0801, *pte=7fc2565f, *ppte=7fc2545f [ 0.719064] pgd = c0204000 [ 0.719229] [40135fa8] *pgd=00000000 [ 0.720592] rtc-efi rtc-efi: rtc core: registered rtc-efi as rtc0 [ 0.725523] i2c /dev entries driver [ 0.730382] usbcore: registered new interface driver uvcvideo [ 0.730574] USB Video Class driver (1.1.1) [ 0.730722] gspca_main: v2.14.0 registered [ 0.738884] sdhci: Secure Digital Host Controller Interface driver [ 0.739077] sdhci: Copyright(c) Pierre Ossman [ 0.741055] Synopsys Designware Multimedia Card Interface Driver [ 0.742779] sdhci-pltfm: SDHCI platform and OF driver helper [ 0.745151] ledtrig-cpu: registered to indicate activity on CPUs [ 0.745887] usbcore: registered new interface driver usbhid [ 0.746056] usbhid: USB HID core driver [ 0.752141] usbcore: registered new interface driver snd-usb-audio [ 0.757717] NET: Registered protocol family 17 [ 0.757962] can: controller area network core (rev 20120528 abi 9) [ 0.758407] NET: Registered protocol family 29 [ 0.758597] can: raw protocol (rev 20120528) [ 0.758793] can: broadcast manager protocol (rev 20120528 t) [ 0.759009] can: netlink gateway (rev 20130117) max_hops=1 [ 0.760727] Key type dns_resolver registered [ 0.761485] ThumbEE CPU extension supported. [ 0.761804] Registering SWP/SWPB emulation handler [ 0.769849] pgd = ee0a8000 [ 0.770038] [40135fa8] *pgd=6eff0801, *pte=7fc2565f, *ppte=7fc2545f [ 0.771889] rtc-efi rtc-efi: setting system clock to 2015-04-29 11:29:27 UTC (1430306967) [ 0.773564] ALSA device list: [ 0.773716] No soundcards found. [ 0.776119] uart-pl011 9000000.pl011: no DMA platform data [ 0.780952] EXT4-fs (vda2): couldn't mount as ext3 due to feature incompatibilities [ 0.782820] EXT4-fs (vda2): couldn't mount as ext2 due to feature incompatibilities [ 0.785690] EXT4-fs (vda2): INFO: recovery required on readonly filesystem [ 0.785914] EXT4-fs (vda2): write access will be enabled during recovery [ 0.818639] EXT4-fs (vda2): recovery complete [ 0.823286] EXT4-fs (vda2): mounted filesystem with ordered data mode. Opts: (null) [ 0.824828] VFS: Mounted root (ext4 filesystem) readonly on device 254:2. [ 0.829458] devtmpfs: mounted [ 0.850536] Freeing unused kernel memory: 828K (c0d95000 - c0e64000) INIT: version 2.88 booting Error opening /dev/fb0: No such file or directory Starting udev [ 2.201880] udevd[65]: starting version 182 [ 9.722297] FAT-fs (vda1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck. [ 9.968052] EXT4-fs (vda2): re-mounted. Opts: data=ordered [ 10.346751] random: dd urandom read with 9 bits of entropy available Populating dev cache [ 13.790965] pgd = ee0a8000 [ 13.791126] [40135fa8] *pgd=6eff0801, *pte=00000000, *ppte=00000000 [ 13.791581] Unable to handle kernel paging request at virtual address 40135fa8 [ 13.791820] pgd = ed170000 [ 13.791925] [40135fa8] *pgd=00000000 [ 13.792281] Internal error: Oops: 7 [#1] SMP ARM [ 13.792553] Modules linked in: [ 13.792879] CPU: 0 PID: 308 Comm: hwclock Not tainted 4.1.0-rc1-00008-gb6fc321f4ca5-dirty #124 [ 13.793144] Hardware name: Generic DT based system [ 13.793355] task: ed03d300 ti: ed252000 task.ti: ed252000 [ 13.793607] PC is at virt_efi_get_time+0x4c/0x88 [ 13.793794] LR is at broadcast_tlb_a15_erratum+0x1c/0x3c [ 13.793985] pc : [<c0851a58>] lr : [<c0216ca8>] psr: 60060093 [ 13.793985] sp : ed253e68 ip : 00000000 fp : 00000000 [ 13.794328] r10: 00000000 r9 : ed252000 r8 : ed253e84 [ 13.794508] r7 : 40060013 r6 : ed253e90 r5 : c0f9be08 r4 : c0f9be04 [ 13.794718] r3 : 40135f90 r2 : 00000000 r1 : ed253e84 r0 : ed253e90 [ 13.794982] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user [ 13.795221] Control: 10c5387d Table: 6e0a806a DAC: 00000015 [ 13.795425] Process hwclock (pid: 308, stack limit = 0xed252220) [ 13.795646] Stack: (0xed253e68 to 0xed254000) [ 13.795903] 3e60: ed253ed4 c0f0a158 ee389800 bed83c34 c0ab1b20 c07baadc [ 13.796169] 3e80: ee002d00 ed08ef00 ed253ef0 c03154a4 ed253eac ed0c3080 00000000 ed0c9a50 [ 13.796426] 3ea0: ed253fb0 ee389994 ed253ed4 c07b6d68 ee389800 ee389998 ed253ed4 c07b6dbc [ 13.796684] 3ec0: ee389800 80247009 ee389998 c07b8048 ed0e0000 00000000 00000000 00000000 [ 13.796937] 3ee0: 00000000 00000000 00000000 00000000 00000000 00000000 b37f1802 00000004 [ 13.797191] 3f00: ed14e540 000a7cf8 00000000 ed8256e8 ee38abe8 00000101 00000004 0000004a [ 13.797446] 3f20: ee38abe8 bed83c34 ed08ef00 00000003 bed83c34 c0318944 00000000 00000000 [ 13.797701] 3f40: 00020000 00000003 00000003 ed08ef00 ed0e0000 ee38abe8 ed08ef08 00000020 [ 13.797953] 3f60: 00000000 c03075fc 00000000 00000000 00000000 ed08ef00 00000003 ed08ef00 [ 13.798209] 3f80: 80247009 bed83c34 ed252000 c0318b6c 00094500 00000003 00000002 00000036 [ 13.798464] 3fa0: c0210784 c0210600 00094500 00000003 00000003 80247009 bed83c34 00094500 [ 13.798720] 3fc0: 00094500 00000003 00000002 00000036 00000000 00000000 000a7cf8 00000000 [ 13.798984] 3fe0: b6e2e8a0 bed83bfc 00019538 b6e2e8ac 60060010 00000003 6f7fd821 6f7fdc21 [ 13.799397] [<c0851a58>] (virt_efi_get_time) from [<c07baadc>] (efi_read_time+0x28/0x74) [ 13.799709] [<c07baadc>] (efi_read_time) from [<c07b6d68>] (__rtc_read_time.isra.3+0x48/0x6c) [ 13.799986] [<c07b6d68>] (__rtc_read_time.isra.3) from [<c07b6dbc>] (rtc_read_time+0x30/0x44) [ 13.800237] [<c07b6dbc>] (rtc_read_time) from [<c07b8048>] (rtc_dev_ioctl+0x328/0x5b0) [ 13.800481] [<c07b8048>] (rtc_dev_ioctl) from [<c0318944>] (do_vfs_ioctl+0x418/0x60c) [ 13.800755] [<c0318944>] (do_vfs_ioctl) from [<c0318b6c>] (SyS_ioctl+0x34/0x5c) [ 13.800991] [<c0318b6c>] (SyS_ioctl) from [<c0210600>] (ret_fast_syscall+0x0/0x34) [ 13.801370] Code: e1a01008 e5933000 e1a00006 e5933038 (e5933018) [ 13.801783] ---[ end trace d5b7f564e6da9c28 ]---
On Wed, Apr 29, 2015 at 4:48 AM, Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
Hi all,
Yesterday and this morning, I had a go at bringing the 32-bit ARM EFI support in line with the current arm64 upstream code. I have reshuffled a lot of Roy's code, mainly so that the remaining delta against the ARM tree is as small as possible, and keeps out of existing early init code as much as possible. I have not reused any of the existing 32-bit runtime services code. I did not use the early ioremap support but instead refactored the existing init code lightly so that we can use two adjacent fixmap slots instead.
This mostly works, but there are (at least) two issues that need resolving:
- LPAE support builds but doesn't run
- the EFI page tables are clobbered at some point in the execution -> note in the log below that the RTC efi is read successfully once, but later on (when invoked by hwclock from userland), the page table entries have been cleared
I don't intend to burn a lot of time on this but it may be worthwile to run this on a model (with better watchpoint support) to figure out what is going on with the page tables. Not today though ....
Very nice! I will try to take a look at this. The 32 bit stub has been something that has been on my nagging todo list for a while..
Roy
Ard Biesheuvel (7): efi: avoid initialized .data in the EFI stub efi: build efi_config_init() only if CONFIG_EARLY_IOREMAP arm64/efi: split off EFI init and runtime code for reuse by 32-bit ARM arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM ARM: move fixmap init before memblock init and use static allocation ARM: split off core code from create_mapping() for EFI reuse ARM: add UEFI support
Roy Franz (1): ARM: add strstr and strncmp to compressed string.c
arch/arm/Kconfig | 19 ++ arch/arm/boot/compressed/.gitignore | 2 + arch/arm/boot/compressed/Makefile | 18 +- arch/arm/boot/compressed/efi-header.S | 141 +++++++++++ arch/arm/boot/compressed/efi-stub.c | 89 +++++++ arch/arm/boot/compressed/head.S | 66 ++++- arch/arm/boot/compressed/string.c | 43 ++++ arch/arm/include/asm/efi.h | 135 ++++++++++ arch/arm/include/asm/fixmap.h | 4 + arch/arm/include/asm/mach/map.h | 1 + arch/arm/kernel/setup.c | 5 + arch/arm/mm/mmu.c | 68 +++-- arch/arm64/include/asm/efi.h | 29 +++ arch/arm64/kernel/efi.c | 330 +------------------------ drivers/firmware/efi/Makefile | 4 + drivers/firmware/efi/arm-init.c | 212 ++++++++++++++++ drivers/firmware/efi/arm-runtime.c | 142 +++++++++++ drivers/firmware/efi/efi.c | 2 + drivers/firmware/efi/libstub/efi-stub-helper.c | 8 +- 19 files changed, 952 insertions(+), 366 deletions(-) create mode 100644 arch/arm/boot/compressed/efi-header.S create mode 100644 arch/arm/boot/compressed/efi-stub.c create mode 100644 arch/arm/include/asm/efi.h create mode 100644 drivers/firmware/efi/arm-init.c create mode 100644 drivers/firmware/efi/arm-runtime.c
--
EFI stub: Booting Linux Kernel... EFI stub: Using DTB from configuration table EFI stub: Exiting boot services and installing virtual address map... [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 4.1.0-rc1-00008-gb6fc321f4ca5-dirty (ard@ards-macbook-pro) (gcc version 4.9.1 20140529 (prerelease) (crosstool-NG linaro-1.13.1-4.9-2014.06 - Linaro GCC 4.9-2014.06) ) #124 SMP Wed Apr 29 13:28:54 CEST 2015 [ 0.000000] CPU: ARMv7 Processor [412fc0f1] revision 1 (ARMv7), cr=10c5387d [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache [ 0.000000] Machine model: linux,dummy-virt [ 0.000000] earlycon: no match for ttyAMA0 [ 0.000000] efi: Getting EFI parameters from FDT: [ 0.000000] efi: System Table: 0x000000007fc25010 [ 0.000000] efi: MemMap Address: 0x0000000076b20010 [ 0.000000] efi: MemMap Size: 0x00000540 [ 0.000000] efi: MemMap Desc. Size: 0x00000030 [ 0.000000] efi: MemMap Desc. Version: 0x00000001 [ 0.000000] Processing EFI memory map: [ 0.000000] 0x000040000000-0x0000425f5fff [Loader Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x0000425f6000-0x000047fedfff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x000047fee000-0x000047ffffff [Loader Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000048000000-0x000076b1ffff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x000076b20000-0x000076b21fff [Loader Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000076b22000-0x000077116fff [Loader Code | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000077117000-0x00007711afff [Reserved | | | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007711b000-0x00007711cfff [ACPI Reclaim Memory| | | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007711d000-0x0000771dffff [Runtime Data |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x0000771e0000-0x000079e6bfff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x000079e6c000-0x00007a59cfff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007a59d000-0x00007a63afff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007a63b000-0x00007babbfff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007babc000-0x00007bb0afff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007bb0b000-0x00007bb19fff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007bb1a000-0x00007bb1efff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007bb1f000-0x00007c01ffff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007c020000-0x00007fabefff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fabf000-0x00007fbc7fff [Boot Code | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fbc8000-0x00007fbdbfff [Runtime Code |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007fbdc000-0x00007fc0dfff [Runtime Data |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007fc0e000-0x00007fc0ffff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fc10000-0x00007fc23fff [Conventional Memory| | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fc24000-0x00007fc24fff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x00007fc25000-0x00007fc25fff [Runtime Data |RUN| | | | |WB|WT|WC|UC]* [ 0.000000] 0x00007fc26000-0x00007fffffff [Boot Data | | | | | |WB|WT|WC|UC] [ 0.000000] 0x000004000000-0x000007ffffff [Memory Mapped I/O |RUN| | | | | | | |UC] [ 0.000000] 0x000009010000-0x000009010fff [Memory Mapped I/O |RUN| | | | | | | |UC] [ 0.000000] EFI v2.40 by EDK II [ 0.000000] efi: [ 0.000000] cma: Reserved 64 MiB at 0x7b800000 [ 0.000000] Memory policy: Data cache writealloc [ 0.000000] psci: probing for conduit method from DT. [ 0.000000] psci: PSCIv0.2 detected in firmware. [ 0.000000] psci: Using standard PSCI v0.2 function IDs [ 0.000000] PERCPU: Embedded 12 pages/cpu @eefe3000 s16960 r8192 d24000 u49152 [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260624 [ 0.000000] Kernel command line: console=ttyAMA0 uefi_debug root=/dev/vda2 [ 0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes) [ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes) [ 0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes) [ 0.000000] Memory: 958824K/1048576K available (8132K kernel code, 967K rwdata, 3688K rodata, 828K init, 321K bss, 24216K reserved, 65536K cma-reserved, 203708K highmem) [ 0.000000] Virtual kernel memory layout: [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB) [ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB) [ 0.000000] vmalloc : 0xf0000000 - 0xff000000 ( 240 MB) [ 0.000000] lowmem : 0xc0000000 - 0xef800000 ( 760 MB) [ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB) [ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB) [ 0.000000] .text : 0xc0208000 - 0xc0d940e0 (11825 kB) [ 0.000000] .init : 0xc0d95000 - 0xc0e64000 ( 828 kB) [ 0.000000] .data : 0xc0e64000 - 0xc0f55f40 ( 968 kB) [ 0.000000] .bss : 0xc0f58000 - 0xc0fa86d8 ( 322 kB) [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 [ 0.000000] Hierarchical RCU implementation. [ 0.000000] Additional per-CPU info printed with stalls. [ 0.000000] RCU restricting CPUs from NR_CPUS=16 to nr_cpu_ids=1. [ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1 [ 0.000000] NR_IRQS:16 nr_irqs:16 16 [ 0.000000] Architected cp15 timer(s) running at 62.50MHz (virt). [ 0.000000] clocksource arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns [ 0.000118] sched_clock: 56 bits at 62MHz, resolution 16ns, wraps every 4398046511096ns [ 0.000226] Switching to timer-based delay loop, resolution 16ns [ 0.002942] Console: colour dummy device 80x30 [ 0.003398] Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=312500) [ 0.003518] pid_max: default: 32768 minimum: 301 [ 0.006917] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes) [ 0.006955] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes) [ 0.014326] CPU: Testing write buffer coherency: ok [ 0.020134] /cpus/cpu@0 missing clock-frequency property [ 0.020346] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 [ 0.020922] Setting up static identity map for 0x40209000 - 0x40209098 [ 0.028361] Brought up 1 CPUs [ 0.028426] SMP: Total of 1 processors activated (125.00 BogoMIPS). [ 0.028474] CPU: All CPU(s) started in SVC mode. [ 0.036288] devtmpfs: initialized [ 0.040769] VFP support v0.3: implementor 41 architecture 4 part 30 variant f rev 0 [ 0.053306] clocksource jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 9556302231375000 ns [ 0.064590] pinctrl core: initialized pinctrl subsystem [ 0.080529] NET: Registered protocol family 16 [ 0.087570] DMA: preallocated 256 KiB pool for atomic coherent allocations [ 0.091747] cpuidle: using governor ladder [ 0.091877] cpuidle: using governor menu [ 0.091935] Remapping and enabling EFI services. [ 0.092255] EFI remap 0x7711d000 => 4000d000 [ 0.092976] EFI remap 0x7fbc8000 => 400d8000 [ 0.093004] EFI remap 0x7fbdc000 => 400fc000 [ 0.093024] EFI remap 0x7fc25000 => 40135000 [ 0.093039] EFI remap 0x04000000 => 40200000 [ 0.093110] EFI remap 0x09010000 => 44200000 [ 0.113384] No ATAGs? [ 0.113803] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4 watchpoint registers. [ 0.113892] hw-breakpoint: maximum watchpoint size is 8 bytes. [ 0.119299] Serial: AMBA PL011 UART driver [ 0.120749] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 52, base_baud = 0) is a PL011 rev1 [ 0.139298] console [ttyAMA0] enabled [ 0.233516] vgaarb: loaded [ 0.239868] SCSI subsystem initialized [ 0.244809] usbcore: registered new interface driver usbfs [ 0.245706] usbcore: registered new interface driver hub [ 0.246613] usbcore: registered new device driver usb [ 0.253095] media: Linux media interface: v0.10 [ 0.253947] Linux video capture interface: v2.00 [ 0.254678] pps_core: LinuxPPS API ver. 1 registered [ 0.255062] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti giometti@linux.it [ 0.255873] PTP clock support registered [ 0.257389] EDAC MC: Ver: 3.0.0 [ 0.265252] Advanced Linux Sound Architecture Driver Initialized. [ 0.282630] Switched to clocksource arch_sys_counter [ 0.332666] NET: Registered protocol family 2 [ 0.341082] TCP established hash table entries: 8192 (order: 3, 32768 bytes) [ 0.342231] TCP bind hash table entries: 8192 (order: 4, 65536 bytes) [ 0.343018] TCP: Hash tables configured (established 8192 bind 8192) [ 0.344267] UDP hash table entries: 512 (order: 2, 16384 bytes) [ 0.344795] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes) [ 0.347463] NET: Registered protocol family 1 [ 0.352278] RPC: Registered named UNIX socket transport module. [ 0.352676] RPC: Registered udp transport module. [ 0.352960] RPC: Registered tcp transport module. [ 0.353230] RPC: Registered tcp NFSv4.1 backchannel transport module. [ 0.373238] futex hash table entries: 256 (order: 2, 16384 bytes) [ 0.420563] squashfs: version 4.0 (2009/01/31) Phillip Lougher [ 0.425328] NFS: Registering the id_resolver key type [ 0.426767] Key type id_resolver registered [ 0.427035] Key type id_legacy registered [ 0.427812] ntfs: driver 2.1.32 [Flags: R/O]. [ 0.438395] bounce: pool size: 64 pages [ 0.439517] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 248) [ 0.440019] io scheduler noop registered [ 0.440277] io scheduler deadline registered [ 0.441080] io scheduler cfq registered (default) [ 0.463911] PCI host bridge /pcie@10000000 ranges: [ 0.464611] IO 0x3eff0000..0x3effffff -> 0x00000000 [ 0.465131] MEM 0x10000000..0x3efeffff -> 0x10000000 [ 0.468035] pci-host-generic 3f000000.pcie: PCI host bridge to bus 0000:00 [ 0.468773] pci_bus 0000:00: root bus resource [bus 00-0f] [ 0.469124] pci_bus 0000:00: root bus resource [io 0x0000-0xffff] [ 0.469463] pci_bus 0000:00: root bus resource [mem 0x10000000-0x3efeffff] [ 0.472424] pci 0000:00:00.0: IOMMU is currently not supported for PCI [ 0.474335] PCI: bus0: Fast back to back transfers disabled [ 0.632744] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled [ 0.636742] SuperH (H)SCI(F) driver initialized [ 0.638086] msm_serial: driver initialized [ 0.639063] STMicroelectronics ASC driver initialized [ 0.641720] [drm] Initialized drm 1.1.0 20060810 [ 0.659210] loop: module loaded [ 0.674291] vda: vda1 vda2 [ 0.689435] CAN device driver interface [ 0.691055] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.2.15-k [ 0.691280] igb: Copyright (c) 2007-2014 Intel Corporation. [ 0.694341] pegasus: v0.9.3 (2013/04/25), Pegasus/Pegasus II USB Ethernet driver [ 0.694655] usbcore: registered new interface driver pegasus [ 0.694987] usbcore: registered new interface driver asix [ 0.695260] usbcore: registered new interface driver ax88179_178a [ 0.695545] usbcore: registered new interface driver cdc_ether [ 0.695860] usbcore: registered new interface driver smsc75xx [ 0.696165] usbcore: registered new interface driver smsc95xx [ 0.696563] usbcore: registered new interface driver net1080 [ 0.696881] usbcore: registered new interface driver cdc_subset [ 0.697179] usbcore: registered new interface driver zaurus [ 0.697529] usbcore: registered new interface driver cdc_ncm [ 0.701287] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver [ 0.701882] ehci-pci: EHCI PCI platform driver [ 0.702229] ehci-platform: EHCI generic platform driver [ 0.702671] ehci-omap: OMAP-EHCI Host Controller driver [ 0.703101] ehci-orion: EHCI orion driver [ 0.703434] SPEAr-ehci: EHCI SPEAr driver [ 0.703766] ehci-st: EHCI STMicroelectronics driver [ 0.704114] ehci-exynos: EHCI EXYNOS driver [ 0.704610] tegra-ehci: Tegra EHCI driver [ 0.705215] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver [ 0.705714] ohci-pci: OHCI PCI platform driver [ 0.706201] ohci-platform: OHCI generic platform driver [ 0.706838] ohci-omap3: OHCI OMAP3 driver [ 0.707191] SPEAr-ohci: OHCI SPEAr driver [ 0.707534] ohci-st: OHCI STMicroelectronics driver [ 0.708011] usbcore: registered new interface driver usb-storage [ 0.710715] mousedev: PS/2 mouse device common for all mice [ 0.715348] pgd = ee0a8000 [ 0.715530] [40135fa8] *pgd=6eff0801, *pte=7fc2565f, *ppte=7fc2545f [ 0.717378] pgd = c0204000 [ 0.717569] [40135fa8] *pgd=00000000 [ 0.718496] pgd = ee0a8000 [ 0.718662] [40135fa8] *pgd=6eff0801, *pte=7fc2565f, *ppte=7fc2545f [ 0.719064] pgd = c0204000 [ 0.719229] [40135fa8] *pgd=00000000 [ 0.720592] rtc-efi rtc-efi: rtc core: registered rtc-efi as rtc0 [ 0.725523] i2c /dev entries driver [ 0.730382] usbcore: registered new interface driver uvcvideo [ 0.730574] USB Video Class driver (1.1.1) [ 0.730722] gspca_main: v2.14.0 registered [ 0.738884] sdhci: Secure Digital Host Controller Interface driver [ 0.739077] sdhci: Copyright(c) Pierre Ossman [ 0.741055] Synopsys Designware Multimedia Card Interface Driver [ 0.742779] sdhci-pltfm: SDHCI platform and OF driver helper [ 0.745151] ledtrig-cpu: registered to indicate activity on CPUs [ 0.745887] usbcore: registered new interface driver usbhid [ 0.746056] usbhid: USB HID core driver [ 0.752141] usbcore: registered new interface driver snd-usb-audio [ 0.757717] NET: Registered protocol family 17 [ 0.757962] can: controller area network core (rev 20120528 abi 9) [ 0.758407] NET: Registered protocol family 29 [ 0.758597] can: raw protocol (rev 20120528) [ 0.758793] can: broadcast manager protocol (rev 20120528 t) [ 0.759009] can: netlink gateway (rev 20130117) max_hops=1 [ 0.760727] Key type dns_resolver registered [ 0.761485] ThumbEE CPU extension supported. [ 0.761804] Registering SWP/SWPB emulation handler [ 0.769849] pgd = ee0a8000 [ 0.770038] [40135fa8] *pgd=6eff0801, *pte=7fc2565f, *ppte=7fc2545f [ 0.771889] rtc-efi rtc-efi: setting system clock to 2015-04-29 11:29:27 UTC (1430306967) [ 0.773564] ALSA device list: [ 0.773716] No soundcards found. [ 0.776119] uart-pl011 9000000.pl011: no DMA platform data [ 0.780952] EXT4-fs (vda2): couldn't mount as ext3 due to feature incompatibilities [ 0.782820] EXT4-fs (vda2): couldn't mount as ext2 due to feature incompatibilities [ 0.785690] EXT4-fs (vda2): INFO: recovery required on readonly filesystem [ 0.785914] EXT4-fs (vda2): write access will be enabled during recovery [ 0.818639] EXT4-fs (vda2): recovery complete [ 0.823286] EXT4-fs (vda2): mounted filesystem with ordered data mode. Opts: (null) [ 0.824828] VFS: Mounted root (ext4 filesystem) readonly on device 254:2. [ 0.829458] devtmpfs: mounted [ 0.850536] Freeing unused kernel memory: 828K (c0d95000 - c0e64000) INIT: version 2.88 booting Error opening /dev/fb0: No such file or directory Starting udev [ 2.201880] udevd[65]: starting version 182 [ 9.722297] FAT-fs (vda1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck. [ 9.968052] EXT4-fs (vda2): re-mounted. Opts: data=ordered [ 10.346751] random: dd urandom read with 9 bits of entropy available Populating dev cache [ 13.790965] pgd = ee0a8000 [ 13.791126] [40135fa8] *pgd=6eff0801, *pte=00000000, *ppte=00000000 [ 13.791581] Unable to handle kernel paging request at virtual address 40135fa8 [ 13.791820] pgd = ed170000 [ 13.791925] [40135fa8] *pgd=00000000 [ 13.792281] Internal error: Oops: 7 [#1] SMP ARM [ 13.792553] Modules linked in: [ 13.792879] CPU: 0 PID: 308 Comm: hwclock Not tainted 4.1.0-rc1-00008-gb6fc321f4ca5-dirty #124 [ 13.793144] Hardware name: Generic DT based system [ 13.793355] task: ed03d300 ti: ed252000 task.ti: ed252000 [ 13.793607] PC is at virt_efi_get_time+0x4c/0x88 [ 13.793794] LR is at broadcast_tlb_a15_erratum+0x1c/0x3c [ 13.793985] pc : [<c0851a58>] lr : [<c0216ca8>] psr: 60060093 [ 13.793985] sp : ed253e68 ip : 00000000 fp : 00000000 [ 13.794328] r10: 00000000 r9 : ed252000 r8 : ed253e84 [ 13.794508] r7 : 40060013 r6 : ed253e90 r5 : c0f9be08 r4 : c0f9be04 [ 13.794718] r3 : 40135f90 r2 : 00000000 r1 : ed253e84 r0 : ed253e90 [ 13.794982] Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user [ 13.795221] Control: 10c5387d Table: 6e0a806a DAC: 00000015 [ 13.795425] Process hwclock (pid: 308, stack limit = 0xed252220) [ 13.795646] Stack: (0xed253e68 to 0xed254000) [ 13.795903] 3e60: ed253ed4 c0f0a158 ee389800 bed83c34 c0ab1b20 c07baadc [ 13.796169] 3e80: ee002d00 ed08ef00 ed253ef0 c03154a4 ed253eac ed0c3080 00000000 ed0c9a50 [ 13.796426] 3ea0: ed253fb0 ee389994 ed253ed4 c07b6d68 ee389800 ee389998 ed253ed4 c07b6dbc [ 13.796684] 3ec0: ee389800 80247009 ee389998 c07b8048 ed0e0000 00000000 00000000 00000000 [ 13.796937] 3ee0: 00000000 00000000 00000000 00000000 00000000 00000000 b37f1802 00000004 [ 13.797191] 3f00: ed14e540 000a7cf8 00000000 ed8256e8 ee38abe8 00000101 00000004 0000004a [ 13.797446] 3f20: ee38abe8 bed83c34 ed08ef00 00000003 bed83c34 c0318944 00000000 00000000 [ 13.797701] 3f40: 00020000 00000003 00000003 ed08ef00 ed0e0000 ee38abe8 ed08ef08 00000020 [ 13.797953] 3f60: 00000000 c03075fc 00000000 00000000 00000000 ed08ef00 00000003 ed08ef00 [ 13.798209] 3f80: 80247009 bed83c34 ed252000 c0318b6c 00094500 00000003 00000002 00000036 [ 13.798464] 3fa0: c0210784 c0210600 00094500 00000003 00000003 80247009 bed83c34 00094500 [ 13.798720] 3fc0: 00094500 00000003 00000002 00000036 00000000 00000000 000a7cf8 00000000 [ 13.798984] 3fe0: b6e2e8a0 bed83bfc 00019538 b6e2e8ac 60060010 00000003 6f7fd821 6f7fdc21 [ 13.799397] [<c0851a58>] (virt_efi_get_time) from [<c07baadc>] (efi_read_time+0x28/0x74) [ 13.799709] [<c07baadc>] (efi_read_time) from [<c07b6d68>] (__rtc_read_time.isra.3+0x48/0x6c) [ 13.799986] [<c07b6d68>] (__rtc_read_time.isra.3) from [<c07b6dbc>] (rtc_read_time+0x30/0x44) [ 13.800237] [<c07b6dbc>] (rtc_read_time) from [<c07b8048>] (rtc_dev_ioctl+0x328/0x5b0) [ 13.800481] [<c07b8048>] (rtc_dev_ioctl) from [<c0318944>] (do_vfs_ioctl+0x418/0x60c) [ 13.800755] [<c0318944>] (do_vfs_ioctl) from [<c0318b6c>] (SyS_ioctl+0x34/0x5c) [ 13.800991] [<c0318b6c>] (SyS_ioctl) from [<c0210600>] (ret_fast_syscall+0x0/0x34) [ 13.801370] Code: e1a01008 e5933000 e1a00006 e5933038 (e5933018) [ 13.801783] ---[ end trace d5b7f564e6da9c28 ]---