/*
* Kernel startup entry point.
* ---------------------------
*
* The requirements are:
* MMU = off, D-cache = off, I-cache = on or off,
* x0 = physical address to the FDT blob.
*
* Note that the callee-saved registers are used for storing variables
* that are useful before the MMU is enabled. The allocations are described
* in the entry routines.
*/
__HEAD
#define __HEAD .section ".head.text","ax"
__HEAD는 .head.text 섹션으로 되어 있으며, 해당 섹션은 vmlinux.lds.S에 정의되어 있다.
SECTIONS
{
/*
* XXX: The linker does not define how output sections are
* assigned to input sections when there are multiple statements
* matching the same input section name. There is no documented
* order of matching.
*/
DISCARDS
/DISCARD/ : {
*(.interp .dynamic)
*(.dynsym .dynstr .hash .gnu.hash)
*(.ARM.attributes)
}
. = KIMAGE_VADDR;
.head.text : {
_text = .;
HEAD_TEXT
}
...
따라서 커널의 부팅은 이 head.text 세션부터 시작한다.
__HEAD
/*
* DO NOT MODIFY. Image header expected by Linux boot-loaders.
*/
efi_signature_nop // special NOP to identity as PE/COFF executable
b primary_entry // branch to kernel start, magic
이후 efi_signature_nop 매크로 실행 후, primary_entry 함수로 분기한다.
.macro efi_signature_nop
#ifdef CONFIG_EFI
.L_head:
/*
* This ccmp instruction has no meaningful effect except that
* its opcode forms the magic "MZ" signature required by UEFI.
*/
ccmp x18, #0, #0xd, pl
#else
/*
* Bootloaders may inspect the opcode at the start of the kernel
* image to decide if the kernel is capable of booting via UEFI.
* So put an ordinary NOP here, not the "MZ.." pseudo-nop above.
*/
nop
#endif
.endm
해당 매크로는 EFI 호환성을 위해 커널 이미지 앞에 MZ(magic number)를 붙이는 명령어이다. MZ는 아스키 넘버로 0x4d, 0x5A인데, ccmp 0x18, 0x0, 0xd, pl 은 opcode 변경하게 되면 0xfa405a4d이다. 첫번째 바이트와 두 번째 바이트가 0x4d, 0x5a 이므
로 해당 명령어를 통해 이미지 첫번째와 두번째 바이트에 MZ 값을 써주게 된다.
(https://developer.arm.com/documentation/ddi0602/2021-12/Base-Instructions/CCMP--immediate---Conditional-Compare--immediate--) sf 값은 64 bit일 경우 1이며, imm5는 0, cond는 pl이므로 5이며, Rn은 r18이므로 18이다. 이후 그림에는 생략되었지만 nzcv 항목은 0xd를 써줬다. 그러면 바이너리 코드로 환산해보면, 1111 1010 0100 0000 0101 1010 0100 1101 = 0xfa405a4d 이 된다.