This linker voodoo clones the Earlycon drivers from the kernel into the decompressor, selecting everything in the designated ELF sections (.text.earlycon.info and .init.earlycon.info). My linker script skills are quite primitive so the code is manually relocated by the decompressor using information left by the kernel linker script. So we have some constrains for the Earlycom drivers: - no global or static variables (mind the strings) - no dynamic memory allocation (but the decompressor reserves 1K of RAM for the driver) - no function calls outside of .text.earlycon.info and the restricted namespace provided by struct earlycon_drv - calls to normal functions in .text.earlycon.info must go through manual relocation (see RELOC_FUN() later on), inline functions do not need this extra step - drivers shall not bloat, all this stuff is stored uncompressed together with the decompressor and friends Signed-off-by: Domenico Andreoli --- arch/arm/boot/Makefile | 6 +++++- arch/arm/boot/compressed/vmlinux.lds.in | 16 +++++++++++++++- arch/arm/kernel/vmlinux.lds.S | 10 ++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) Index: b/arch/arm/boot/Makefile =================================================================== --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -48,7 +48,11 @@ $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) @echo ' Kernel: $@ is ready' -$(obj)/compressed/vmlinux: $(obj)/Image FORCE +OBJCOPYFLAGS_earlycon.o = -O elf32-littlearm -j .init.earlycon.info -j .text.earlycon.info -j .ARM.attributes +$(obj)/compressed/earlycon.o: vmlinux FORCE + $(call if_changed,objcopy) + +$(obj)/compressed/vmlinux: $(obj)/Image $(obj)/compressed/earlycon.o FORCE $(Q)$(MAKE) $(build)=$(obj)/compressed $@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE Index: b/arch/arm/kernel/vmlinux.lds.S =================================================================== --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -111,6 +111,10 @@ SECTIONS *(.got) /* Global offset table */ ARM_CPU_KEEP(PROC_INFO) } + .text.earlycon.info : { + __earlycon_text_begin = .; + *(.earlycon.info.text) + } RO_DATA(PAGE_SIZE) @@ -150,6 +154,12 @@ SECTIONS *(.arch.info.init) __arch_info_end = .; } + .init.earlycon.info : { + LONG(__earlycon_text_begin) + __earlycon_desc_begin = .; + *(.earlycon.info.desc) + __earlycon_desc_end = .; + } .init.tagtable : { __tagtable_begin = .; *(.taglist.init) Index: b/arch/arm/boot/compressed/vmlinux.lds.in =================================================================== --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -30,6 +30,9 @@ SECTIONS _start = .; *(.start) *(.text) + . = ALIGN(4); + __earlycon_text_begin = .; + *(.text.earlycon.info) *(.text.*) *(.fixup) *(.gnu.warning) @@ -38,6 +41,11 @@ SECTIONS } .rodata : { *(.rodata) + . = ALIGN(4); + __earlycon_text_base = .; + __earlycon_desc_begin = . + 4; + *(.init.earlycon.info) + __earlycon_desc_end = .; *(.rodata.*) } .piggydata : { @@ -59,7 +67,13 @@ SECTIONS . = BSS_START; __bss_start = .; - .bss : { *(.bss) } + .bss : { + *(.bss) + . = ALIGN(4); + __earlycon_drvdata_begin = .; + . = . + 1K; + __earlycon_drvdata_end = .; + } _end = .; . = ALIGN(8); /* the stack must be 64-bit aligned */