2

In the linux source there are two different head.S files located at:

arch/arm/kernel/head.S

arch/arm/boot/compressed/head.S

What is the puprpose of each one and what is the order of there execution ?

2

I welcome better answers, but my understanding is that it's the kernel startup code (which is architecture-specific) hand-written in assembly (remember, at this point we just have a bare metal CPU and raw access to memory; we can't access complex libraries stored on the file system because we have no file manager yet - it's like asking who created the big bang). Do not confuse this with the boot loader (which loads the boot sector from disk into RAM). I myself had confused them in my earlier answer.

+------+     +--------------------+     +------------------+     +------------------------+
| BIOS | --> | Bootloader (mbr.S) | --> | startup (head.S) | --> | kernel/main.c::kmain() |
+------+     +--------------------+     +------------------+     +------------------------+

enter image description here

At the end of head.S you'll see the line

    call    _C_LABEL(kmain)

which is the entry point to the kernel:

kernel/main.c

I believe head.S is tacked on to the top of the kernel image at compile time. The BIOS knows to execute this block of code because it's at the very beginning and is the root file system of the ram disk.

As for why there is a compressed and uncompressed part, I think it's because the architecture specific assembly portion of the kernel image, no programmer is skilled enough to do compression. Once we can jump to the kmain routine written in C (but compiled into assembly) we have access to a decompression routine which makes the kernel footprint significantly smaller.

enter image description here

http://duartes.org/gustavo/blog/post/kernel-boot-process/


The entry point using assembly

We like to write everything in C, but we cannot avoid a little bit of assembly. We will write a small file in x86 assembly-language that serves as the starting point for our kernel. All our assembly file will do is invoke an external function which we will write in C, and then halt the program flow.

How do we make sure that this assembly code will serve as the starting point of the kernel?

We will use a linker script that links the object files to produce the final kernel executable. (more explained later) In this linker script, we will explicitly specify that we want our binary to be loaded at the address 0x100000. This address, as I have said earlier, is where the kernel is expected to be. Thus, the bootloader will take care of firing the kernel’s entry point.

http://arjunsreedharan.org/post/82710718100/kernel-101-lets-write-a-kernel

  • I just realized .S indicates "aSsembler" – Sridhar Sarnobat Oct 25 '17 at 19:21
  • 1
    Your answer, while a good one, deals with x86. To the OP : make sure, if interested in ARM boot, you filter out the x86-specific bits. The boot process is different when dealing with ARM. – schaiba Oct 30 '17 at 7:03
  • Feel free to edit my post, I'm still trying to learn it myself :) – Sridhar Sarnobat Oct 30 '17 at 7:04
  • 1
    I'll have to do some in-depth digging myself :) What springs to mind is that, for example, ARM does not have protected mode, not in the sense employed by x86. – schaiba Oct 30 '17 at 7:10
  • Ooops, I just realized my answer is for Minix, not Linux. – Sridhar Sarnobat Oct 16 '19 at 0:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.