https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/compressed/Makefile?h=master
Read the contents of the Makefile. Omit the fdt part that you are not interested in.
arch/arm/boot/compressed/Makefile
# SPDX-License-Identifier: GPL-2.0
#
# linux/arch/arm/boot/compressed/Makefile
#
# create a compressed vmlinuz image from the original vmlinux
#
OBJS =
AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
It means to add the option of TEXT_OFFSET when creating head.o.
TEXT_OFFSET $ (TEXT_OFFSET) is defined in arch / arm / Makefile.
arch/arm/Makefile
# Text offset. This list is sorted numerically by address in order to
# provide a means to avoid/resolve conflicts in multi-arch kernels.
textofs-y := 0x00008000
# We don't want the htc bootloader to corrupt kernel during resume
textofs-$(CONFIG_PM_H1940) := 0x00108000
# SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
ifeq ($(CONFIG_ARCH_SA1100),y)
textofs-$(CONFIG_SA1111) := 0x00208000
endif
textofs-$(CONFIG_ARCH_IPQ40XX) := 0x00208000
textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000
textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
textofs-$(CONFIG_ARCH_MESON) := 0x00208000
textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
(Omitted)
TEXT_OFFSET := $(textofs-y)
arch/arm/boot/compressed/Makefile
HEAD = head.o
OBJS += misc.o decompress.o
head.S This is the logic of the compressed Linux Kernel expansion section itself.
Do various things, but call decompress_kernel.
arch/arm/boot/compressed/head.S
/*
* The C runtime environment should now be setup sufficiently.
* Set up some pointers, and start decompressing.
* r4 = kernel execution address
* r7 = architecture ID
* r8 = atags pointer
*/
mov r0, r4
mov r1, sp @ malloc space above stack
add r2, sp, #0x10000 @ 64k max
mov r3, r7
bl decompress_kernel
misc.S The main body of decompress_kernel () is described.
Actually, do_decompress () is called from this.
arch/arm/boot/compressed/misc.c
void
decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
unsigned long free_mem_ptr_end_p,
int arch_id)
{
int ret;
output_data = (unsigned char *)output_start;
free_mem_ptr = free_mem_ptr_p;
free_mem_end_ptr = free_mem_ptr_end_p;
__machine_arch_type = arch_id;
arch_decomp_setup();
putstr("Uncompressing Linux...");
ret = do_decompress(input_data, input_data_end - input_data,
output_data, error);
if (ret)
error("decompressor returned an error");
else
putstr(" done, booting the kernel.\n");
}
decompress.S
The part that calls __decompress () of each compression module to decompress it.
arch/arm/boot/compressed/decompress.c
#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
#ifdef CONFIG_KERNEL_LZO
#include "../../../../lib/decompress_unlzo.c"
#endif
#ifdef CONFIG_KERNEL_LZMA
#include "../../../../lib/decompress_unlzma.c"
#endif
#ifdef CONFIG_KERNEL_XZ
#define memmove memmove
#define memcpy memcpy
#include "../../../../lib/decompress_unxz.c"
#endif
#ifdef CONFIG_KERNEL_LZ4
#include "../../../../lib/decompress_unlz4.c"
#endif
int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
{
return __decompress(input, len, NULL, NULL, output, 0, NULL, error);
}
For example, for lz4:
lib/decompress_unlz4.c
#ifdef PREBOOT
STATIC int INIT __decompress(unsigned char *buf, long in_len,
long (*fill)(void*, unsigned long),
long (*flush)(void*, unsigned long),
unsigned char *output, long out_len,
long *posp,
void (*error)(char *x)
)
{
return unlz4(buf, in_len - 4, fill, flush, output, posp, error);
}
#endif
arch/arm/boot/compressed/Makefile
ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y)
OBJS += debug.o
endif
FONTC = $(srctree)/lib/fonts/font_acorn_8x8.c
I think font_acorn_8x8.c isn't used except for acorn ...
DEBUG_UNCOMPRESS
DEBUG_UNCOMPRESS is defined in KConfig.debug.
This option concerns the output of the decompressor on a multiplatform kernel. Usually, decompressor is not good for multiplatform kernels. Because I don't know where to send the decompressor output.
Once this option is set, it will be reused by the DEBUG_LL output means.
So you can debug it.
arch/arm/Kconfig.debug
config DEBUG_UNCOMPRESS
bool "Enable decompressor debugging via DEBUG_LL output"
depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG || ARM_SINGLE_ARMV7M
depends on DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \
(!DEBUG_TEGRA_UART || !ZBOOT_ROM) && \
!DEBUG_BRCMSTB_UART
help
This option influences the normal decompressor output for
multiplatform kernels. Normally, multiplatform kernels disable
decompressor output because it is not possible to know where to
send the decompressor output.
When this option is set, the selected DEBUG_LL output method
will be re-used for normal decompressor output on multiplatform
kernels.
debug.S
debug.s is used for the implementation of putc (). If CONFIG_DEBUG_SEMIHOSTING is disabled, adduart / waituart / senduart / busyuart will output the characters to the console.
arm/boot/compressed/debug.S
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/linkage.h>
#include <asm/assembler.h>
#ifndef CONFIG_DEBUG_SEMIHOSTING
#include CONFIG_DEBUG_LL_INCLUDE
ENTRY(putc)
addruart r1, r2, r3
waituart r3, r1
senduart r0, r1
busyuart r3, r1
mov pc, lr
ENDPROC(putc)
#else
(Omitted)
string library
string.c is a subset of memcpu / memmove / strlen / strnlen. Estimated to be built in so that the decompressor can move independently when it moves.
arch/arm/boot/compressed/Makefile
# string library code (-Os is enforced to keep it much smaller)
OBJS += string.o
CFLAGS_string.o := -Os
string.c
The content is an implementation of a simplified version of the function defined in string.h.
arch/arm/boot/compressed/string.c
void *memcpy(void *__dest, __const void *__src, size_t __n)
{
int i = 0;
unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
for (i = __n >> 3; i > 0; i--) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
if (__n & 1 << 2) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
if (__n & 1 << 1) {
*d++ = *s++;
*d++ = *s++;
}
if (__n & 1)
*d++ = *s++;
return __dest;
}
VIRT_EXT
arch/arm/boot/compressed/Makefile
ifeq ($(CONFIG_ARM_VIRT_EXT),y)
OBJS += hyp-stub.o
endif
ARM_VIRT_EXT
arch/arm/mm/Kconfig
config ARM_VIRT_EXT
bool
default y if CPU_V7
help
Enable the kernel to make use of the ARM Virtualization
Extensions to install hypervisors without run-time firmware
assistance.
A compliant bootloader is required in order to make maximum
use of this feature. Refer to Documentation/arm/booting.rst for
details.
GCOV/KCOV
The debugging function has been disabled.
arch/arm/boot/compressed/Makefile
GCOV_PROFILE := n
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
KCOV_INSTRUMENT := n
This area is model-dependent, so it is omitted.
arch/arm/boot/compressed/Makefile
#
# Architecture dependencies
#
ifeq ($(CONFIG_ARCH_ACORN),y)
OBJS += ll_char_wr.o font.o
endif
<Omitted>
--The decompressor implementation is PIC (address independent implementation). --When running Decompressor on RAM, do not specify ZTEXTADDR. --If you want to run Decompressor with ROM / Flash, you need to specify it.
arch/arm/boot/compressed/Makefile
#
# We now have a PIC decompressor implementation. Decompressors running
# from RAM should not define ZTEXTADDR. Decompressors running directly
# from ROM or Flash must define ZTEXTADDR (preferably via the config)
# FIXME: Previous assignment to ztextaddr-y is lost here. See SHARK
ifeq ($(CONFIG_ZBOOT_ROM),y)
ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT)
ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS)
else
ZTEXTADDR := 0
ZBSSADDR := ALIGN(8)
endif
CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)"
Specify the compression format specified by KConfig.
arch/arm/boot/compressed/Makefile
compress-$(CONFIG_KERNEL_GZIP) = gzip
compress-$(CONFIG_KERNEL_LZO) = lzo
compress-$(CONFIG_KERNEL_LZMA) = lzma
compress-$(CONFIG_KERNEL_XZ) = xzkern
compress-$(CONFIG_KERNEL_LZ4) = lz4
arch/arm/boot/compressed/Makefile
# Borrowed libfdt files for the ATAG compatibility mode
<Omitted>
arch/arm/boot/compressed/Makefile
targets := vmlinux vmlinux.lds piggy_data piggy.o \
lib1funcs.o ashldi3.o bswapsdi2.o \
head.o $(OBJS)
clean-files += piggy_data lib1funcs.S ashldi3.S bswapsdi2.S \
$(libfdt) $(libfdt_hdrs) hyp-stub.S
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
ifeq ($(CONFIG_FUNCTION_TRACER),y)
ORIG_CFLAGS := $(KBUILD_CFLAGS)
KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
endif
It seems that it is still early to use stack-protector-strong.
arch/arm/boot/compressed/Makefile
# -fstack-protector-strong triggers protection checks in this code,
# but it is being used too early to link to meaningful stack_chk logic.
nossp-flags-$(CONFIG_CC_HAS_STACKPROTECTOR_NONE) := -fno-stack-protector
CFLAGS_atags_to_fdt.o := $(nossp-flags-y)
<Omitted>
It seems that it is calculated using between \ _ \ _ bss_start and \ _ \ _ bss_stop. That is communicated as an option to the Linker.
arch/arm/boot/compressed/Makefile
# Supply kernel BSS size to the decompressor via a linker symbol.
KBSS_SZ = $(shell echo $$(($$($(NM) $(obj)/../../../../vmlinux | \
sed -n -e 's/^\([^ ]*\) [AB] __bss_start$$/-0x\1/p' \
-e 's/^\([^ ]*\) [AB] __bss_stop$$/+0x\1/p') )) )
LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
# Supply ZRELADDR to the decompressor via a linker symbol.
ifneq ($(CONFIG_AUTO_ZRELADDR),y)
LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
endif
--Big Endian support --No unresolved references --Temporary removal of local symbols --- The T option is for the linker script, isn't it?
arch/arm/boot/compressed/Makefile
ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
LDFLAGS_vmlinux += --be8
endif
# Report unresolved symbol references
LDFLAGS_vmlinux += --no-undefined
# Delete all temporary local symbols
LDFLAGS_vmlinux += -X
# Next argument is a linker script
LDFLAGS_vmlinux += -T
Deployment of code prepared to mess with non-existent functions.
arch/arm/boot/compressed/Makefile
# For __aeabi_uidivmod
lib1funcs = $(obj)/lib1funcs.o
$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
$(call cmd,shipped)
# For __aeabi_llsl
ashldi3 = $(obj)/ashldi3.o
$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S
$(call cmd,shipped)
# For __bswapsi2, __bswapdi2
bswapsdi2 = $(obj)/bswapsdi2.o
$(obj)/bswapsdi2.S: $(srctree)/arch/$(SRCARCH)/lib/bswapsdi2.S
$(call cmd,shipped)
lib1funcs.S It seems to be a division optimization routine.
https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html
The following functions etc. are included.
Runtime Function: int __divsi3 (int a, int b) Runtime Function: long __divdi3 (long a, long b) Runtime Function: long long __divti3 (long long a, long long b) These functions return the quotient of the signed division of a and b.
arch/arm/lib/lib1funcs.S
/*
* linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
*
* Author: Nicolas Pitre <[email protected]>
* - contributed to gcc-3.4 on Sep 30, 2003
* - adapted for the Linux kernel on Oct 2, 2003
*/
ashldi3.S/bswapsdi2.S https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html
There is a description of what the function is around here.
Runtime Function: int __ashlsi3 (int a, int b) Runtime Function: long __ashldi3 (long a, int b) Runtime Function: long long __ashlti3 (long long a, int b) These functions return the result of shifting a left by b bits.
Runtime Function: int32_t __bswapsi2 (int32_t a) Runtime Function: int64_t __bswapdi2 (int64_t a) These functions return the a byteswapped.
"The following symbols must not be in the local / private scope," he said.
arch/arm/boot/compressed/Makefile
# We need to prevent any GOTOFF relocs being used with references
# to symbols in the .bss section since we cannot relocate them
# independently from the rest at run time. This can be achieved by
# ensuring that no private .bss symbols exist, as global symbols
# always have a GOT entry which is what we need.
# The .data section is already discarded by the linker script so no need
# to bother about it here.
check_for_bad_syms = \
bad_syms=$$($(NM) $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \
[ -z "$$bad_syms" ] || \
( echo "following symbols must have non local/private scope:" >&2; \
echo "$$bad_syms" >&2; false )
If ZRELADDR is not set and AUTO_ZRELADDR is not set, will I get angry?
arch/arm/boot/compressed/Makefile
check_for_multiple_zreladdr = \
if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \
echo 'multiple zreladdrs: $(ZRELADDR)'; \
echo 'This needs CONFIG_AUTO_ZRELADDR to be set'; \
false; \
fi
(Omitted without interest)
arch/arm/boot/compressed/Makefile
efi-obj-$(CONFIG_EFI_STUB) := $(objtree)/drivers/firmware/efi/libstub/lib.a
arch/arm/boot/compressed/Makefile
$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \
$(bswapsdi2) $(efi-obj-y) FORCE
@$(check_for_multiple_zreladdr)
$(call if_changed,ld)
@$(check_for_bad_syms)
compress-y contains the compression program specified in the form compress- $ (CONFIG_KERNEL_XXXX) = CMD
. Use this to convert Image to piggy_data
arch/arm/boot/compressed/Makefile
$(obj)/piggy_data: $(obj)/../Image FORCE
$(call if_changed,$(compress-y))
$(obj)/piggy.o: $(obj)/piggy_data
piggy.S
I have imported piggy_data as binary data.
arch/arm/boot/compressed/piggy.S
/* SPDX-License-Identifier: GPL-2.0 */
.section .piggydata, "a"
.globl input_data
input_data:
.incbin "arch/arm/boot/compressed/piggy_data"
.globl input_data_end
input_data_end:
arch/arm/boot/compressed/Makefile
CFLAGS_font.o := -Dstatic=
$(obj)/font.c: $(FONTC)
$(call cmd,shipped)
AFLAGS_hyp-stub.o := -Wa,-march=armv7-a
$(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S
$(call cmd,shipped)